Karl: > I have a paralell port adapter as in the attached schematic, > and I would like to make it work with urjtag. ...
To understand how to write a driver and how the code works, I started writing some doc about it. Please comment. Regards, /Karl Hammar
############################## 1. Intro (All directory and file references are relative <urjtag-git top dir>/urjtag.) All "cable" drivers lives in: src/tap/cable Currently theese parport drivers are available: arcom.c byteblaster.c dlc5.c ea253.c ei012.c keithkoep.c lattice.c minimal.c mpcbdm.c triton.c wiggler.c wiggler2.c To write a new driver, you make a new file in that directory named by convention by the driver name. In this case I'll describe the steps I took to make the driver for the aspo adapter card (as of july 2019). ############################## 2. Build system, adding a driver. (This section is valid for all cable driver, parport, usb and others.) Before I describe the driver code, let's look into how to integrate the .c file into the build system. You have to update the following files: MAINTAINERS configure.ac doc/UrJTAG.txt po/POTFILES.in src/tap/Makefile.am src/tap/cable_list.h 2.1 MAINTAINERS To be kind to others, please fill in the MAINTAINERS file, and keep it sorted. I added the entry: ASPO CABLE DRIVER M: Karl Hammar <karl at aspodata.se> F: src/tap/cable/aspo.c S: Tested between the "ARCOM CABLE DRIVER" and "AU1500 BUS DRIVER". 2.2 configure.ac In configure.ac there is a list of all possible "cable" drivers around line 655: # Enable cable drivers URJ_DRIVER_SET([cable], [ arcom byteblaster dirtyjtag dlc5 ea253 ... (omitted lines) wiggler xpc ],[ ep9307 jim ts7800 ],[ # automatically disable cable drivers when a required feature is not available ... (omitted lines) ]) ]) add your name there. This will make it possible to enable your driver when you running autogen.sh and configure (look in config.h to make sure). URJ_DRIVER_SET() have four parameters 1st is the driver set name 2nd is the list of drivers to enable by default 3rd is the list of drivers to disable by default 4th is some extra code to run before processing user list you will probably add your driver name to the 2nd argument. I added the line: aspo between the lines with arcom and byteblaster to keep the list sorted. 2.3 doc/UrJTAG.txt Make a note here about your driver so others has a chance to know that it exist. The best place is below line 202 under the headers: ==== Supported JTAG adapters/cables ==== See 'help cable' command for up-to-date info. Parallel-port cables: 2.4 po/POTFILES.in Add your driver source file in the list. TODO: Still don't know at this moment how to make gettext to update po/urjtag.pot so translators can do their job properly. 2.5 src/tap/Makefile.am Add, if-endif code to add your code if your driver is enabled. I added: if ENABLE_CABLE_ASPO libtap_la_SOURCES += \ cable/aspo.c endif between the similar lines for ARCOM and BYTEBLASTER to keep the list sorted. 2.6 src/tap/cable_list.h Add your _URJ_CABLE() section here so your driver entry point can be included. This file is then included in: src/tap/cable.h src/tap/cable.c and via cpp hackery makes the driver entry points available. As before, keep the list sorted I added this section (between the ARCOM and BYTEBLASTER sections): #ifdef ENABLE_CABLE_ASPO _URJ_CABLE(aspo) #endif ############################## 3. Driver code. 3.1 Test building Copy a similar driver as your initial source file and replace the old driver name with the new one. In my case it amounted to: sed -e 's/wiggler2/aspo/g' < src/tap/cable/wiggler2.c > src/tap/cable/aspo.c and then change the first two text entries of the const urj_cable_driver_t last in the file to say something else than the original, just for testing. Now, run ./autogen.sh # ./configure done by autogen.sh; run it here with special options if needed make make install Look at the make output and make sure you see your source compiling, something like: CC cable/aspo.lo Test with jtag and verify that your driver is there with "help cable" without any actual "cable" attached to the paralell port. For me it worked out as (on linux using ppdev as the lowlevel driver): $ jtag UrJTAG 2018.09 # Copyright (C) 2002, 2003 ETC s.r.o. Copyright (C) 2007, 2008, 2009 Kolja Waschk and the respective authors ... (omitted lines) jtag> help cable Usage: cable DRIVER [DRIVER_OPTS] Select JTAG cable type. DRIVER name of cable DRIVER_OPTS options for the selected cable Type "cable DRIVER help" for info about options for cable DRIVER. You can also use the driver "probe" to attempt autodetection. List of supported cables: ARCOM Arcom JTAG Cable ASPO Aspo JTAG Cable (experimental) ByteBlaster Altera ByteBlaster/ByteBlaster II/ByteBlasterMV Parallel Port Download Cable DLC5 Xilinx DLC5 JTAG Parallel Cable III ... (omitted lines) DirtyJTAG DirtyJTAG STM32-based cable jtag> cable aspo ppdev /dev/parport0 Initializing ppdev port /dev/parport0 jtag> cable ASPO ppdev /dev/parport0 Initializing ppdev port /dev/parport0 jtag> quit As you can see, the driver name is case insensitive, the function that finds the driver is urj_tap_cable_find() (in src/tap/cable.c) and it uses strcasecmp(). 3.2 driver documentation Your driver is reached with the "const urj_cable_driver_t" struct, usually found near the end of the driver code. The name of the struct must match what comes out of the _URJ_CABLE(<driver name>) macro found in src/tap/cable.[ch] and src/tap/cable_list.h. This macro is differntly defined in src/tap/cable.[ch]: cable.c: #define _URJ_CABLE(cable) &urj_tap_cable_##cable##_driver, cable.h: #define _URJ_CABLE(cable) extern const urj_cable_driver_t urj_tap_cable_##cable##_driver; but the struct name is the same for booth theese to definitions urj_tap_cable_##cable##_driver, i.e. if you used _URJ_CABLE(foo) in the cable_list.h file, then you must define the entry point as: const urj_cable_driver_t urj_tap_cable_foo_driver = { ... (omitted lines) }; This type, urj_cable_driver_t, is defined in include/urjtag/cable.h, it is a typedef near the top of the file: typedef struct URJ_CABLE_DRIVER urj_cable_driver_t; and the actual struct is defined in middle of the file. Your job as a driver writer is to fill in your struct variable with the right set of functions for the operation of your hardware. Most of theese entries are generic as seen in my example: const urj_cable_driver_t urj_tap_cable_aspo_driver = { "ASPO", N_("Aspo JTAG Cable (experimental)"), URJ_CABLE_DEVICE_PARPORT, { .parport = urj_tap_cable_generic_parport_connect, }, urj_tap_cable_generic_disconnect, urj_tap_cable_generic_parport_free, aspo_init, urj_tap_cable_generic_parport_done, urj_tap_cable_generic_set_frequency, aspo_clock, aspo_get_tdo, urj_tap_cable_generic_transfer, aspo_set_signal, urj_tap_cable_generic_get_signal, urj_tap_cable_generic_flush_one_by_one, urj_tap_cable_generic_parport_help }; The only thing I had to add is the init, clock, get_tdo and set_signal entries and the name ("ASPO") and the description (N_("...")). The N_(...) thing is defined in sysdep.h as #define N_(s) gettext_noop(s) and definition of gettext_noop() is found in include/urjtag/gettext.h. All function entries in the urj_cable_t struct (except help) have a "urj_cable_t *" first parameter, as can be seen from the list below: int (*parport) (urj_cable_t *cable, urj_cable_parport_devtype_t devtype, int (*usb) (urj_cable_t *cable, const urj_param_t *params[]); int (*other) (urj_cable_t *cable, const urj_param_t *params[]); void (*disconnect) (urj_cable_t *cable); void (*cable_free) (urj_cable_t *cable); int (*init) (urj_cable_t *); void (*done) (urj_cable_t *); void (*set_frequency) (urj_cable_t *, uint32_t freq); void (*clock) (urj_cable_t *, int, int, int); int (*get_tdo) (urj_cable_t *); int (*transfer) (urj_cable_t *, int, const char *, char *); int (*set_signal) (urj_cable_t *, int, int); int (*get_signal) (urj_cable_t *, urj_pod_sigsel_t); void (*flush) (urj_cable_t *, urj_cable_flush_amount_t); void (*help) (urj_log_level_t ll, const char *);
_______________________________________________ UrJTAG-development mailing list UrJTAG-development@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/urjtag-development