This is a revision to a patch I posted earlier this year, adding python language bindings for liburjtag.
- tested with python 2.7 and 3.1 on fedora 14 - code formatting much closer to the style of the rest of urjtag (but claiming perfection) - some non-python-related routines factored out into files urj_helpers.[ch]. these routines provide cleaner access to the liburjtag library, and might be considered for inclusion in the core. - includes additions by Jonathan Stroud, which provide bindings for more methods, including those needed for burning (some?) flash devices. Steve [email protected] --- urjtag/Makefile.am | 3 +- urjtag/bindings/Makefile.am | 30 + urjtag/bindings/python/Makefile.am | 36 ++ urjtag/bindings/python/chain.c | 901 ++++++++++++++++++++++++++++++ urjtag/bindings/python/pycompat23.h | 38 ++ urjtag/bindings/python/setup.py | 12 + urjtag/bindings/python/t_srst.py | 49 ++ urjtag/bindings/python/t_urjtag_chain.py | 81 +++ urjtag/bindings/python/urj_helpers.c | 161 ++++++ urjtag/bindings/python/urj_helpers.h | 34 ++ urjtag/configure.ac | 25 + 11 files changed, 1369 insertions(+), 1 deletions(-) create mode 100644 urjtag/bindings/Makefile.am create mode 100644 urjtag/bindings/python/Makefile.am create mode 100644 urjtag/bindings/python/chain.c create mode 100644 urjtag/bindings/python/pycompat23.h create mode 100644 urjtag/bindings/python/setup.py create mode 100644 urjtag/bindings/python/t_srst.py create mode 100644 urjtag/bindings/python/t_urjtag_chain.py create mode 100644 urjtag/bindings/python/urj_helpers.c create mode 100644 urjtag/bindings/python/urj_helpers.h diff --git a/urjtag/Makefile.am b/urjtag/Makefile.am index 7998707..e7c0200 100644 --- a/urjtag/Makefile.am +++ b/urjtag/Makefile.am @@ -28,7 +28,8 @@ SUBDIRS = \ include/urjtag \ data \ src \ - po + po \ + bindings if ENABLE_APPS SUBDIRS += \ diff --git a/urjtag/bindings/Makefile.am b/urjtag/bindings/Makefile.am new file mode 100644 index 0000000..363d334 --- /dev/null +++ b/urjtag/bindings/Makefile.am @@ -0,0 +1,30 @@ +# +# $Id$ +# +# Copyright (C) 2002,2011 ETC s.r.o. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You 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. +# +# Written by Steve Tell <[email protected]> 2011 +# + +SUBDIRS = $(PYTHON_SUBDIR) + +if BIND_PYTHON +PYTHON_SUBDIR=python +else +PYTHON_SUBDIR= +endif diff --git a/urjtag/bindings/python/Makefile.am b/urjtag/bindings/python/Makefile.am new file mode 100644 index 0000000..87f64c2 --- /dev/null +++ b/urjtag/bindings/python/Makefile.am @@ -0,0 +1,36 @@ +# +# $Id$ +# +# Copyright (C) 2002,2011 ETC s.r.o. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You 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. +# +# Written by Steve Tell <[email protected]> 2011 +# + +EXTRA_DIST = setup.py chain.c pycompat23.h t_urjtag_chain.py + +all-local: build + +build: chain.c + -{ $(PYTHON) setup.py build && touch build; } || { $(RM) -r build; exit 1; } + +install-data-local: + -$(PYTHON) setup.py install --prefix=$(DESTDIR)$(prefix) + +clean-local: + -$(RM) -r build + diff --git a/urjtag/bindings/python/chain.c b/urjtag/bindings/python/chain.c new file mode 100644 index 0000000..1911daa --- /dev/null +++ b/urjtag/bindings/python/chain.c @@ -0,0 +1,901 @@ +/* + * $Id$ + * + * Copyright (C) 2011 + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You 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. + * + * Python bindings for urjtag intially written by Steve Tell. + * Additional methods by Jonathan Stroud. + * + */ +#include <Python.h> +#include "structmember.h" +#include "pycompat23.h" + +#include <urjtag.h> +#include <chain.h> +#include <cmd.h> +#include <assert.h> +#include <sys/mman.h> + +#include "urj_helpers.h" + +/* missing from urjtag headers */ +extern int urj_cmd_get_number (const char *s, long unsigned *i); +extern int urj_cmd_test_cable (urj_chain_t * chain); + +static PyObject *UrjtagError; + +typedef struct { + PyObject_HEAD urj_chain_t * urchain; +} Chain; + +static void +Chain_dealloc (Chain * self) +{ + //printf ("in Chain_dealloc urc=%p\n", self); + urj_tap_chain_free (self->urchain); + Py_TYPE(self)->tp_free ((PyObject *) self); +} + +static PyObject * +Chain_new (PyTypeObject * type, PyObject * args, PyObject * kwds) +{ + Chain *self; + + self = (Chain *) type->tp_alloc (type, 0); + if (self != NULL) + { + self->urchain = urj_tap_chain_alloc (); + if (self->urchain == NULL) + { + Py_DECREF (self); + return PyErr_NoMemory (); + } + self->urchain->main_part = 0; + } + return (PyObject *) self; +} + + +/* methods */ + +static PyObject * +Chain_cable (Chain * self, PyObject * args) +{ + char *cable_params[5] = { NULL, NULL, NULL, NULL, NULL }; + urj_chain_t *urc = self->urchain; + + assert (self->urchain == g_tstptr); + if (urc == NULL) + { + PyErr_SetString (PyExc_RuntimeError, "null chain"); + return NULL; + } + if (!PyArg_ParseTuple (args, "s|sss", + &cable_params[0], + &cable_params[1], + &cable_params[2], &cable_params[3])) + { + return NULL; + } + if (urj_chain_cable (urc, cable_params) != URJ_STATUS_OK) + { + if (urj_error_get ()) + { + PyErr_SetString (UrjtagError, urj_error_describe ()); + urj_error_reset (); + } + else + { + PyErr_SetString (UrjtagError, + "unknown urjtag error in cable()"); + + } + return NULL; + } + //printf ("Chain_cable: cable=%p %s\n", urc->cable, cable_params[0]); + return Py_BuildValue (""); // None +} + +static PyObject * +Chain_disconnect (Chain * self) +{ + urj_chain_t *urc = self->urchain; + if (urc == NULL) + { + PyErr_SetString (PyExc_RuntimeError, "null chain"); + return NULL; + } + urj_tap_chain_disconnect (urc); + return Py_BuildValue (""); // None +} + +static PyObject * +Chain_test_cable (Chain * self) +{ + urj_chain_t *urc = self->urchain; + if (urc == NULL) + { + PyErr_SetString (PyExc_RuntimeError, "null chain"); + return NULL; + } + if (urj_cmd_test_cable (urc) != URJ_STATUS_OK) + { + + if (urj_error_get ()) + { + PyErr_SetString (UrjtagError, urj_error_describe ()); + urj_error_reset (); + } + else + { + PyErr_SetString (UrjtagError, + "unknown urjtag error in test_cable()"); + } + return NULL; + } + return Py_BuildValue (""); // None +} + +static PyObject * +Chain_tap_detect (Chain * self) +{ + urj_chain_t *urc = self->urchain; + if (urc == NULL) + { + PyErr_SetString (PyExc_RuntimeError, "null chain"); + return NULL; + } + // printf("_tap_detect: urchain=%p cable=%p\n", urc, urc->cable); + + if (urj_tap_detect (urc) != URJ_STATUS_OK) + { + if (urj_error_get ()) + { + PyErr_SetString (UrjtagError, urj_error_describe ()); + urj_error_reset (); + } + else + { + PyErr_SetString (UrjtagError, + "unknown urjtag error in detect()"); + } + return NULL; + } + return Py_BuildValue (""); // None +} + +static PyObject * +Chain_len (Chain * self, PyObject * args) +{ + urj_chain_t *urc = self->urchain; + if (!urc) + { + PyErr_SetString (PyExc_RuntimeError, "null chain"); + return NULL; + } + if (urc->parts == NULL) + { + PyErr_SetString (PyExc_RuntimeError, + "detect not called on this chain"); + return NULL; + } + + return Py_BuildValue ("i", urc->parts->len); +} + +static PyObject * +Chain_partid (Chain * self, PyObject * args) +{ + urj_chain_t *urc = self->urchain; + int partno; + if (!PyArg_ParseTuple (args, "i", &partno)) + return NULL; + + if (!urc) + { + PyErr_SetString (PyExc_RuntimeError, "null chain"); + return NULL; + } + if (urc->parts == NULL) + { + PyErr_SetString (PyExc_RuntimeError, + "detect not called on this chain"); + return NULL; + } + if (partno >= urc->parts->len) + { + PyErr_SetString (PyExc_RuntimeError, "part number out of range"); + return NULL; + } + else + { + urj_part_t *p; + uint32_t id; + + p = urc->parts->parts[partno]; + id = urj_tap_register_get_value (p->id); + return Py_BuildValue ("i", id); + } +} + +static PyObject * +Chain_reset (Chain * self) +{ + urj_chain_t *urc = self->urchain; + if (!urc) + { + PyErr_SetString (PyExc_RuntimeError, "null chain"); + return NULL; + } + + if (urj_tap_reset_bypass (urc) != URJ_STATUS_OK) + { + if (urj_error_get ()) + { + PyErr_SetString (UrjtagError, urj_error_describe ()); + urj_error_reset (); + } + else + { + PyErr_SetString (UrjtagError, + "unknown urjtag error in dereset_bypass()"); + } + return NULL; + } + urj_tap_chain_flush (urc); + return Py_BuildValue (""); +} + + +static PyObject * +Chain_set_trst (Chain * self, PyObject * args) +{ + urj_chain_t *urc = self->urchain; + int trstval; + if (!PyArg_ParseTuple (args, "i", &trstval)) + return NULL; + if (!urc) + { + PyErr_SetString (PyExc_RuntimeError, "null chain"); + return NULL; + } + urj_tap_chain_set_trst (urc, trstval); + return Py_BuildValue (""); // None +} + +static PyObject * +Chain_get_trst (Chain * self) +{ + int trstval; + urj_chain_t *urc = self->urchain; + if (!urc) + { + PyErr_SetString (PyExc_RuntimeError, "null chain"); + return NULL; + } + + trstval = urj_tap_chain_get_trst (urc); + return Py_BuildValue ("i", trstval); +} + +static PyObject * +Chain_set_pod_signal (Chain * self, PyObject * args) +{ + urj_chain_t *urc = self->urchain; + uint32_t mask, + val, + oldval; + if (!PyArg_ParseTuple (args, "ii", &mask, &val)) + return NULL; + if (!urc) + { + PyErr_SetString (PyExc_RuntimeError, "null chain"); + return NULL; + } + oldval = urj_tap_chain_set_pod_signal (urc, mask, val); + return Py_BuildValue ("i", oldval); // None +} + +static PyObject * +Chain_get_pod_signal (Chain * self, PyObject * args) +{ + uint32_t sig; + uint32_t val; + urj_chain_t *urc = self->urchain; + if (!PyArg_ParseTuple (args, "i", &sig)) + return NULL; + if (!urc) + { + PyErr_SetString (PyExc_RuntimeError, "null chain"); + return NULL; + } + + val = urj_tap_chain_get_pod_signal (urc, sig); + // printf("_get_pod_signal(sig=%x result=%x)\n", sig, val); + return Py_BuildValue ("i", val); +} + +static PyObject * +Chain_set_frequency (Chain * self, PyObject * args) +{ + urj_chain_t *urc = self->urchain; + uint32_t freq; + if (!PyArg_ParseTuple (args, "i", &freq)) + return NULL; + if (!urc) + { + PyErr_SetString (PyExc_RuntimeError, "null chain"); + return NULL; + } + urj_tap_cable_set_frequency (urc->cable, freq); + return Py_BuildValue (""); // None +} + +static PyObject * +Chain_get_frequency (Chain * self, PyObject * args) +{ + urj_chain_t *urc = self->urchain; + unsigned long freq; + freq = urj_tap_cable_get_frequency (urc->cable); + + return Py_BuildValue ("i", (uint32_t) freq); +} + +// set instruction for the active part +static PyObject * +Chain_set_instruction (Chain * self, PyObject * args) +{ + char *instname; + urj_part_t *part; + urj_chain_t *urc = self->urchain; + if (!PyArg_ParseTuple (args, "s", &instname)) + return NULL; + if (!urc) + { + PyErr_SetString (PyExc_RuntimeError, "null chain"); + return NULL; + } + part = urj_tap_chain_active_part (urc); + if (part == NULL) + { + PyErr_SetString (UrjtagError, "No active part on chain"); + return NULL; + } + urj_part_set_instruction (part, instname); + return Py_BuildValue (""); // None +} + +static PyObject * +Chain_shift_ir (Chain * self) +{ + urj_chain_t *urc = self->urchain; + if (!urc) + { + PyErr_SetString (PyExc_RuntimeError, "null chain"); + return NULL; + } + if (urj_cmd_test_cable (urc) != URJ_STATUS_OK) + { + PyErr_SetString (UrjtagError, "cable() has not been called"); + return NULL; + } + + if (urj_tap_chain_shift_instructions (urc) != URJ_STATUS_OK) + { + if (urj_error_get ()) + { + PyErr_SetString (UrjtagError, urj_error_describe ()); + urj_error_reset (); + } + else + { + PyErr_SetString (UrjtagError, + "unknown urjtag error in deshift_ir"); + } + return NULL; + } + return Py_BuildValue (""); // None +} + +static PyObject * +Chain_shift_dr (Chain * self) +{ + urj_chain_t *urc = self->urchain; + if (!urc) + { + PyErr_SetString (PyExc_RuntimeError, "null chain"); + return NULL; + } + if (urj_cmd_test_cable (urc) != URJ_STATUS_OK) + { + PyErr_SetString (UrjtagError, "cable() has not been called"); + return NULL; + } + // TODO: need a way to not capture the TDO output + if (urj_tap_chain_shift_data_registers (urc, 1) != URJ_STATUS_OK) + { + if (urj_error_get ()) + { + PyErr_SetString (UrjtagError, urj_error_describe ()); + urj_error_reset (); + } + else + { + PyErr_SetString (UrjtagError, + "unknown urjtag error in deshift_dr"); + } + return NULL; + } + return Py_BuildValue (""); // None +} + +static PyObject * +Chain_get_dr (Chain * self, int in) +{ + urj_chain_t *urc = self->urchain; + urj_part_t *part; + urj_tap_register_t *r; + urj_data_register_t *dr; + urj_part_instruction_t *active_ir; + + if (!urc) + { + PyErr_SetString (PyExc_RuntimeError, "null chain"); + return NULL; + } + if (urj_cmd_test_cable (urc) != URJ_STATUS_OK) + { + PyErr_SetString (UrjtagError, "cable() has not been called"); + return NULL; + } + part = urj_tap_chain_active_part (urc); + if (part == NULL) + { + PyErr_SetString (UrjtagError, "no active part in chain"); + return NULL; + } + active_ir = part->active_instruction; + if (active_ir == NULL) + { + PyErr_SetString (UrjtagError, "part without active instruction"); + return NULL; + } + dr = active_ir->data_register; + if (dr == NULL) + { + PyErr_SetString (UrjtagError, + "instruction without active data register"); + return NULL; + } + + if (in) + r = dr->in; // input buffer for next shift_dr + else + r = dr->out; // recently captured+scanned-out values + // TODO: input buffer + // for now: use ascii bitstrings + return Py_BuildValue ("s", urj_tap_register_get_string (r)); +} + +static PyObject * +Chain_get_dr_out (Chain * self) +{ + return Chain_get_dr (self, 0); +} + +static PyObject * +Chain_get_dr_in (Chain * self) +{ + return Chain_get_dr (self, 1); +} + +static PyObject * +Chain_run_svf (Chain * self, PyObject * args) +{ + urj_chain_t *urc = self->urchain; + char *fname; + int stop = 0; + unsigned long ref_freq = 0; + FILE *svf_file; + + if (!PyArg_ParseTuple (args, "s|iI", &fname, &stop, &ref_freq)) + return NULL; + if (!urc) + { + PyErr_SetString (PyExc_RuntimeError, "null chain"); + return NULL; + } + svf_file = fopen (fname, "rb"); + if (!svf_file) + { + PyErr_SetString (PyExc_RuntimeError, "error opening svf file"); // TODO: + // fix + // error + // type + return NULL; + } + if (urj_svf_run (urc, svf_file, stop, ref_freq) != URJ_STATUS_OK) + { + if (urj_error_get ()) + { + PyErr_SetString (UrjtagError, urj_error_describe ()); + urj_error_reset (); + } + else + { + PyErr_SetString (UrjtagError, + "unknown urjtag error in desvf_run"); + } + return NULL; + } + fclose (svf_file); + return Py_BuildValue (""); // None +} + +static PyObject * +Chain_addpart(Chain* self, PyObject *args) +{ + urj_chain_t *urc = self->urchain; + long unsigned len; + + if(!PyArg_ParseTuple(args, "i", &len)) + return NULL; + + if (urj_cmd_test_cable (urc) != URJ_STATUS_OK) + return NULL; + + if (urj_tap_manual_add (urc, len) == -1) + return NULL; + + // @@@@ RFHH this cannot be + if (urc->parts == NULL) + return NULL; + + // @@@@ RFHH this cannot be + if (urc->parts->len == 0) + { + urj_part_parts_free (urc->parts); + self->urchain->parts = NULL; + return NULL; + } + + urj_part_parts_set_instruction (urc->parts, "BYPASS"); + urj_tap_chain_shift_instructions (urc); + return Py_BuildValue(""); // None +} + +static PyObject * +Chain_setpart (Chain * self, PyObject * args) +{ + urj_chain_t *urc = self->urchain; + int part; + if(!PyArg_ParseTuple(args, "i", &part)) + return NULL; + if(!urc) { + PyErr_SetString(PyExc_RuntimeError, "null chain"); + return NULL; + } + urc->active_part = part; + return Py_BuildValue(""); // None +} + +static PyObject * +Chain_initbus (Chain * self, PyObject * args) +{ + char *bus_params[5] = {NULL,NULL,NULL,NULL,NULL}; + urj_chain_t *urc = self->urchain; + + assert(self->urchain == g_tstptr); + if (urc == NULL) { + PyErr_SetString(PyExc_RuntimeError, "null chain"); + return NULL; + } + if(!PyArg_ParseTuple(args, "s|sss", + &bus_params[0], + &bus_params[1], + &bus_params[2], + &bus_params[3])) { + return NULL; + } + return Py_BuildValue("i", urj_initbus(urc, bus_params)); +} + +static PyObject * +Chain_detectflash (Chain * self, PyObject * args) +{ + urj_chain_t *urc = self->urchain; + int adr; + if(!PyArg_ParseTuple(args, "i", &adr)) + return NULL; + if(!urc) { + PyErr_SetString(PyExc_RuntimeError, "null chain"); + return NULL; + } + + if (!urj_bus) + { + urj_error_set (URJ_ERROR_ILLEGAL_STATE, "Bus missing"); + return NULL; + } + + return Py_BuildValue("i", urj_flash_detectflash (URJ_LOG_LEVEL_NORMAL, urj_bus, adr)); +} + +static PyObject * +Chain_peek (Chain * self, PyObject * args) +{ + long unsigned adr; + uint32_t val; + urj_bus_area_t area; + + if(!PyArg_ParseTuple(args, "i", &adr)) + return NULL; + + if (!urj_bus) + { + urj_error_set (URJ_ERROR_ILLEGAL_STATE, "Bus missing"); + return NULL; + } + if (!urj_bus->driver) + { + urj_error_set (URJ_ERROR_ILLEGAL_STATE, "Bus driver missing"); + return NULL; + } + + URJ_BUS_PREPARE (urj_bus); + URJ_BUS_AREA (urj_bus, adr, &area); + val = URJ_BUS_READ (urj_bus, adr); + + switch (area.width) + { + case 8: + val &= 0xff; + break; + case 16: + val &= 0xffff; + break; + default: + break; + } + return Py_BuildValue("i", val); // None +} + +static PyObject * +Chain_poke (Chain * self, PyObject * args) +{ + long unsigned adr, val; + urj_bus_area_t area; + + if(!PyArg_ParseTuple(args, "ii", &adr, &val)) + return NULL; + + if (!urj_bus) + { + urj_error_set (URJ_ERROR_ILLEGAL_STATE, "Bus missing"); + return NULL; + } + if (!urj_bus->driver) + { + urj_error_set (URJ_ERROR_ILLEGAL_STATE, "Bus driver missing"); + return NULL; + } + + URJ_BUS_PREPARE (urj_bus); + + URJ_BUS_AREA (urj_bus, adr, &area); + URJ_BUS_WRITE (urj_bus, adr, val); + return Py_BuildValue(""); // None +} + +static PyObject * +Chain_flashmem (Chain * self, PyObject * args) +{ + int msbin; + int noverify = 0; + long unsigned adr = 0; + FILE *f; + char *params[2] = {NULL,NULL}; + int r; + + if (!urj_bus) + { + urj_error_set (URJ_ERROR_ILLEGAL_STATE, "Bus driver missing"); + return NULL; + } + + if(!PyArg_ParseTuple(args, "ss|i", ¶ms[0], ¶ms[1], &noverify)) + return NULL; + + msbin = strcasecmp ("msbin", params[0]) == 0; + if (!msbin && urj_cmd_get_number (params[0], &adr) != URJ_STATUS_OK) + return NULL; + + f = fopen (params[1], "rb"); + if (!f) + { + urj_error_IO_set ("Unable to open file `%s'", params[2]); + return NULL; + } + //printf("msbin = %d, file = %s, noverify = %d\n", msbin, params[1], noverify); + + if (msbin) + r = urj_flashmsbin (urj_bus, f, noverify); + else + r = urj_flashmem (urj_bus, f, adr, noverify); + + fclose (f); + return Py_BuildValue("i", r); // None +} + +static PyMethodDef Chain_methods[] = { + {"cable", (PyCFunction) Chain_cable, METH_VARARGS, + "Connect to the jtag hardware cable of the specified name and type."}, + {"test_cable", (PyCFunction) Chain_test_cable, METH_NOARGS, + "check that the jtag cable is connected to a valid chain"}, + {"disconnect", (PyCFunction) Chain_disconnect, METH_NOARGS, + "Disconnect from the jtag hardware cable"}, + {"tap_detect", (PyCFunction) Chain_tap_detect, METH_NOARGS, + "Identify the chips on the chain"}, + {"len", (PyCFunction) Chain_len, METH_NOARGS, + "Return the length of the TAP chain"}, + {"reset", (PyCFunction) Chain_reset, METH_NOARGS, + "Perform jtag reset using TMS"}, + {"partid", (PyCFunction) Chain_partid, METH_VARARGS, + "Return the IDCODE for the indicated part number in the chain"}, + {"set_trst", (PyCFunction) Chain_set_trst, METH_VARARGS, + "set the TRST output of the cable"}, + {"get_trst", (PyCFunction) Chain_get_trst, METH_NOARGS, + "get the current value of the TRST output of the cable"}, + {"set_pod_signal", (PyCFunction) Chain_set_pod_signal, METH_VARARGS, + "set an auxiliary pod signal"}, + {"get_pod_signal", (PyCFunction) Chain_get_pod_signal, METH_VARARGS, + "get the current value of an auxiliary pod signal"}, + {"set_frequency", (PyCFunction) Chain_set_frequency, METH_VARARGS, + "Change the TCK frequency to be at most the specified value in Hz"}, + {"get_frequency", (PyCFunction) Chain_get_frequency, METH_NOARGS, + "get the current TCK frequency"}, + {"set_instruction", (PyCFunction) Chain_set_instruction, METH_VARARGS, + "Set values in the instruction register holding buffer"}, + {"shift_ir", (PyCFunction) Chain_shift_ir, METH_NOARGS, + "scan values through the instruction register"}, + {"shift_dr", (PyCFunction) Chain_shift_dr, METH_NOARGS, + "scan values through the data register"}, + {"get_dr_in", (PyCFunction) Chain_get_dr_in, METH_NOARGS, + "get bits that will be scanned in on next shiftdr"}, + {"get_dr_out", (PyCFunction) Chain_get_dr_out, METH_NOARGS, + "retrieve values scanned out from the data registers"}, + {"run_svf", (PyCFunction) Chain_run_svf, METH_VARARGS, + "Play a named SVF file; optionally setting stop-on-mismatch and runtest frequency"}, + {"addpart", (PyCFunction)Chain_addpart, METH_VARARGS, + "manually adds parts on the JTAG chain"}, + {"part", (PyCFunction)Chain_setpart, METH_VARARGS, + "change active part for current JTAG chain"}, + {"initbus", (PyCFunction)Chain_initbus, METH_VARARGS, + "initialize bus driver for active part"}, + {"detectflash", (PyCFunction)Chain_detectflash, METH_VARARGS, + "Detect parameters of flash chips attached to a part"}, + {"peek", (PyCFunction)Chain_peek, METH_VARARGS, + "read a single word"}, + {"poke", (PyCFunction)Chain_poke, METH_VARARGS, + "write a single word"}, + {"flashmem", (PyCFunction)Chain_flashmem, METH_VARARGS, + "burn flash memory with data from a file"}, + {NULL} /* Sentinel */ +}; + +static PyTypeObject ChainType = { +// PyObject_HEAD_INIT (NULL) 0, /* ob_size */ + PyVarObject_HEAD_INIT(NULL, 0) + "urjtag.chain", /* tp_name */ + sizeof (Chain), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor) Chain_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + "JTAG chain objects", /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + Chain_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + Chain_new, /* tp_new */ +}; + +/************************************************************************ + * module methods that are not part of any type + */ + +static PyObject * +urjtag_loglevel (PyObject * self, PyObject * args) +{ + int loglevel; // TODO: accept string and map to the + // enum. + if (!PyArg_ParseTuple (args, "i", &loglevel)) + return NULL; + urj_log_state.level = loglevel; + return Py_BuildValue (""); // None +} + +static PyMethodDef module_methods[] = { + {"loglevel", urjtag_loglevel, METH_VARARGS, + "Set log level of the urjtag library"}, + {NULL} /* Sentinel */ +}; + +static struct PyModuleDef chain_moduledef = { + PyModuleDef_HEAD_INIT, + "urjtag", + "Python extension module for urjtag", + -1, + module_methods, +}; + +MODINIT_DECL(urjtag) +{ + PyObject *m; + + if (PyType_Ready (&ChainType) < 0) + return MODINIT_ERROR_VAL; + + m = PyModule_Create(&chain_moduledef); + + if (m == NULL) + return MODINIT_ERROR_VAL; + + UrjtagError = PyErr_NewException ("urjtag.error", NULL, NULL); + Py_INCREF (UrjtagError); + PyModule_AddObject (m, "error", UrjtagError); + + + Py_INCREF (&ChainType); + PyModule_AddObject (m, "chain", (PyObject *) & ChainType); + + return MODINIT_SUCCESS_VAL(m); +} + +/* Local Variables: */ +/* mode:c */ +/* comment-column:0 */ +/* c-basic-offset:4 */ +/* space-before-funcall:t */ +/* End: */ diff --git a/urjtag/bindings/python/pycompat23.h b/urjtag/bindings/python/pycompat23.h new file mode 100644 index 0000000..35f322f --- /dev/null +++ b/urjtag/bindings/python/pycompat23.h @@ -0,0 +1,38 @@ +/* + * some compatibility macros for python 2 / python 3 + * by Steve Tell + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + */ + +#if PY_MAJOR_VERSION >= 3 + +#define MODINIT_ERROR_VAL NULL +#define MODINIT_SUCCESS_VAL(val) val +#define MODINIT_DECL(name) PyMODINIT_FUNC PyInit_##name(void) + +#else /* assume python 2 */ + +#ifndef PyMODINIT_FUNC +#define PyMODINIT_FUNC void +#endif + +#define MODINIT_ERROR_VAL +#define MODINIT_SUCCESS_VAL(val) +#define MODINIT_DECL(name) PyMODINIT_FUNC init##name(void) + +struct PyModuleDef { + int dc1; + const char *name; + const char *doc; + int dc2; + PyMethodDef *methods; +}; +#define PyModuleDef_HEAD_INIT 0 +#define PyModule_Create(dp) Py_InitModule3((dp)->name, (dp)->methods, (dp)->doc) + +#endif diff --git a/urjtag/bindings/python/setup.py b/urjtag/bindings/python/setup.py new file mode 100644 index 0000000..8848af4 --- /dev/null +++ b/urjtag/bindings/python/setup.py @@ -0,0 +1,12 @@ +# python extension setup script for urjtag + +from distutils.core import setup, Extension +setup(name="urjtag", + version="1.0", + description="urJtag Python Bindings", + ext_modules=[ + Extension("urjtag", ["chain.c", "urj_helpers.c"], + include_dirs=['../../include/urjtag'], + library_dirs=['../../src/.libs'], + libraries=['urjtag']) + ]) diff --git a/urjtag/bindings/python/t_srst.py b/urjtag/bindings/python/t_srst.py new file mode 100644 index 0000000..5f86950 --- /dev/null +++ b/urjtag/bindings/python/t_srst.py @@ -0,0 +1,49 @@ +#!/usr/bin/python + +# works in both python 2 and 3 +def printf(format, *args): + """Format args with the first argument as format string, and print. + If the format is not a string, it is converted to one with str. + You must use printf('%s', x) instead of printf(x) if x might + contain % or backslash characters.""" + sys.stdout.write(str(format) % args) + +import sys +sys.path.append( "." ) + +import urjtag + +#urjtag.loglevel(0) # ALL + +urc = urjtag.chain() +printf("%s\n", urc); + +urc.cable("JTAGKey") +printf("urc.cable done %s\n", urc) + +urc.test_cable() +printf("urc.test_cable done\n") + +# trst = urc.get_trst() +# printf("TRST=%d\n", trst) +# urc.set_trst(0) +# trst = urc.get_trst() +# printf( "TRST set 0 -> %d\n", trst) + +# urc.set_trst(1) +# trst = urc.get_trst() +# printf("TRST set 1 -> %d\n", trst) + +srstbit = 0x10 +srstval = urc.get_pod_signal(srstbit) +printf( "srstval -> %s\n", srstval); + +urc.set_pod_signal(srstbit, 0) +srstval = urc.get_pod_signal(srstbit) +printf("srstval set 0 -> %s\n", srstval) +urc.set_pod_signal(srstbit, 1) +srstval = urc.get_pod_signal(srstbit) +printf("srstval set 1 -> %s\n", srstval) + + + diff --git a/urjtag/bindings/python/t_urjtag_chain.py b/urjtag/bindings/python/t_urjtag_chain.py new file mode 100644 index 0000000..d0eaf61 --- /dev/null +++ b/urjtag/bindings/python/t_urjtag_chain.py @@ -0,0 +1,81 @@ +#!/usr/bin/python + +# +# A general test and demonstration of several urjtag operations from python. +# + +# works in both python 2 and 3 +def printf(format, *args): + """Format args with the first argument as format string, and print. + If the format is not a string, it is converted to one with str. + You must use printf('%s', x) instead of printf(x) if x might + contain % or backslash characters.""" + sys.stdout.write(str(format) % args) + +import sys +sys.path.append( "." ) + +import urjtag + +#urjtag.loglevel(0) # ALL + +urc = urjtag.chain() +printf("%s\n", urc); + +urc.cable("JTAGKey") +printf("urc.cable done %s\n", urc) + +urc.test_cable() +printf("urc.test_cable done\n") + +f = urc.get_frequency() +printf("frequency was %d Hz\n", f) +urc.set_frequency(10000) +f = urc.get_frequency() +printf("frequency readback = %d Hz\n", f) + +trst = urc.get_trst() +printf("TRST=%d\n", trst) +urc.set_trst(0) +trst = urc.get_trst() +printf( "TRST set 0 -> %d\n", trst) +urc.set_trst(1) +trst = urc.get_trst() +printf("TRST set 1 -> %d\n", trst) + +urc.reset(); + +urc.tap_detect() +printf("urc.detect done\n") +printf("chainlength=%d\n", urc.len()) + +printf("id[0]=%08x\n", urc.partid(0) ); + +srstbit = 0x10 +srstval = urc.get_pod_signal(srstbit) +printf( "srstval -> %s\n", srstval); + +urc.set_pod_signal(srstbit, 0) +srstval = urc.get_pod_signal(srstbit) +printf("srstval set 0 -> %s\n", srstval) +urc.set_pod_signal(srstbit, 1) +srstval = urc.get_pod_signal(srstbit) +printf("srstval set 1 -> %s\n", srstval) + +urc.set_instruction("SAMPLE/PRELOAD") +urc.shift_ir() +drval = urc.get_dr_in() +printf("BSR dr_in result: %s\n", drval) +urc.shift_dr() +drval = urc.get_dr_out() +printf("BSR dr_out result: %s\n", drval) + +urc.set_instruction("IDCODE") +urc.shift_ir() +urc.shift_dr() +drval = urc.get_dr_out() +printf("IDREG dr result: %s\n", drval) + +urc.set_instruction("BYPASS") +urc.shift_ir() + diff --git a/urjtag/bindings/python/urj_helpers.c b/urjtag/bindings/python/urj_helpers.c new file mode 100644 index 0000000..c4d4cac --- /dev/null +++ b/urjtag/bindings/python/urj_helpers.c @@ -0,0 +1,161 @@ + +/* + * Additional urjtag cain operations. + * These are not language-binding specific, but do help in writing of concise + * language bindings. In theory, this code could someday be merged into + * the core urjtag library. + * + * + * Copyright (C) 2011 + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You 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. + * + */ + +#include <urjtag.h> +#include <chain.h> +#include <cmd.h> +#include <assert.h> +#include <string.h> +#include <sys/mman.h> + +extern int urj_cmd_test_cable (urj_chain_t * chain); +extern int urj_cmd_params (char *params[]); + +int +urj_chain_cable (urj_chain_t * chain, char *params[]) +{ + urj_cable_t *cable = NULL; + int i; + int j; + int paramc = urj_cmd_params (params); + const urj_param_t **cable_params; + urj_cable_parport_devtype_t devtype = -1; + const char *devname = NULL; + int param_start = 1; + const urj_cable_driver_t *driver; + + /* search cable driver list */ + for (i = 0; urj_tap_cable_drivers[i]; i++) + if (strcasecmp (params[0], urj_tap_cable_drivers[i]->name) == 0) + break; + driver = urj_tap_cable_drivers[i]; + if (!driver) + { + urj_error_set (URJ_ERROR_INVALID, + "unknown cable driver '%s'", params[0]); + return URJ_STATUS_FAIL; + } + + if (driver->device_type == URJ_CABLE_DEVICE_PARPORT) + { + if (paramc < 4) + { + urj_error_set (URJ_ERROR_SYNTAX, + "parallel cable requires >= 4 parameters"); + return URJ_STATUS_FAIL; + } + for (j = 0; j < URJ_CABLE_PARPORT_N_DEVS; j++) + if (strcasecmp (params[1], + urj_cable_parport_devtype_string (j)) == 0) + break; + if (j == URJ_CABLE_PARPORT_N_DEVS) + { + urj_error_set (URJ_ERROR_INVALID, + "unknown parallel port device type '%s'", + params[1]); + return URJ_STATUS_FAIL; + } + + devtype = j; + devname = params[2]; + param_start = 3; + } + + urj_param_init (&cable_params); + for (j = param_start; params[j] != NULL; j++) + if (urj_param_push (&urj_cable_param_list, &cable_params, + params[j]) != URJ_STATUS_OK) + { + urj_param_clear (&cable_params); + return URJ_STATUS_FAIL; + } + + switch (driver->device_type) + { + case URJ_CABLE_DEVICE_PARPORT: + cable = + urj_tap_cable_parport_connect (chain, driver, devtype, devname, + cable_params); + break; + case URJ_CABLE_DEVICE_USB: + cable = urj_tap_cable_usb_connect (chain, driver, cable_params); + break; + case URJ_CABLE_DEVICE_OTHER: + cable = urj_tap_cable_other_connect (chain, driver, cable_params); + break; + } + + urj_param_clear (&cable_params); + + if (cable == NULL) + { + return URJ_STATUS_FAIL; + } + + chain->cable->chain = chain; + return URJ_STATUS_OK; +} + +int urj_initbus (urj_chain_t *chain, char *params[]) +{ + int drv, i; + const urj_param_t **bus_params; + + if (urj_cmd_test_cable (chain) != URJ_STATUS_OK) + return URJ_STATUS_FAIL; + + if (urj_tap_chain_active_part (chain) == NULL) + return URJ_STATUS_FAIL; + + for (drv = 0; urj_bus_drivers[drv] != NULL; drv++) + if (strcasecmp (urj_bus_drivers[drv]->name, params[0]) == 0) + break; + + if (urj_bus_drivers[drv] == NULL) + { + urj_error_set (URJ_ERROR_NOTFOUND, "Unknown bus: %s", params[0]); + return URJ_STATUS_FAIL; + } + + urj_param_init (&bus_params); + for (i = 1; params[i] != NULL; i++) + if (urj_param_push (&urj_bus_param_list, &bus_params, + params[i]) != URJ_STATUS_OK) + { + urj_param_clear (&bus_params); + return URJ_STATUS_FAIL; + } + + if (urj_bus_init_bus(chain, urj_bus_drivers[drv], bus_params) == NULL) + { + urj_param_clear (&bus_params); + return URJ_STATUS_FAIL; + } + + urj_param_clear (&bus_params); + return URJ_STATUS_OK; +} diff --git a/urjtag/bindings/python/urj_helpers.h b/urjtag/bindings/python/urj_helpers.h new file mode 100644 index 0000000..cc81a8e --- /dev/null +++ b/urjtag/bindings/python/urj_helpers.h @@ -0,0 +1,34 @@ + +/* + * Additional urjtag cain operations. + * These are not language-binding specific, but do help in writing of concise + * language bindings. In theory, this code could someday be merged into + * the core urjtag library. + * + * + * Copyright (C) 2011 + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You 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. + * + */ + + +int urj_chain_cable (urj_chain_t * chain, char *params[]); +int urj_initbus (urj_chain_t *chain, char *params[]); + + + + diff --git a/urjtag/configure.ac b/urjtag/configure.ac index 52d5d4c..806fd05 100644 --- a/urjtag/configure.ac +++ b/urjtag/configure.ac @@ -86,6 +86,8 @@ AC_CONFIG_FILES( src/apps/bsdl2jtag/Makefile src/bfin/Makefile po/Makefile.in + bindings/Makefile + bindings/python/Makefile ) AM_MAINTAINER_MODE @@ -358,6 +360,26 @@ AS_IF([test "x$enable_apps" = xyes], [ AM_CONDITIONAL(ENABLE_APPS, false) ]) +AC_ARG_ENABLE([python], + [AS_HELP_STRING([--enable-python], [build python language bindings for liburjtag])], + [BIND_PYTHON="yes"],[BIND_PYTHON="no"]) + +if test "$BIND_PYTHON" == "yes"; then + AM_PATH_PYTHON() + PYTHON_MAJOR_VERSION=$(echo $PYTHON_VERSION | cut -d. -f1 ) + PYTHON_MINOR_VERSION=$(echo $PYTHON_VERSION | cut -d. -f2 ) + if (( $PYTHON_MAJOR_VERSION < 2 )); then + AC_MSG_WARN([python version less than 2.0, disabling python binding]) + BIND_PYTHON="no" + fi +fi +if test "$BIND_PYTHON" == "yes"; then + AM_CHECK_PYTHON_HEADERS([],[BIND_PYTHON=no;AC_MSG_NOTICE([python headers not found, disabling python binding])]) +fi +AM_CONDITIONAL([BIND_PYTHON], [test "$BIND_PYTHON" == "yes"]) + +# for future use +#AM_CONDITIONAL([BIND_TCL], false) # check for lex/flex AC_PROG_LEX @@ -748,4 +770,7 @@ jtag is now configured for Bus drivers : $enabled_bus_drivers Cable drivers : $enabled_cable_drivers Lowlevel drivers : $enabled_lowlevel_drivers + Python binding : $BIND_PYTHON ]) + + -- 1.7.4 ------------------------------------------------------------------------------ EditLive Enterprise is the world's most technically advanced content authoring tool. Experience the power of Track Changes, Inline Image Editing and ensure content is compliant with Accessibility Checking. http://p.sf.net/sfu/ephox-dev2dev _______________________________________________ UrJTAG-development mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/urjtag-development
