You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

jlink.c 28 KiB

Submitted by Magnus Lundin <lundin@mlu.mine.nu>: Updates to the J-Link interface driver to support more device versions: - Add capability detection: - if capable, detect protocol version; otherwise, assume v2 protocol. - if capable, detect buffer size; otherwise, assume minimal. - Disable command result queries for devices using v2 protocol. - Defined and use JTAG2 command with v2 protocol; JTAG3 is v3 protocol. - Add TCL command to allow explicit setting of J-Link protocol version. With approval, I revised the patch to make the following changes: - add static keywords to new jlink-specific variables - factor calculation of major_version to be more readable - remove braces around simple one-line statements in if/else clauses - remove (rather than #if 0) duplicate reset code; it is in SVN - use &function to be clearer when passing function pointers - add symbols for EMU_CMD_GET_CAPS bits; do not hard-code constants! - almost renamed jlink_handle_jlink_hw_jtag_command (seriously?!?!) - rewrote that function using a switch statement. - made version request processing easier to understand and modify - improve alternate endpoint detection: - make code easier to read by using temporary variables - eliminate extra level of indentation and redundant logging - use ternary conditional to select JTAG2 or JTAG3 command - reverse version test in jlink_usb_message to reduce indentation - this had the biggest effect in cleaning up this patch - use C99's ability to declare new/changed variables with less scope - add spaces around binary operators in new/changed code - revert other superfluous whitespace/comment style changes git-svn-id: svn://svn.berlios.de/openocd/trunk@1889 b42882b7-edfa-0310-969c-e2dbd0fdcd60
13 years ago
Submitted by Magnus Lundin <lundin@mlu.mine.nu>: Updates to the J-Link interface driver to support more device versions: - Add capability detection: - if capable, detect protocol version; otherwise, assume v2 protocol. - if capable, detect buffer size; otherwise, assume minimal. - Disable command result queries for devices using v2 protocol. - Defined and use JTAG2 command with v2 protocol; JTAG3 is v3 protocol. - Add TCL command to allow explicit setting of J-Link protocol version. With approval, I revised the patch to make the following changes: - add static keywords to new jlink-specific variables - factor calculation of major_version to be more readable - remove braces around simple one-line statements in if/else clauses - remove (rather than #if 0) duplicate reset code; it is in SVN - use &function to be clearer when passing function pointers - add symbols for EMU_CMD_GET_CAPS bits; do not hard-code constants! - almost renamed jlink_handle_jlink_hw_jtag_command (seriously?!?!) - rewrote that function using a switch statement. - made version request processing easier to understand and modify - improve alternate endpoint detection: - make code easier to read by using temporary variables - eliminate extra level of indentation and redundant logging - use ternary conditional to select JTAG2 or JTAG3 command - reverse version test in jlink_usb_message to reduce indentation - this had the biggest effect in cleaning up this patch - use C99's ability to declare new/changed variables with less scope - add spaces around binary operators in new/changed code - revert other superfluous whitespace/comment style changes git-svn-id: svn://svn.berlios.de/openocd/trunk@1889 b42882b7-edfa-0310-969c-e2dbd0fdcd60
13 years ago
Submitted by Magnus Lundin <lundin@mlu.mine.nu>: Updates to the J-Link interface driver to support more device versions: - Add capability detection: - if capable, detect protocol version; otherwise, assume v2 protocol. - if capable, detect buffer size; otherwise, assume minimal. - Disable command result queries for devices using v2 protocol. - Defined and use JTAG2 command with v2 protocol; JTAG3 is v3 protocol. - Add TCL command to allow explicit setting of J-Link protocol version. With approval, I revised the patch to make the following changes: - add static keywords to new jlink-specific variables - factor calculation of major_version to be more readable - remove braces around simple one-line statements in if/else clauses - remove (rather than #if 0) duplicate reset code; it is in SVN - use &function to be clearer when passing function pointers - add symbols for EMU_CMD_GET_CAPS bits; do not hard-code constants! - almost renamed jlink_handle_jlink_hw_jtag_command (seriously?!?!) - rewrote that function using a switch statement. - made version request processing easier to understand and modify - improve alternate endpoint detection: - make code easier to read by using temporary variables - eliminate extra level of indentation and redundant logging - use ternary conditional to select JTAG2 or JTAG3 command - reverse version test in jlink_usb_message to reduce indentation - this had the biggest effect in cleaning up this patch - use C99's ability to declare new/changed variables with less scope - add spaces around binary operators in new/changed code - revert other superfluous whitespace/comment style changes git-svn-id: svn://svn.berlios.de/openocd/trunk@1889 b42882b7-edfa-0310-969c-e2dbd0fdcd60
13 years ago
Submitted by Magnus Lundin <lundin@mlu.mine.nu>: Updates to the J-Link interface driver to support more device versions: - Add capability detection: - if capable, detect protocol version; otherwise, assume v2 protocol. - if capable, detect buffer size; otherwise, assume minimal. - Disable command result queries for devices using v2 protocol. - Defined and use JTAG2 command with v2 protocol; JTAG3 is v3 protocol. - Add TCL command to allow explicit setting of J-Link protocol version. With approval, I revised the patch to make the following changes: - add static keywords to new jlink-specific variables - factor calculation of major_version to be more readable - remove braces around simple one-line statements in if/else clauses - remove (rather than #if 0) duplicate reset code; it is in SVN - use &function to be clearer when passing function pointers - add symbols for EMU_CMD_GET_CAPS bits; do not hard-code constants! - almost renamed jlink_handle_jlink_hw_jtag_command (seriously?!?!) - rewrote that function using a switch statement. - made version request processing easier to understand and modify - improve alternate endpoint detection: - make code easier to read by using temporary variables - eliminate extra level of indentation and redundant logging - use ternary conditional to select JTAG2 or JTAG3 command - reverse version test in jlink_usb_message to reduce indentation - this had the biggest effect in cleaning up this patch - use C99's ability to declare new/changed variables with less scope - add spaces around binary operators in new/changed code - revert other superfluous whitespace/comment style changes git-svn-id: svn://svn.berlios.de/openocd/trunk@1889 b42882b7-edfa-0310-969c-e2dbd0fdcd60
13 years ago
Submitted by Magnus Lundin <lundin@mlu.mine.nu>: Updates to the J-Link interface driver to support more device versions: - Add capability detection: - if capable, detect protocol version; otherwise, assume v2 protocol. - if capable, detect buffer size; otherwise, assume minimal. - Disable command result queries for devices using v2 protocol. - Defined and use JTAG2 command with v2 protocol; JTAG3 is v3 protocol. - Add TCL command to allow explicit setting of J-Link protocol version. With approval, I revised the patch to make the following changes: - add static keywords to new jlink-specific variables - factor calculation of major_version to be more readable - remove braces around simple one-line statements in if/else clauses - remove (rather than #if 0) duplicate reset code; it is in SVN - use &function to be clearer when passing function pointers - add symbols for EMU_CMD_GET_CAPS bits; do not hard-code constants! - almost renamed jlink_handle_jlink_hw_jtag_command (seriously?!?!) - rewrote that function using a switch statement. - made version request processing easier to understand and modify - improve alternate endpoint detection: - make code easier to read by using temporary variables - eliminate extra level of indentation and redundant logging - use ternary conditional to select JTAG2 or JTAG3 command - reverse version test in jlink_usb_message to reduce indentation - this had the biggest effect in cleaning up this patch - use C99's ability to declare new/changed variables with less scope - add spaces around binary operators in new/changed code - revert other superfluous whitespace/comment style changes git-svn-id: svn://svn.berlios.de/openocd/trunk@1889 b42882b7-edfa-0310-969c-e2dbd0fdcd60
13 years ago
Submitted by Magnus Lundin <lundin@mlu.mine.nu>: Updates to the J-Link interface driver to support more device versions: - Add capability detection: - if capable, detect protocol version; otherwise, assume v2 protocol. - if capable, detect buffer size; otherwise, assume minimal. - Disable command result queries for devices using v2 protocol. - Defined and use JTAG2 command with v2 protocol; JTAG3 is v3 protocol. - Add TCL command to allow explicit setting of J-Link protocol version. With approval, I revised the patch to make the following changes: - add static keywords to new jlink-specific variables - factor calculation of major_version to be more readable - remove braces around simple one-line statements in if/else clauses - remove (rather than #if 0) duplicate reset code; it is in SVN - use &function to be clearer when passing function pointers - add symbols for EMU_CMD_GET_CAPS bits; do not hard-code constants! - almost renamed jlink_handle_jlink_hw_jtag_command (seriously?!?!) - rewrote that function using a switch statement. - made version request processing easier to understand and modify - improve alternate endpoint detection: - make code easier to read by using temporary variables - eliminate extra level of indentation and redundant logging - use ternary conditional to select JTAG2 or JTAG3 command - reverse version test in jlink_usb_message to reduce indentation - this had the biggest effect in cleaning up this patch - use C99's ability to declare new/changed variables with less scope - add spaces around binary operators in new/changed code - revert other superfluous whitespace/comment style changes git-svn-id: svn://svn.berlios.de/openocd/trunk@1889 b42882b7-edfa-0310-969c-e2dbd0fdcd60
13 years ago
Submitted by Magnus Lundin <lundin@mlu.mine.nu>: Updates to the J-Link interface driver to support more device versions: - Add capability detection: - if capable, detect protocol version; otherwise, assume v2 protocol. - if capable, detect buffer size; otherwise, assume minimal. - Disable command result queries for devices using v2 protocol. - Defined and use JTAG2 command with v2 protocol; JTAG3 is v3 protocol. - Add TCL command to allow explicit setting of J-Link protocol version. With approval, I revised the patch to make the following changes: - add static keywords to new jlink-specific variables - factor calculation of major_version to be more readable - remove braces around simple one-line statements in if/else clauses - remove (rather than #if 0) duplicate reset code; it is in SVN - use &function to be clearer when passing function pointers - add symbols for EMU_CMD_GET_CAPS bits; do not hard-code constants! - almost renamed jlink_handle_jlink_hw_jtag_command (seriously?!?!) - rewrote that function using a switch statement. - made version request processing easier to understand and modify - improve alternate endpoint detection: - make code easier to read by using temporary variables - eliminate extra level of indentation and redundant logging - use ternary conditional to select JTAG2 or JTAG3 command - reverse version test in jlink_usb_message to reduce indentation - this had the biggest effect in cleaning up this patch - use C99's ability to declare new/changed variables with less scope - add spaces around binary operators in new/changed code - revert other superfluous whitespace/comment style changes git-svn-id: svn://svn.berlios.de/openocd/trunk@1889 b42882b7-edfa-0310-969c-e2dbd0fdcd60
13 years ago
Submitted by Magnus Lundin <lundin@mlu.mine.nu>: Updates to the J-Link interface driver to support more device versions: - Add capability detection: - if capable, detect protocol version; otherwise, assume v2 protocol. - if capable, detect buffer size; otherwise, assume minimal. - Disable command result queries for devices using v2 protocol. - Defined and use JTAG2 command with v2 protocol; JTAG3 is v3 protocol. - Add TCL command to allow explicit setting of J-Link protocol version. With approval, I revised the patch to make the following changes: - add static keywords to new jlink-specific variables - factor calculation of major_version to be more readable - remove braces around simple one-line statements in if/else clauses - remove (rather than #if 0) duplicate reset code; it is in SVN - use &function to be clearer when passing function pointers - add symbols for EMU_CMD_GET_CAPS bits; do not hard-code constants! - almost renamed jlink_handle_jlink_hw_jtag_command (seriously?!?!) - rewrote that function using a switch statement. - made version request processing easier to understand and modify - improve alternate endpoint detection: - make code easier to read by using temporary variables - eliminate extra level of indentation and redundant logging - use ternary conditional to select JTAG2 or JTAG3 command - reverse version test in jlink_usb_message to reduce indentation - this had the biggest effect in cleaning up this patch - use C99's ability to declare new/changed variables with less scope - add spaces around binary operators in new/changed code - revert other superfluous whitespace/comment style changes git-svn-id: svn://svn.berlios.de/openocd/trunk@1889 b42882b7-edfa-0310-969c-e2dbd0fdcd60
13 years ago
Submitted by Magnus Lundin <lundin@mlu.mine.nu>: Updates to the J-Link interface driver to support more device versions: - Add capability detection: - if capable, detect protocol version; otherwise, assume v2 protocol. - if capable, detect buffer size; otherwise, assume minimal. - Disable command result queries for devices using v2 protocol. - Defined and use JTAG2 command with v2 protocol; JTAG3 is v3 protocol. - Add TCL command to allow explicit setting of J-Link protocol version. With approval, I revised the patch to make the following changes: - add static keywords to new jlink-specific variables - factor calculation of major_version to be more readable - remove braces around simple one-line statements in if/else clauses - remove (rather than #if 0) duplicate reset code; it is in SVN - use &function to be clearer when passing function pointers - add symbols for EMU_CMD_GET_CAPS bits; do not hard-code constants! - almost renamed jlink_handle_jlink_hw_jtag_command (seriously?!?!) - rewrote that function using a switch statement. - made version request processing easier to understand and modify - improve alternate endpoint detection: - make code easier to read by using temporary variables - eliminate extra level of indentation and redundant logging - use ternary conditional to select JTAG2 or JTAG3 command - reverse version test in jlink_usb_message to reduce indentation - this had the biggest effect in cleaning up this patch - use C99's ability to declare new/changed variables with less scope - add spaces around binary operators in new/changed code - revert other superfluous whitespace/comment style changes git-svn-id: svn://svn.berlios.de/openocd/trunk@1889 b42882b7-edfa-0310-969c-e2dbd0fdcd60
13 years ago
Submitted by Magnus Lundin <lundin@mlu.mine.nu>: Updates to the J-Link interface driver to support more device versions: - Add capability detection: - if capable, detect protocol version; otherwise, assume v2 protocol. - if capable, detect buffer size; otherwise, assume minimal. - Disable command result queries for devices using v2 protocol. - Defined and use JTAG2 command with v2 protocol; JTAG3 is v3 protocol. - Add TCL command to allow explicit setting of J-Link protocol version. With approval, I revised the patch to make the following changes: - add static keywords to new jlink-specific variables - factor calculation of major_version to be more readable - remove braces around simple one-line statements in if/else clauses - remove (rather than #if 0) duplicate reset code; it is in SVN - use &function to be clearer when passing function pointers - add symbols for EMU_CMD_GET_CAPS bits; do not hard-code constants! - almost renamed jlink_handle_jlink_hw_jtag_command (seriously?!?!) - rewrote that function using a switch statement. - made version request processing easier to understand and modify - improve alternate endpoint detection: - make code easier to read by using temporary variables - eliminate extra level of indentation and redundant logging - use ternary conditional to select JTAG2 or JTAG3 command - reverse version test in jlink_usb_message to reduce indentation - this had the biggest effect in cleaning up this patch - use C99's ability to declare new/changed variables with less scope - add spaces around binary operators in new/changed code - revert other superfluous whitespace/comment style changes git-svn-id: svn://svn.berlios.de/openocd/trunk@1889 b42882b7-edfa-0310-969c-e2dbd0fdcd60
13 years ago
Submitted by Magnus Lundin <lundin@mlu.mine.nu>: Updates to the J-Link interface driver to support more device versions: - Add capability detection: - if capable, detect protocol version; otherwise, assume v2 protocol. - if capable, detect buffer size; otherwise, assume minimal. - Disable command result queries for devices using v2 protocol. - Defined and use JTAG2 command with v2 protocol; JTAG3 is v3 protocol. - Add TCL command to allow explicit setting of J-Link protocol version. With approval, I revised the patch to make the following changes: - add static keywords to new jlink-specific variables - factor calculation of major_version to be more readable - remove braces around simple one-line statements in if/else clauses - remove (rather than #if 0) duplicate reset code; it is in SVN - use &function to be clearer when passing function pointers - add symbols for EMU_CMD_GET_CAPS bits; do not hard-code constants! - almost renamed jlink_handle_jlink_hw_jtag_command (seriously?!?!) - rewrote that function using a switch statement. - made version request processing easier to understand and modify - improve alternate endpoint detection: - make code easier to read by using temporary variables - eliminate extra level of indentation and redundant logging - use ternary conditional to select JTAG2 or JTAG3 command - reverse version test in jlink_usb_message to reduce indentation - this had the biggest effect in cleaning up this patch - use C99's ability to declare new/changed variables with less scope - add spaces around binary operators in new/changed code - revert other superfluous whitespace/comment style changes git-svn-id: svn://svn.berlios.de/openocd/trunk@1889 b42882b7-edfa-0310-969c-e2dbd0fdcd60
13 years ago
Submitted by Magnus Lundin <lundin@mlu.mine.nu>: Updates to the J-Link interface driver to support more device versions: - Add capability detection: - if capable, detect protocol version; otherwise, assume v2 protocol. - if capable, detect buffer size; otherwise, assume minimal. - Disable command result queries for devices using v2 protocol. - Defined and use JTAG2 command with v2 protocol; JTAG3 is v3 protocol. - Add TCL command to allow explicit setting of J-Link protocol version. With approval, I revised the patch to make the following changes: - add static keywords to new jlink-specific variables - factor calculation of major_version to be more readable - remove braces around simple one-line statements in if/else clauses - remove (rather than #if 0) duplicate reset code; it is in SVN - use &function to be clearer when passing function pointers - add symbols for EMU_CMD_GET_CAPS bits; do not hard-code constants! - almost renamed jlink_handle_jlink_hw_jtag_command (seriously?!?!) - rewrote that function using a switch statement. - made version request processing easier to understand and modify - improve alternate endpoint detection: - make code easier to read by using temporary variables - eliminate extra level of indentation and redundant logging - use ternary conditional to select JTAG2 or JTAG3 command - reverse version test in jlink_usb_message to reduce indentation - this had the biggest effect in cleaning up this patch - use C99's ability to declare new/changed variables with less scope - add spaces around binary operators in new/changed code - revert other superfluous whitespace/comment style changes git-svn-id: svn://svn.berlios.de/openocd/trunk@1889 b42882b7-edfa-0310-969c-e2dbd0fdcd60
13 years ago
Submitted by Magnus Lundin <lundin@mlu.mine.nu>: Updates to the J-Link interface driver to support more device versions: - Add capability detection: - if capable, detect protocol version; otherwise, assume v2 protocol. - if capable, detect buffer size; otherwise, assume minimal. - Disable command result queries for devices using v2 protocol. - Defined and use JTAG2 command with v2 protocol; JTAG3 is v3 protocol. - Add TCL command to allow explicit setting of J-Link protocol version. With approval, I revised the patch to make the following changes: - add static keywords to new jlink-specific variables - factor calculation of major_version to be more readable - remove braces around simple one-line statements in if/else clauses - remove (rather than #if 0) duplicate reset code; it is in SVN - use &function to be clearer when passing function pointers - add symbols for EMU_CMD_GET_CAPS bits; do not hard-code constants! - almost renamed jlink_handle_jlink_hw_jtag_command (seriously?!?!) - rewrote that function using a switch statement. - made version request processing easier to understand and modify - improve alternate endpoint detection: - make code easier to read by using temporary variables - eliminate extra level of indentation and redundant logging - use ternary conditional to select JTAG2 or JTAG3 command - reverse version test in jlink_usb_message to reduce indentation - this had the biggest effect in cleaning up this patch - use C99's ability to declare new/changed variables with less scope - add spaces around binary operators in new/changed code - revert other superfluous whitespace/comment style changes git-svn-id: svn://svn.berlios.de/openocd/trunk@1889 b42882b7-edfa-0310-969c-e2dbd0fdcd60
13 years ago
Submitted by Magnus Lundin <lundin@mlu.mine.nu>: Updates to the J-Link interface driver to support more device versions: - Add capability detection: - if capable, detect protocol version; otherwise, assume v2 protocol. - if capable, detect buffer size; otherwise, assume minimal. - Disable command result queries for devices using v2 protocol. - Defined and use JTAG2 command with v2 protocol; JTAG3 is v3 protocol. - Add TCL command to allow explicit setting of J-Link protocol version. With approval, I revised the patch to make the following changes: - add static keywords to new jlink-specific variables - factor calculation of major_version to be more readable - remove braces around simple one-line statements in if/else clauses - remove (rather than #if 0) duplicate reset code; it is in SVN - use &function to be clearer when passing function pointers - add symbols for EMU_CMD_GET_CAPS bits; do not hard-code constants! - almost renamed jlink_handle_jlink_hw_jtag_command (seriously?!?!) - rewrote that function using a switch statement. - made version request processing easier to understand and modify - improve alternate endpoint detection: - make code easier to read by using temporary variables - eliminate extra level of indentation and redundant logging - use ternary conditional to select JTAG2 or JTAG3 command - reverse version test in jlink_usb_message to reduce indentation - this had the biggest effect in cleaning up this patch - use C99's ability to declare new/changed variables with less scope - add spaces around binary operators in new/changed code - revert other superfluous whitespace/comment style changes git-svn-id: svn://svn.berlios.de/openocd/trunk@1889 b42882b7-edfa-0310-969c-e2dbd0fdcd60
13 years ago
Submitted by Magnus Lundin <lundin@mlu.mine.nu>: Updates to the J-Link interface driver to support more device versions: - Add capability detection: - if capable, detect protocol version; otherwise, assume v2 protocol. - if capable, detect buffer size; otherwise, assume minimal. - Disable command result queries for devices using v2 protocol. - Defined and use JTAG2 command with v2 protocol; JTAG3 is v3 protocol. - Add TCL command to allow explicit setting of J-Link protocol version. With approval, I revised the patch to make the following changes: - add static keywords to new jlink-specific variables - factor calculation of major_version to be more readable - remove braces around simple one-line statements in if/else clauses - remove (rather than #if 0) duplicate reset code; it is in SVN - use &function to be clearer when passing function pointers - add symbols for EMU_CMD_GET_CAPS bits; do not hard-code constants! - almost renamed jlink_handle_jlink_hw_jtag_command (seriously?!?!) - rewrote that function using a switch statement. - made version request processing easier to understand and modify - improve alternate endpoint detection: - make code easier to read by using temporary variables - eliminate extra level of indentation and redundant logging - use ternary conditional to select JTAG2 or JTAG3 command - reverse version test in jlink_usb_message to reduce indentation - this had the biggest effect in cleaning up this patch - use C99's ability to declare new/changed variables with less scope - add spaces around binary operators in new/changed code - revert other superfluous whitespace/comment style changes git-svn-id: svn://svn.berlios.de/openocd/trunk@1889 b42882b7-edfa-0310-969c-e2dbd0fdcd60
13 years ago
Submitted by Magnus Lundin <lundin@mlu.mine.nu>: Updates to the J-Link interface driver to support more device versions: - Add capability detection: - if capable, detect protocol version; otherwise, assume v2 protocol. - if capable, detect buffer size; otherwise, assume minimal. - Disable command result queries for devices using v2 protocol. - Defined and use JTAG2 command with v2 protocol; JTAG3 is v3 protocol. - Add TCL command to allow explicit setting of J-Link protocol version. With approval, I revised the patch to make the following changes: - add static keywords to new jlink-specific variables - factor calculation of major_version to be more readable - remove braces around simple one-line statements in if/else clauses - remove (rather than #if 0) duplicate reset code; it is in SVN - use &function to be clearer when passing function pointers - add symbols for EMU_CMD_GET_CAPS bits; do not hard-code constants! - almost renamed jlink_handle_jlink_hw_jtag_command (seriously?!?!) - rewrote that function using a switch statement. - made version request processing easier to understand and modify - improve alternate endpoint detection: - make code easier to read by using temporary variables - eliminate extra level of indentation and redundant logging - use ternary conditional to select JTAG2 or JTAG3 command - reverse version test in jlink_usb_message to reduce indentation - this had the biggest effect in cleaning up this patch - use C99's ability to declare new/changed variables with less scope - add spaces around binary operators in new/changed code - revert other superfluous whitespace/comment style changes git-svn-id: svn://svn.berlios.de/openocd/trunk@1889 b42882b7-edfa-0310-969c-e2dbd0fdcd60
13 years ago
Submitted by Magnus Lundin <lundin@mlu.mine.nu>: Updates to the J-Link interface driver to support more device versions: - Add capability detection: - if capable, detect protocol version; otherwise, assume v2 protocol. - if capable, detect buffer size; otherwise, assume minimal. - Disable command result queries for devices using v2 protocol. - Defined and use JTAG2 command with v2 protocol; JTAG3 is v3 protocol. - Add TCL command to allow explicit setting of J-Link protocol version. With approval, I revised the patch to make the following changes: - add static keywords to new jlink-specific variables - factor calculation of major_version to be more readable - remove braces around simple one-line statements in if/else clauses - remove (rather than #if 0) duplicate reset code; it is in SVN - use &function to be clearer when passing function pointers - add symbols for EMU_CMD_GET_CAPS bits; do not hard-code constants! - almost renamed jlink_handle_jlink_hw_jtag_command (seriously?!?!) - rewrote that function using a switch statement. - made version request processing easier to understand and modify - improve alternate endpoint detection: - make code easier to read by using temporary variables - eliminate extra level of indentation and redundant logging - use ternary conditional to select JTAG2 or JTAG3 command - reverse version test in jlink_usb_message to reduce indentation - this had the biggest effect in cleaning up this patch - use C99's ability to declare new/changed variables with less scope - add spaces around binary operators in new/changed code - revert other superfluous whitespace/comment style changes git-svn-id: svn://svn.berlios.de/openocd/trunk@1889 b42882b7-edfa-0310-969c-e2dbd0fdcd60
13 years ago
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087
  1. /***************************************************************************
  2. * Copyright (C) 2007 by Juergen Stuber <juergen@jstuber.net> *
  3. * based on Dominic Rath's and Benedikt Sauter's usbprog.c *
  4. * *
  5. * Copyright (C) 2008 by Spencer Oliver *
  6. * spen@spen-soft.co.uk *
  7. * *
  8. * This program is free software; you can redistribute it and/or modify *
  9. * it under the terms of the GNU General Public License as published by *
  10. * the Free Software Foundation; either version 2 of the License, or *
  11. * (at your option) any later version. *
  12. * *
  13. * This program is distributed in the hope that it will be useful, *
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of *
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
  16. * GNU General Public License for more details. *
  17. * *
  18. * You should have received a copy of the GNU General Public License *
  19. * along with this program; if not, write to the *
  20. * Free Software Foundation, Inc., *
  21. * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
  22. ***************************************************************************/
  23. #ifdef HAVE_CONFIG_H
  24. #include "config.h"
  25. #endif
  26. #include <jtag/interface.h>
  27. #include <jtag/commands.h>
  28. #include "usb_common.h"
  29. /* See Segger's public documentation:
  30. * Reference manual for J-Link USB Protocol
  31. * Document RM08001-R6 Date: June 16, 2009
  32. */
  33. #define VID 0x1366
  34. #define PID 0x0101
  35. #define JLINK_WRITE_ENDPOINT 0x02
  36. #define JLINK_READ_ENDPOINT 0x81
  37. static unsigned int jlink_write_ep = JLINK_WRITE_ENDPOINT;
  38. static unsigned int jlink_read_ep = JLINK_READ_ENDPOINT;
  39. static unsigned int jlink_hw_jtag_version = 2;
  40. #define JLINK_USB_TIMEOUT 1000
  41. // See Section 1.3.2 of the Segger JLink USB protocol manual
  42. /* 2048 is the max value we can use here */
  43. //#define JLINK_TAP_BUFFER_SIZE 2048
  44. #define JLINK_TAP_BUFFER_SIZE 256
  45. //#define JLINK_TAP_BUFFER_SIZE 384
  46. #define JLINK_IN_BUFFER_SIZE 2048
  47. #define JLINK_OUT_BUFFER_SIZE 2*2048 + 4
  48. #define JLINK_EMU_RESULT_BUFFER_SIZE 64
  49. /* Global USB buffers */
  50. static uint8_t usb_in_buffer[JLINK_IN_BUFFER_SIZE];
  51. static uint8_t usb_out_buffer[JLINK_OUT_BUFFER_SIZE];
  52. static uint8_t usb_emu_result_buffer[JLINK_EMU_RESULT_BUFFER_SIZE];
  53. /* Constants for JLink command */
  54. #define EMU_CMD_VERSION 0x01
  55. #define EMU_CMD_SET_SPEED 0x05
  56. #define EMU_CMD_GET_STATE 0x07
  57. #define EMU_CMD_HW_CLOCK 0xc8
  58. #define EMU_CMD_HW_TMS0 0xc9
  59. #define EMU_CMD_HW_TMS1 0xca
  60. #define EMU_CMD_HW_JTAG2 0xce
  61. #define EMU_CMD_HW_JTAG3 0xcf
  62. #define EMU_CMD_GET_MAX_MEM_BLOCK 0xd4
  63. #define EMU_CMD_HW_RESET0 0xdc
  64. #define EMU_CMD_HW_RESET1 0xdd
  65. #define EMU_CMD_HW_TRST0 0xde
  66. #define EMU_CMD_HW_TRST1 0xdf
  67. #define EMU_CMD_GET_CAPS 0xe8
  68. #define EMU_CMD_GET_HW_VERSION 0xf0
  69. /* bits return from EMU_CMD_GET_CAPS */
  70. #define EMU_CAP_GET_HW_VERSION 1
  71. #define EMU_CAP_GET_MAX_BLOCK_SIZE 11
  72. /* max speed 12MHz v5.0 jlink */
  73. #define JLINK_MAX_SPEED 12000
  74. /* Queue command functions */
  75. static void jlink_end_state(tap_state_t state);
  76. static void jlink_state_move(void);
  77. static void jlink_path_move(int num_states, tap_state_t *path);
  78. static void jlink_runtest(int num_cycles);
  79. static void jlink_scan(bool ir_scan, enum scan_type type, uint8_t *buffer, int scan_size, struct scan_command *command);
  80. static void jlink_reset(int trst, int srst);
  81. static void jlink_simple_command(uint8_t command);
  82. static int jlink_get_status(void);
  83. /* J-Link tap buffer functions */
  84. static void jlink_tap_init(void);
  85. static int jlink_tap_execute(void);
  86. static void jlink_tap_ensure_space(int scans, int bits);
  87. static void jlink_tap_append_step(int tms, int tdi);
  88. static void jlink_tap_append_scan(int length, uint8_t *buffer, struct scan_command *command);
  89. /* Jlink lowlevel functions */
  90. struct jlink {
  91. struct usb_dev_handle* usb_handle;
  92. };
  93. static struct jlink *jlink_usb_open(void);
  94. static void jlink_usb_close(struct jlink *jlink);
  95. static int jlink_usb_message(struct jlink *jlink, int out_length, int in_length);
  96. static int jlink_usb_write(struct jlink *jlink, int out_length);
  97. static int jlink_usb_read(struct jlink *jlink, int expected_size);
  98. static int jlink_usb_read_emu_result(struct jlink *jlink);
  99. /* helper functions */
  100. static int jlink_get_version_info(void);
  101. #ifdef _DEBUG_USB_COMMS_
  102. static void jlink_debug_buffer(uint8_t *buffer, int length);
  103. #endif
  104. static enum tap_state jlink_last_state = TAP_RESET;
  105. static struct jlink* jlink_handle;
  106. /***************************************************************************/
  107. /* External interface implementation */
  108. static void jlink_execute_runtest(struct jtag_command *cmd)
  109. {
  110. DEBUG_JTAG_IO("runtest %i cycles, end in %i",
  111. cmd->cmd.runtest->num_cycles,
  112. cmd->cmd.runtest->end_state);
  113. jlink_end_state(cmd->cmd.runtest->end_state);
  114. jlink_runtest(cmd->cmd.runtest->num_cycles);
  115. }
  116. static void jlink_execute_statemove(struct jtag_command *cmd)
  117. {
  118. DEBUG_JTAG_IO("statemove end in %i", cmd->cmd.statemove->end_state);
  119. jlink_end_state(cmd->cmd.statemove->end_state);
  120. jlink_state_move();
  121. }
  122. static void jlink_execute_pathmove(struct jtag_command *cmd)
  123. {
  124. DEBUG_JTAG_IO("pathmove: %i states, end in %i",
  125. cmd->cmd.pathmove->num_states,
  126. cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]);
  127. jlink_path_move(cmd->cmd.pathmove->num_states,
  128. cmd->cmd.pathmove->path);
  129. }
  130. static void jlink_execute_scan(struct jtag_command *cmd)
  131. {
  132. int scan_size;
  133. enum scan_type type;
  134. uint8_t *buffer;
  135. DEBUG_JTAG_IO("scan end in %s", tap_state_name(cmd->cmd.scan->end_state));
  136. jlink_end_state(cmd->cmd.scan->end_state);
  137. scan_size = jtag_build_buffer(cmd->cmd.scan, &buffer);
  138. DEBUG_JTAG_IO("scan input, length = %d", scan_size);
  139. #ifdef _DEBUG_USB_COMMS_
  140. jlink_debug_buffer(buffer, (scan_size + 7) / 8);
  141. #endif
  142. type = jtag_scan_type(cmd->cmd.scan);
  143. jlink_scan(cmd->cmd.scan->ir_scan,
  144. type, buffer, scan_size, cmd->cmd.scan);
  145. }
  146. static void jlink_execute_reset(struct jtag_command *cmd)
  147. {
  148. DEBUG_JTAG_IO("reset trst: %i srst %i",
  149. cmd->cmd.reset->trst, cmd->cmd.reset->srst);
  150. jlink_tap_execute();
  151. jlink_reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst);
  152. jlink_tap_execute();
  153. }
  154. static void jlink_execute_sleep(struct jtag_command *cmd)
  155. {
  156. DEBUG_JTAG_IO("sleep %" PRIi32 "", cmd->cmd.sleep->us);
  157. jlink_tap_execute();
  158. jtag_sleep(cmd->cmd.sleep->us);
  159. }
  160. static void jlink_execute_command(struct jtag_command *cmd)
  161. {
  162. switch (cmd->type)
  163. {
  164. case JTAG_RUNTEST: jlink_execute_runtest(cmd); break;
  165. case JTAG_STATEMOVE: jlink_execute_statemove(cmd); break;
  166. case JTAG_PATHMOVE: jlink_execute_pathmove(cmd); break;
  167. case JTAG_SCAN: jlink_execute_scan(cmd); break;
  168. case JTAG_RESET: jlink_execute_reset(cmd); break;
  169. case JTAG_SLEEP: jlink_execute_sleep(cmd); break;
  170. default:
  171. LOG_ERROR("BUG: unknown JTAG command type encountered");
  172. exit(-1);
  173. }
  174. }
  175. static int jlink_execute_queue(void)
  176. {
  177. struct jtag_command *cmd = jtag_command_queue;
  178. while (cmd != NULL)
  179. {
  180. jlink_execute_command(cmd);
  181. cmd = cmd->next;
  182. }
  183. return jlink_tap_execute();
  184. }
  185. /* Sets speed in kHz. */
  186. static int jlink_speed(int speed)
  187. {
  188. int result;
  189. if (speed > JLINK_MAX_SPEED)
  190. {
  191. LOG_INFO("Ignoring speed request: %dkHz exceeds %dkHz maximum",
  192. speed, JLINK_MAX_SPEED);
  193. return ERROR_OK;
  194. }
  195. /* check for RTCK setting */
  196. if (speed == 0)
  197. speed = -1;
  198. usb_out_buffer[0] = EMU_CMD_SET_SPEED;
  199. usb_out_buffer[1] = (speed >> 0) & 0xff;
  200. usb_out_buffer[2] = (speed >> 8) & 0xff;
  201. result = jlink_usb_write(jlink_handle, 3);
  202. if (result != 3)
  203. {
  204. LOG_ERROR("J-Link setting speed failed (%d)", result);
  205. return ERROR_JTAG_DEVICE_ERROR;
  206. }
  207. return ERROR_OK;
  208. }
  209. static int jlink_speed_div(int speed, int* khz)
  210. {
  211. *khz = speed;
  212. return ERROR_OK;
  213. }
  214. static int jlink_khz(int khz, int *jtag_speed)
  215. {
  216. *jtag_speed = khz;
  217. return ERROR_OK;
  218. }
  219. static int jlink_init(void)
  220. {
  221. int i;
  222. jlink_handle = jlink_usb_open();
  223. if (jlink_handle == 0)
  224. {
  225. LOG_ERROR("Cannot find jlink Interface! Please check connection and permissions.");
  226. return ERROR_JTAG_INIT_FAILED;
  227. }
  228. /*
  229. * The next three instructions were added after discovering a problem while using an oscilloscope. For the V8
  230. * SAM-ICE dongle (and likely other j-link device variants), the reset line to the target microprocessor was found to
  231. * cycle only intermittently during emulator startup (even after encountering the downstream reset instruction later
  232. * in the code). This was found to create two issues: 1) In general it is a bad practice to not reset a CPU to a known
  233. * state when starting an emulator and 2) something critical happens inside the dongle when it does the first read
  234. * following a new USB session. Keeping the processor in reset during the first read collecting version information
  235. * seems to prevent errant "J-Link command EMU_CMD_VERSION failed" issues.
  236. */
  237. LOG_INFO("J-Link initialization started / target CPU reset initiated");
  238. jlink_simple_command(EMU_CMD_HW_TRST0);
  239. jlink_simple_command(EMU_CMD_HW_RESET0);
  240. usleep(1000);
  241. jlink_hw_jtag_version = 2;
  242. if (jlink_get_version_info() == ERROR_OK)
  243. {
  244. /* attempt to get status */
  245. jlink_get_status();
  246. }
  247. LOG_INFO("J-Link JTAG Interface ready");
  248. jlink_reset(0, 0);
  249. jtag_sleep(3000);
  250. jlink_tap_init();
  251. jlink_speed(jtag_get_speed());
  252. /* v5/6 jlink seems to have an issue if the first tap move
  253. * is not divisible by 8, so we send a TLR on first power up */
  254. for (i = 0; i < 8; i++) {
  255. jlink_tap_append_step(1, 0);
  256. }
  257. jlink_tap_execute();
  258. return ERROR_OK;
  259. }
  260. static int jlink_quit(void)
  261. {
  262. jlink_usb_close(jlink_handle);
  263. return ERROR_OK;
  264. }
  265. /***************************************************************************/
  266. /* Queue command implementations */
  267. static void jlink_end_state(tap_state_t state)
  268. {
  269. if (tap_is_state_stable(state))
  270. {
  271. tap_set_end_state(state);
  272. }
  273. else
  274. {
  275. LOG_ERROR("BUG: %i is not a valid end state", state);
  276. exit(-1);
  277. }
  278. }
  279. /* Goes to the end state. */
  280. static void jlink_state_move(void)
  281. {
  282. int i;
  283. int tms = 0;
  284. uint8_t tms_scan = tap_get_tms_path(tap_get_state(), tap_get_end_state());
  285. uint8_t tms_scan_bits = tap_get_tms_path_len(tap_get_state(), tap_get_end_state());
  286. for (i = 0; i < tms_scan_bits; i++)
  287. {
  288. tms = (tms_scan >> i) & 1;
  289. jlink_tap_append_step(tms, 0);
  290. }
  291. tap_set_state(tap_get_end_state());
  292. }
  293. static void jlink_path_move(int num_states, tap_state_t *path)
  294. {
  295. int i;
  296. for (i = 0; i < num_states; i++)
  297. {
  298. if (path[i] == tap_state_transition(tap_get_state(), false))
  299. {
  300. jlink_tap_append_step(0, 0);
  301. }
  302. else if (path[i] == tap_state_transition(tap_get_state(), true))
  303. {
  304. jlink_tap_append_step(1, 0);
  305. }
  306. else
  307. {
  308. LOG_ERROR("BUG: %s -> %s isn't a valid TAP transition", tap_state_name(tap_get_state()), tap_state_name(path[i]));
  309. exit(-1);
  310. }
  311. tap_set_state(path[i]);
  312. }
  313. tap_set_end_state(tap_get_state());
  314. }
  315. static void jlink_runtest(int num_cycles)
  316. {
  317. int i;
  318. tap_state_t saved_end_state = tap_get_end_state();
  319. jlink_tap_ensure_space(1,num_cycles + 16);
  320. /* only do a state_move when we're not already in IDLE */
  321. if (tap_get_state() != TAP_IDLE)
  322. {
  323. jlink_end_state(TAP_IDLE);
  324. jlink_state_move();
  325. // num_cycles--;
  326. }
  327. /* execute num_cycles */
  328. for (i = 0; i < num_cycles; i++)
  329. {
  330. jlink_tap_append_step(0, 0);
  331. }
  332. /* finish in end_state */
  333. jlink_end_state(saved_end_state);
  334. if (tap_get_state() != tap_get_end_state())
  335. {
  336. jlink_state_move();
  337. }
  338. }
  339. static void jlink_scan(bool ir_scan, enum scan_type type, uint8_t *buffer, int scan_size, struct scan_command *command)
  340. {
  341. tap_state_t saved_end_state;
  342. jlink_tap_ensure_space(1, scan_size + 16);
  343. saved_end_state = tap_get_end_state();
  344. /* Move to appropriate scan state */
  345. jlink_end_state(ir_scan ? TAP_IRSHIFT : TAP_DRSHIFT);
  346. /* Only move if we're not already there */
  347. if (tap_get_state() != tap_get_end_state())
  348. jlink_state_move();
  349. jlink_end_state(saved_end_state);
  350. /* Scan */
  351. jlink_tap_append_scan(scan_size, buffer, command);
  352. /* We are in Exit1, go to Pause */
  353. jlink_tap_append_step(0, 0);
  354. tap_set_state(ir_scan ? TAP_IRPAUSE : TAP_DRPAUSE);
  355. if (tap_get_state() != tap_get_end_state())
  356. {
  357. jlink_state_move();
  358. }
  359. }
  360. static void jlink_reset(int trst, int srst)
  361. {
  362. LOG_DEBUG("trst: %i, srst: %i", trst, srst);
  363. /* Signals are active low */
  364. if (srst == 0)
  365. {
  366. jlink_simple_command(EMU_CMD_HW_RESET1);
  367. }
  368. if (srst == 1)
  369. {
  370. jlink_simple_command(EMU_CMD_HW_RESET0);
  371. }
  372. if (trst == 1)
  373. {
  374. jlink_simple_command(EMU_CMD_HW_TRST0);
  375. }
  376. if (trst == 0)
  377. {
  378. jlink_simple_command(EMU_CMD_HW_TRST1);
  379. }
  380. }
  381. static void jlink_simple_command(uint8_t command)
  382. {
  383. int result;
  384. DEBUG_JTAG_IO("0x%02x", command);
  385. usb_out_buffer[0] = command;
  386. result = jlink_usb_write(jlink_handle, 1);
  387. if (result != 1)
  388. {
  389. LOG_ERROR("J-Link command 0x%02x failed (%d)", command, result);
  390. }
  391. }
  392. static int jlink_get_status(void)
  393. {
  394. int result;
  395. jlink_simple_command(EMU_CMD_GET_STATE);
  396. result = jlink_usb_read(jlink_handle, 8);
  397. if (result != 8)
  398. {
  399. LOG_ERROR("J-Link command EMU_CMD_GET_STATE failed (%d)\n", result);
  400. return ERROR_JTAG_DEVICE_ERROR;
  401. }
  402. int vref = usb_in_buffer[0] + (usb_in_buffer[1] << 8);
  403. LOG_INFO("Vref = %d.%d TCK = %d TDI = %d TDO = %d TMS = %d SRST = %d TRST = %d\n", \
  404. vref / 1000, vref % 1000, \
  405. usb_in_buffer[2], usb_in_buffer[3], usb_in_buffer[4], \
  406. usb_in_buffer[5], usb_in_buffer[6], usb_in_buffer[7]);
  407. if (vref < 1500)
  408. LOG_ERROR("Vref too low. Check Target Power\n");
  409. return ERROR_OK;
  410. }
  411. static int jlink_get_version_info(void)
  412. {
  413. int result;
  414. int len;
  415. uint32_t jlink_caps, jlink_max_size;
  416. /* query hardware version */
  417. jlink_simple_command(EMU_CMD_VERSION);
  418. result = jlink_usb_read(jlink_handle, 2);
  419. if (2 != result)
  420. {
  421. LOG_ERROR("J-Link command EMU_CMD_VERSION failed (%d)\n", result);
  422. return ERROR_JTAG_DEVICE_ERROR;
  423. }
  424. len = buf_get_u32(usb_in_buffer, 0, 16);
  425. if (len > JLINK_IN_BUFFER_SIZE)
  426. {
  427. LOG_ERROR("J-Link command EMU_CMD_VERSION impossible return length 0x%0x", len);
  428. len = JLINK_IN_BUFFER_SIZE;
  429. }
  430. result = jlink_usb_read(jlink_handle, len);
  431. if (result != len)
  432. {
  433. LOG_ERROR("J-Link command EMU_CMD_VERSION failed (%d)\n", result);
  434. return ERROR_JTAG_DEVICE_ERROR;
  435. }
  436. usb_in_buffer[result] = 0;
  437. LOG_INFO("%s", (char *)usb_in_buffer);
  438. /* query hardware capabilities */
  439. jlink_simple_command(EMU_CMD_GET_CAPS);
  440. result = jlink_usb_read(jlink_handle, 4);
  441. if (4 != result)
  442. {
  443. LOG_ERROR("J-Link command EMU_CMD_GET_CAPS failed (%d)\n", result);
  444. return ERROR_JTAG_DEVICE_ERROR;
  445. }
  446. jlink_caps = buf_get_u32(usb_in_buffer, 0, 32);
  447. LOG_INFO("JLink caps 0x%x", (unsigned)jlink_caps);
  448. if (jlink_caps & (1 << EMU_CAP_GET_HW_VERSION))
  449. {
  450. /* query hardware version */
  451. jlink_simple_command(EMU_CMD_GET_HW_VERSION);
  452. result = jlink_usb_read(jlink_handle, 4);
  453. if (4 != result)
  454. {
  455. LOG_ERROR("J-Link command EMU_CMD_GET_HW_VERSION failed (%d)\n", result);
  456. return ERROR_JTAG_DEVICE_ERROR;
  457. }
  458. uint32_t jlink_hw_version = buf_get_u32(usb_in_buffer, 0, 32);
  459. uint32_t major_revision = (jlink_hw_version / 10000) % 100;
  460. if (major_revision >= 5)
  461. jlink_hw_jtag_version = 3;
  462. LOG_INFO("JLink hw version %i", (int)jlink_hw_version);
  463. }
  464. if (jlink_caps & (1 << EMU_CAP_GET_MAX_BLOCK_SIZE))
  465. {
  466. /* query hardware maximum memory block */
  467. jlink_simple_command(EMU_CMD_GET_MAX_MEM_BLOCK);
  468. result = jlink_usb_read(jlink_handle, 4);
  469. if (4 != result)
  470. {
  471. LOG_ERROR("J-Link command EMU_CMD_GET_MAX_MEM_BLOCK failed (%d)\n", result);
  472. return ERROR_JTAG_DEVICE_ERROR;
  473. }
  474. jlink_max_size = buf_get_u32(usb_in_buffer, 0, 32);
  475. LOG_INFO("JLink max mem block %i", (int)jlink_max_size);
  476. }
  477. return ERROR_OK;
  478. }
  479. COMMAND_HANDLER(jlink_handle_jlink_info_command)
  480. {
  481. if (jlink_get_version_info() == ERROR_OK)
  482. {
  483. /* attempt to get status */
  484. jlink_get_status();
  485. }
  486. return ERROR_OK;
  487. }
  488. COMMAND_HANDLER(jlink_handle_jlink_hw_jtag_command)
  489. {
  490. switch (CMD_ARGC) {
  491. case 0:
  492. command_print(CMD_CTX, "jlink hw jtag %i", jlink_hw_jtag_version);
  493. break;
  494. case 1: {
  495. int request_version = atoi(CMD_ARGV[0]);
  496. switch (request_version) {
  497. case 2: case 3:
  498. jlink_hw_jtag_version = request_version;
  499. break;
  500. default:
  501. return ERROR_COMMAND_SYNTAX_ERROR;
  502. }
  503. break;
  504. }
  505. default:
  506. return ERROR_COMMAND_SYNTAX_ERROR;
  507. }
  508. return ERROR_OK;
  509. }
  510. static const struct command_registration jlink_command_handlers[] = {
  511. {
  512. .name = "jlink_info",
  513. .handler = &jlink_handle_jlink_info_command,
  514. .mode = COMMAND_EXEC,
  515. .help = "show jlink info",
  516. },
  517. {
  518. .name = "jlink_hw_jtag",
  519. .handler = &jlink_handle_jlink_hw_jtag_command,
  520. .mode = COMMAND_EXEC,
  521. .help = "access J-Link HW JTAG command version",
  522. .usage = "[2|3]",
  523. },
  524. COMMAND_REGISTRATION_DONE
  525. };
  526. struct jtag_interface jlink_interface = {
  527. .name = "jlink",
  528. .commands = jlink_command_handlers,
  529. .execute_queue = jlink_execute_queue,
  530. .speed = jlink_speed,
  531. .speed_div = jlink_speed_div,
  532. .khz = jlink_khz,
  533. .init = jlink_init,
  534. .quit = jlink_quit,
  535. };
  536. /***************************************************************************/
  537. /* J-Link tap functions */
  538. static unsigned tap_length = 0;
  539. static uint8_t tms_buffer[JLINK_TAP_BUFFER_SIZE];
  540. static uint8_t tdi_buffer[JLINK_TAP_BUFFER_SIZE];
  541. static uint8_t tdo_buffer[JLINK_TAP_BUFFER_SIZE];
  542. struct pending_scan_result {
  543. int first; /* First bit position in tdo_buffer to read */
  544. int length; /* Number of bits to read */
  545. struct scan_command *command; /* Corresponding scan command */
  546. uint8_t *buffer;
  547. };
  548. #define MAX_PENDING_SCAN_RESULTS 256
  549. static int pending_scan_results_length;
  550. static struct pending_scan_result pending_scan_results_buffer[MAX_PENDING_SCAN_RESULTS];
  551. static void jlink_tap_init(void)
  552. {
  553. tap_length = 0;
  554. pending_scan_results_length = 0;
  555. }
  556. static void jlink_tap_ensure_space(int scans, int bits)
  557. {
  558. int available_scans = MAX_PENDING_SCAN_RESULTS - pending_scan_results_length;
  559. int available_bits = JLINK_TAP_BUFFER_SIZE * 8 - tap_length - 32;
  560. if (scans > available_scans || bits > available_bits)
  561. {
  562. jlink_tap_execute();
  563. }
  564. }
  565. static void jlink_tap_append_step(int tms, int tdi)
  566. {
  567. int index = tap_length / 8;
  568. if (index >= JLINK_TAP_BUFFER_SIZE)
  569. {
  570. LOG_ERROR("jlink_tap_append_step: overflow");
  571. *(uint32_t *)0xFFFFFFFF = 0;
  572. exit(-1);
  573. }
  574. int bit_index = tap_length % 8;
  575. uint8_t bit = 1 << bit_index;
  576. // we do not pad TMS, so be sure to initialize all bits
  577. if (0 == bit_index)
  578. {
  579. tms_buffer[index] = tdi_buffer[index] = 0;
  580. }
  581. if (tms)
  582. tms_buffer[index] |= bit;
  583. else
  584. tms_buffer[index] &= ~bit;
  585. if (tdi)
  586. tdi_buffer[index] |= bit;
  587. else
  588. tdi_buffer[index] &= ~bit;
  589. tap_length++;
  590. }
  591. static void jlink_tap_append_scan(int length, uint8_t *buffer, struct scan_command *command)
  592. {
  593. struct pending_scan_result *pending_scan_result =
  594. &pending_scan_results_buffer[pending_scan_results_length];
  595. int i;
  596. pending_scan_result->first = tap_length;
  597. pending_scan_result->length = length;
  598. pending_scan_result->command = command;
  599. pending_scan_result->buffer = buffer;
  600. for (i = 0; i < length; i++)
  601. {
  602. int tms = (i < (length - 1)) ? 0 : 1;
  603. int tdi = (buffer[i / 8] & (1 << (i % 8))) != 0;
  604. jlink_tap_append_step(tms, tdi);
  605. }
  606. pending_scan_results_length++;
  607. }
  608. /* Pad and send a tap sequence to the device, and receive the answer.
  609. * For the purpose of padding we assume that we are in idle or pause state. */
  610. static int jlink_tap_execute(void)
  611. {
  612. int byte_length;
  613. int i;
  614. int result;
  615. if (!tap_length)
  616. return ERROR_OK;
  617. /* JLink returns an extra NULL in packet when size of incoming
  618. * message is a multiple of 64, creates problems with USB comms.
  619. * WARNING: This will interfere with tap state counting. */
  620. while ((DIV_ROUND_UP(tap_length, 8) % 64) == 0)
  621. {
  622. jlink_tap_append_step((tap_get_state() == TAP_RESET)?1:0, 0);
  623. }
  624. // number of full bytes (plus one if some would be left over)
  625. byte_length = DIV_ROUND_UP(tap_length, 8);
  626. bool use_jtag3 = jlink_hw_jtag_version >= 3;
  627. usb_out_buffer[0] = use_jtag3 ? EMU_CMD_HW_JTAG3 : EMU_CMD_HW_JTAG2;
  628. usb_out_buffer[1] = 0;
  629. usb_out_buffer[2] = (tap_length >> 0) & 0xff;
  630. usb_out_buffer[3] = (tap_length >> 8) & 0xff;
  631. memcpy(usb_out_buffer + 4, tms_buffer, byte_length);
  632. memcpy(usb_out_buffer + 4 + byte_length, tdi_buffer, byte_length);
  633. jlink_last_state = jtag_debug_state_machine(tms_buffer, tdi_buffer,
  634. tap_length, jlink_last_state);
  635. result = jlink_usb_message(jlink_handle, 4 + 2 * byte_length, byte_length);
  636. if (result != byte_length)
  637. {
  638. LOG_ERROR("jlink_tap_execute, wrong result %d (expected %d)", result, byte_length);
  639. jlink_tap_init();
  640. return ERROR_JTAG_QUEUE_FAILED;
  641. }
  642. memcpy(tdo_buffer, usb_in_buffer, byte_length);
  643. for (i = 0; i < pending_scan_results_length; i++)
  644. {
  645. struct pending_scan_result *pending_scan_result = &pending_scan_results_buffer[i];
  646. uint8_t *buffer = pending_scan_result->buffer;
  647. int length = pending_scan_result->length;
  648. int first = pending_scan_result->first;
  649. struct scan_command *command = pending_scan_result->command;
  650. /* Copy to buffer */
  651. buf_set_buf(tdo_buffer, first, buffer, 0, length);
  652. DEBUG_JTAG_IO("pending scan result, length = %d", length);
  653. #ifdef _DEBUG_USB_COMMS_
  654. jlink_debug_buffer(buffer, DIV_ROUND_UP(length, 8));
  655. #endif
  656. if (jtag_read_buffer(buffer, command) != ERROR_OK)
  657. {
  658. jlink_tap_init();
  659. return ERROR_JTAG_QUEUE_FAILED;
  660. }
  661. if (pending_scan_result->buffer != NULL)
  662. {
  663. free(pending_scan_result->buffer);
  664. }
  665. }
  666. jlink_tap_init();
  667. return ERROR_OK;
  668. }
  669. /*****************************************************************************/
  670. /* JLink USB low-level functions */
  671. static struct jlink* jlink_usb_open()
  672. {
  673. usb_init();
  674. const uint16_t vids[] = { VID, 0 };
  675. const uint16_t pids[] = { PID, 0 };
  676. struct usb_dev_handle *dev;
  677. if (jtag_usb_open(vids, pids, &dev) != ERROR_OK)
  678. return NULL;
  679. /* BE ***VERY CAREFUL*** ABOUT MAKING CHANGES IN THIS
  680. * AREA!!!!!!!!!!! The behavior of libusb is not completely
  681. * consistent across Windows, Linux, and Mac OS X platforms.
  682. * The actions taken in the following compiler conditionals may
  683. * not agree with published documentation for libusb, but were
  684. * found to be necessary through trials and tribulations. Even
  685. * little tweaks can break one or more platforms, so if you do
  686. * make changes test them carefully on all platforms before
  687. * committing them!
  688. */
  689. #if IS_WIN32 == 0
  690. usb_reset(dev);
  691. #if IS_DARWIN == 0
  692. int timeout = 5;
  693. /* reopen jlink after usb_reset
  694. * on win32 this may take a second or two to re-enumerate */
  695. int retval;
  696. while ((retval = jtag_usb_open(vids, pids, &dev)) != ERROR_OK)
  697. {
  698. usleep(1000);
  699. timeout--;
  700. if (!timeout) {
  701. break;
  702. }
  703. }
  704. if (ERROR_OK != retval)
  705. return NULL;
  706. #endif
  707. #endif
  708. /* usb_set_configuration required under win32 */
  709. struct usb_device *udev = usb_device(dev);
  710. usb_set_configuration(dev, udev->config[0].bConfigurationValue);
  711. usb_claim_interface(dev, 0);
  712. #if 0
  713. /*
  714. * This makes problems under Mac OS X. And is not needed
  715. * under Windows. Hopefully this will not break a linux build
  716. */
  717. usb_set_altinterface(result->usb_handle, 0);
  718. #endif
  719. struct usb_interface *iface = udev->config->interface;
  720. struct usb_interface_descriptor *desc = iface->altsetting;
  721. for (int i = 0; i < desc->bNumEndpoints; i++)
  722. {
  723. uint8_t epnum = desc->endpoint[i].bEndpointAddress;
  724. bool is_input = epnum & 0x80;
  725. LOG_DEBUG("usb ep %s %02x", is_input ? "in" : "out", epnum);
  726. if (is_input)
  727. jlink_read_ep = epnum;
  728. else
  729. jlink_write_ep = epnum;
  730. }
  731. struct jlink *result = malloc(sizeof(struct jlink));
  732. result->usb_handle = dev;
  733. return result;
  734. }
  735. static void jlink_usb_close(struct jlink *jlink)
  736. {
  737. usb_close(jlink->usb_handle);
  738. free(jlink);
  739. }
  740. /* Send a message and receive the reply. */
  741. static int jlink_usb_message(struct jlink *jlink, int out_length, int in_length)
  742. {
  743. int result;
  744. result = jlink_usb_write(jlink, out_length);
  745. if (result != out_length)
  746. {
  747. LOG_ERROR("usb_bulk_write failed (requested=%d, result=%d)",
  748. out_length, result);
  749. return ERROR_JTAG_DEVICE_ERROR;
  750. }
  751. result = jlink_usb_read(jlink, in_length);
  752. if ((result != in_length) && (result != (in_length + 1)))
  753. {
  754. LOG_ERROR("usb_bulk_read failed (requested=%d, result=%d)",
  755. in_length, result);
  756. return ERROR_JTAG_DEVICE_ERROR;
  757. }
  758. if (jlink_hw_jtag_version < 3)
  759. return result;
  760. int result2 = ERROR_OK;
  761. if (result == in_length)
  762. {
  763. /* Must read the result from the EMU too */
  764. result2 = jlink_usb_read_emu_result(jlink);
  765. if (1 != result2)
  766. {
  767. LOG_ERROR("jlink_usb_read_emu_result retried requested = 1, result=%d, in_length=%i", result2,in_length);
  768. /* Try again once, should only happen if (in_length%64 == 0) */
  769. result2 = jlink_usb_read_emu_result(jlink);
  770. if (1 != result2)
  771. {
  772. LOG_ERROR("jlink_usb_read_emu_result failed "
  773. "(requested = 1, result=%d)", result2);
  774. return ERROR_JTAG_DEVICE_ERROR;
  775. }
  776. }
  777. /* Check the result itself */
  778. result2 = usb_emu_result_buffer[0];
  779. }
  780. else
  781. {
  782. /* Save the result, then remove it from return value */
  783. result2 = usb_in_buffer[result--];
  784. }
  785. if (result2)
  786. {
  787. LOG_ERROR("jlink_usb_message failed with result=%d)", result2);
  788. return ERROR_JTAG_DEVICE_ERROR;
  789. }
  790. return result;
  791. }
  792. /* calls the given usb_bulk_* function, allowing for the data to trickle in with some timeouts */
  793. static int usb_bulk_with_retries(
  794. int (*f)(usb_dev_handle *, int, char *, int, int),
  795. usb_dev_handle *dev, int ep,
  796. char *bytes, int size, int timeout)
  797. {
  798. int tries = 3, count = 0;
  799. while (tries && (count < size))
  800. {
  801. int result = f(dev, ep, bytes + count, size - count, timeout);
  802. if (result > 0)
  803. count += result;
  804. else if ((-ETIMEDOUT != result) || !--tries)
  805. return result;
  806. }
  807. return count;
  808. }
  809. static int wrap_usb_bulk_write(usb_dev_handle *dev, int ep,
  810. char *buff, int size, int timeout)
  811. {
  812. /* usb_bulk_write() takes const char *buff */
  813. return usb_bulk_write(dev, ep, buff, size, timeout);
  814. }
  815. static inline int usb_bulk_write_ex(usb_dev_handle *dev, int ep,
  816. char *bytes, int size, int timeout)
  817. {
  818. return usb_bulk_with_retries(&wrap_usb_bulk_write,
  819. dev, ep, bytes, size, timeout);
  820. }
  821. static inline int usb_bulk_read_ex(usb_dev_handle *dev, int ep,
  822. char *bytes, int size, int timeout)
  823. {
  824. return usb_bulk_with_retries(&usb_bulk_read,
  825. dev, ep, bytes, size, timeout);
  826. }
  827. /* Write data from out_buffer to USB. */
  828. static int jlink_usb_write(struct jlink *jlink, int out_length)
  829. {
  830. int result;
  831. if (out_length > JLINK_OUT_BUFFER_SIZE)
  832. {
  833. LOG_ERROR("jlink_write illegal out_length=%d (max=%d)", out_length, JLINK_OUT_BUFFER_SIZE);
  834. return -1;
  835. }
  836. result = usb_bulk_write_ex(jlink->usb_handle, jlink_write_ep,
  837. (char *)usb_out_buffer, out_length, JLINK_USB_TIMEOUT);
  838. DEBUG_JTAG_IO("jlink_usb_write, out_length = %d, result = %d", out_length, result);
  839. #ifdef _DEBUG_USB_COMMS_
  840. jlink_debug_buffer(usb_out_buffer, out_length);
  841. #endif
  842. return result;
  843. }
  844. /* Read data from USB into in_buffer. */
  845. static int jlink_usb_read(struct jlink *jlink, int expected_size)
  846. {
  847. int result = usb_bulk_read_ex(jlink->usb_handle, jlink_read_ep,
  848. (char *)usb_in_buffer, expected_size, JLINK_USB_TIMEOUT);
  849. DEBUG_JTAG_IO("jlink_usb_read, result = %d", result);
  850. #ifdef _DEBUG_USB_COMMS_
  851. jlink_debug_buffer(usb_in_buffer, result);
  852. #endif
  853. return result;
  854. }
  855. /* Read the result from the previous EMU cmd into result_buffer. */
  856. static int jlink_usb_read_emu_result(struct jlink *jlink)
  857. {
  858. int result = usb_bulk_read_ex(jlink->usb_handle, jlink_read_ep,
  859. (char *)usb_emu_result_buffer, 1 /* JLINK_EMU_RESULT_BUFFER_SIZE */,
  860. JLINK_USB_TIMEOUT);
  861. DEBUG_JTAG_IO("jlink_usb_read_result, result = %d", result);
  862. #ifdef _DEBUG_USB_COMMS_
  863. jlink_debug_buffer(usb_emu_result_buffer, result);
  864. #endif
  865. return result;
  866. }
  867. #ifdef _DEBUG_USB_COMMS_
  868. #define BYTES_PER_LINE 16
  869. static void jlink_debug_buffer(uint8_t *buffer, int length)
  870. {
  871. char line[81];
  872. char s[4];
  873. int i;
  874. int j;
  875. for (i = 0; i < length; i += BYTES_PER_LINE)
  876. {
  877. snprintf(line, 5, "%04x", i);
  878. for (j = i; j < i + BYTES_PER_LINE && j < length; j++)
  879. {
  880. snprintf(s, 4, " %02x", buffer[j]);
  881. strcat(line, s);
  882. }
  883. LOG_DEBUG("%s", line);
  884. }
  885. }
  886. #endif