You can subscribe to this list here.
2008 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
(75) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2009 |
Jan
(70) |
Feb
(20) |
Mar
(52) |
Apr
(149) |
May
(387) |
Jun
(466) |
Jul
(133) |
Aug
(87) |
Sep
(122) |
Oct
(140) |
Nov
(185) |
Dec
(105) |
2010 |
Jan
(85) |
Feb
(45) |
Mar
(75) |
Apr
(17) |
May
(41) |
Jun
(52) |
Jul
(33) |
Aug
(29) |
Sep
(36) |
Oct
(15) |
Nov
(26) |
Dec
(34) |
2011 |
Jan
(26) |
Feb
(25) |
Mar
(26) |
Apr
(29) |
May
(20) |
Jun
(27) |
Jul
(15) |
Aug
(32) |
Sep
(13) |
Oct
(64) |
Nov
(60) |
Dec
(10) |
2012 |
Jan
(64) |
Feb
(63) |
Mar
(39) |
Apr
(43) |
May
(54) |
Jun
(11) |
Jul
(30) |
Aug
(45) |
Sep
(11) |
Oct
(70) |
Nov
(24) |
Dec
(23) |
2013 |
Jan
(17) |
Feb
(8) |
Mar
(35) |
Apr
(40) |
May
(20) |
Jun
(24) |
Jul
(36) |
Aug
(25) |
Sep
(42) |
Oct
(40) |
Nov
(9) |
Dec
(21) |
2014 |
Jan
(29) |
Feb
(24) |
Mar
(60) |
Apr
(22) |
May
(22) |
Jun
(46) |
Jul
(11) |
Aug
(23) |
Sep
(26) |
Oct
(10) |
Nov
(14) |
Dec
(2) |
2015 |
Jan
(28) |
Feb
(47) |
Mar
(33) |
Apr
(58) |
May
(5) |
Jun
(1) |
Jul
|
Aug
(8) |
Sep
(12) |
Oct
(25) |
Nov
(58) |
Dec
(21) |
2016 |
Jan
(12) |
Feb
(40) |
Mar
(2) |
Apr
(1) |
May
(67) |
Jun
(2) |
Jul
(5) |
Aug
(36) |
Sep
|
Oct
(24) |
Nov
(17) |
Dec
(50) |
2017 |
Jan
(14) |
Feb
(16) |
Mar
(2) |
Apr
(35) |
May
(14) |
Jun
(16) |
Jul
(3) |
Aug
(3) |
Sep
|
Oct
(19) |
Nov
|
Dec
(16) |
2018 |
Jan
(55) |
Feb
(11) |
Mar
(34) |
Apr
(14) |
May
(4) |
Jun
(20) |
Jul
(39) |
Aug
(16) |
Sep
(17) |
Oct
(16) |
Nov
(20) |
Dec
(30) |
2019 |
Jan
(29) |
Feb
(24) |
Mar
(37) |
Apr
(26) |
May
(19) |
Jun
(21) |
Jul
(2) |
Aug
(3) |
Sep
(9) |
Oct
(12) |
Nov
(12) |
Dec
(12) |
2020 |
Jan
(47) |
Feb
(36) |
Mar
(54) |
Apr
(44) |
May
(37) |
Jun
(19) |
Jul
(32) |
Aug
(13) |
Sep
(16) |
Oct
(24) |
Nov
(32) |
Dec
(11) |
2021 |
Jan
(14) |
Feb
(5) |
Mar
(40) |
Apr
(32) |
May
(42) |
Jun
(31) |
Jul
(29) |
Aug
(47) |
Sep
(38) |
Oct
(17) |
Nov
(74) |
Dec
(33) |
2022 |
Jan
(11) |
Feb
(15) |
Mar
(40) |
Apr
(21) |
May
(39) |
Jun
(44) |
Jul
(19) |
Aug
(46) |
Sep
(79) |
Oct
(35) |
Nov
(21) |
Dec
(15) |
2023 |
Jan
(56) |
Feb
(13) |
Mar
(43) |
Apr
(28) |
May
(60) |
Jun
(15) |
Jul
(29) |
Aug
(28) |
Sep
(32) |
Oct
(21) |
Nov
(42) |
Dec
(39) |
2024 |
Jan
(35) |
Feb
(17) |
Mar
(28) |
Apr
(7) |
May
(14) |
Jun
(35) |
Jul
(30) |
Aug
(35) |
Sep
(30) |
Oct
(28) |
Nov
(38) |
Dec
(18) |
2025 |
Jan
(21) |
Feb
(28) |
Mar
(36) |
Apr
(35) |
May
(34) |
Jun
(58) |
Jul
(9) |
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
From: <oh...@ma...> - 2009-01-14 19:41:12
|
Author: oharboe Date: 2009-01-14 19:41:09 +0100 (Wed, 14 Jan 2009) New Revision: 1318 Added: trunk/src/target/board/imx27ads.cfg Log: Alan Carvalho de Assis <ac...@gm...> cfg file to initialize the iMX27ADS board. Added: trunk/src/target/board/imx27ads.cfg =================================================================== --- trunk/src/target/board/imx27ads.cfg 2009-01-14 15:25:45 UTC (rev 1317) +++ trunk/src/target/board/imx27ads.cfg 2009-01-14 18:41:09 UTC (rev 1318) @@ -0,0 +1,75 @@ +# The IMX27 ADS eval board has a single IMX27 chip +# Note: tested on IMX27ADS Board REV-2.6 and REV-2.8 +source [find target/imx27.cfg] +$_TARGETNAME configure -event gdb-attach { reset init } +$_TARGETNAME configure -event reset-init { imx27ads_init } + +# The IMX27 ADS board has a NOR flash on CS0 +flash_bank cfi 0xc0000000 0x00200000 2 2 0 + +proc imx27ads_init { } { + # This setup puts RAM at 0xA0000000 + + # reset the board correctly + reset run + reset halt + + mww 0x10000000 0x20040304 + mww 0x10020000 0x00000000 + mww 0x10000004 0xDFFBFCFB + mww 0x10020004 0xFFFFFFFF + + sleep 100 + + # ======================================== + # Configure DDR on CSD0 -- initial reset + # ======================================== + mww 0xD8001010 0x00000008 + + # ======================================== + # Configure PSRAM on CS5 + # ======================================== + mww 0xd8002050 0x0000dcf6 + mww 0xd8002054 0x444a4541 + mww 0xd8002058 0x44443302 + + # ======================================== + # Configure16 bit NorFlash on CS0 + # ======================================== + mww 0xd8002000 0x0000CC03 + mww 0xd8002004 0xa0330D01 + mww 0xd8002008 0x00220800 + + # ======================================== + # Configure CPLD on CS4 + # ======================================== + mww 0xd8002040 0x0000DCF6 + mww 0xd8002044 0x444A4541 + mww 0xd8002048 0x44443302 + + # ======================================== + # Configure DDR on CSD0 -- wait 5000 cycle + # ======================================== + mww 0x10027828 0x55555555 + mww 0x10027830 0x55555555 + mww 0x10027834 0x55555555 + mww 0x10027838 0x00005005 + mww 0x1002783C 0x15555555 + + mww 0xD8001010 0x00000004 + + mww 0xD8001004 0x00795729 + + mww 0xD8001000 0x92200000 + mww 0xA0000F00 0x0 + + mww 0xD8001000 0xA2200000 + mww 0xA0000F00 0x0 + mww 0xA0000F00 0x0 + + mww 0xD8001000 0xB2200000 + mwb 0xA0000033 0xFF + mwb 0xA1000000 0xAA + + mww 0xD8001000 0x82228085 +} |
From: <oh...@ma...> - 2009-01-14 16:25:46
|
Author: oharboe Date: 2009-01-14 16:25:45 +0100 (Wed, 14 Jan 2009) New Revision: 1317 Modified: trunk/src/jtag/jtag.c trunk/src/target/target/imx31.cfg Log: arm11 wip Modified: trunk/src/jtag/jtag.c =================================================================== --- trunk/src/jtag/jtag.c 2009-01-14 14:10:36 UTC (rev 1316) +++ trunk/src/jtag/jtag.c 2009-01-14 15:25:45 UTC (rev 1317) @@ -40,6 +40,7 @@ */ int jtag_error=ERROR_OK; + typedef struct cmd_queue_page_s { void *address; @@ -1364,6 +1365,11 @@ return retval; } +static const char *jtag_tap_name(jtag_tap_t *tap) +{ + return (tap == NULL) ? "(unknown)" : tap->dotted_name; +} + int jtag_check_value(u8 *captured, void *priv, scan_field_t *field) { int retval = ERROR_OK; @@ -1382,7 +1388,7 @@ * acknowledged the error */ LOG_WARNING("TAP %s:", - (field->tap == NULL) ? "(unknown)" : field->tap->dotted_name ); + jtag_tap_name(field->tap)); if (compare_failed) { char *captured_char = buf_to_str(captured, (num_bits > 64) ? 64 : num_bits, 16); @@ -1698,17 +1704,18 @@ tap = NULL; chain_pos = 0; + int val; for(;;){ tap = jtag_NextEnabledTap(tap); if( tap == NULL ){ break; } - - if (buf_get_u32(ir_test, chain_pos, 2) != 0x1) + val = buf_get_u32(ir_test, chain_pos, 2); + if (val != 0x1) { char *cbuf = buf_to_str(ir_test, total_ir_length, 16); - LOG_ERROR("Error validating JTAG scan chain, IR mismatch, scan returned 0x%s", cbuf); + LOG_ERROR("Could not validate JTAG scan chain, IR mismatch, scan returned 0x%s. tap=%s pos=%d expected 0x1 got %0x", cbuf, jtag_tap_name(tap), chain_pos, val); free(cbuf); free(ir_test); return ERROR_JTAG_INIT_FAILED; @@ -1716,10 +1723,11 @@ chain_pos += tap->ir_length; } - if (buf_get_u32(ir_test, chain_pos, 2) != 0x3) + val = buf_get_u32(ir_test, chain_pos, 2); + if (val != 0x3) { char *cbuf = buf_to_str(ir_test, total_ir_length, 16); - LOG_ERROR("Error validating JTAG scan chain, IR mismatch, scan returned 0x%s", cbuf); + LOG_ERROR("Could not validate end of JTAG scan chain, IR mismatch, scan returned 0x%s. pos=%d expected 0x3 got %0x", cbuf, chain_pos, val); free(cbuf); free(ir_test); return ERROR_JTAG_INIT_FAILED; @@ -2249,7 +2257,7 @@ if (jtag_validate_chain() != ERROR_OK) { - LOG_ERROR("Could not validate JTAG chain, continuing anyway..."); + LOG_WARNING("Could not validate JTAG chain, continuing anyway..."); } return ERROR_OK; @@ -2953,6 +2961,7 @@ } } + /* map state number to SVF state string */ const char* jtag_state_name(enum tap_state state) { @@ -2981,3 +2990,4 @@ return ret; } + Modified: trunk/src/target/target/imx31.cfg =================================================================== --- trunk/src/target/target/imx31.cfg 2009-01-14 14:10:36 UTC (rev 1316) +++ trunk/src/target/target/imx31.cfg 2009-01-14 15:25:45 UTC (rev 1317) @@ -45,14 +45,14 @@ # SDMA_BYPASS - disables SDMA - # # Per ARM: DDI0211J_arm1136_r1p5_trm.pdf - the ARM 1136 as a 5 bit IR register -jtag newtap $_CHIPNAME cpu -irlen 5 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID +jtag newtap $_CHIPNAME cpu -irlen 5 -ircapture 0x1 -irmask 0x1f -expected-id $_CPUTAPID # No IDCODE for this TAP jtag newtap $_CHIPNAME whatchacallit -irlen 4 -ircapture 0 -irmask 0xf -expected-id 0x0 # Per section 40.17.1, table 40-85 the IR register is 4 bits # But this conflicts with Diagram 6-13, "3bits ir and drs" -jtag newtap $_CHIPNAME smda -irlen 5 -ircapture 0x1 -irmask 0xf -expected-id $_SDMATAPID +jtag newtap $_CHIPNAME smda -irlen 5 -ircapture 0x1 -irmask 0x1f -expected-id $_SDMATAPID set _TARGETNAME [format "%s.cpu" $_CHIPNAME] target create $_TARGETNAME arm11 -endian $_ENDIAN -chain-position $_TARGETNAME |
From: <oh...@ma...> - 2009-01-14 15:10:37
|
Author: oharboe Date: 2009-01-14 15:10:36 +0100 (Wed, 14 Jan 2009) New Revision: 1316 Modified: trunk/src/target/target/imx31.cfg Log: Alan Carvalho de Assis <ac...@gm...> small fix to move us in the right direction. Modified: trunk/src/target/target/imx31.cfg =================================================================== --- trunk/src/target/target/imx31.cfg 2009-01-13 14:26:19 UTC (rev 1315) +++ trunk/src/target/target/imx31.cfg 2009-01-14 14:10:36 UTC (rev 1316) @@ -45,14 +45,14 @@ # SDMA_BYPASS - disables SDMA - # # Per ARM: DDI0211J_arm1136_r1p5_trm.pdf - the ARM 1136 as a 5 bit IR register -jtag newtap $_CHIPNAME cpu -irlen 5 -ircapture 0x1e -irmask 0x1f -expected-id $_CPUTAPID +jtag newtap $_CHIPNAME cpu -irlen 5 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID # No IDCODE for this TAP jtag newtap $_CHIPNAME whatchacallit -irlen 4 -ircapture 0 -irmask 0xf -expected-id 0x0 # Per section 40.17.1, table 40-85 the IR register is 4 bits # But this conflicts with Diagram 6-13, "3bits ir and drs" -jtag newtap $_CHIPNAME smda -irlen 4 -ircapture 0xe -irmask 0xf -expected-id $_SDMATAPID +jtag newtap $_CHIPNAME smda -irlen 5 -ircapture 0x1 -irmask 0xf -expected-id $_SDMATAPID set _TARGETNAME [format "%s.cpu" $_CHIPNAME] target create $_TARGETNAME arm11 -endian $_ENDIAN -chain-position $_TARGETNAME |
From: ntfreak at B. <nt...@ma...> - 2009-01-13 15:26:20
|
Author: ntfreak Date: 2009-01-13 15:26:19 +0100 (Tue, 13 Jan 2009) New Revision: 1315 Modified: trunk/configure.in Log: - fix LDFLAGS typo in configure.in Thanks Francois Lorrain Modified: trunk/configure.in =================================================================== --- trunk/configure.in 2009-01-13 13:45:08 UTC (rev 1314) +++ trunk/configure.in 2009-01-13 14:26:19 UTC (rev 1315) @@ -44,7 +44,6 @@ # Let make expand exec_prefix. test x"$OCDxprefix" = xNONE && OCDxprefix="$OCDprefix" - # what matters is the "exec-prefix" if test "$OCDxprefix" != "$ac_default_prefix" then @@ -122,7 +121,6 @@ true ] ) - AC_ARG_WITH(ftd2xx-linux-tardir, AS_HELP_STRING([--with-ftd2xx-linux-tardir], [Where (Linux/Unix) the tar file from ftdichip.com was unpacked <default=search>]), @@ -145,7 +143,6 @@ ] ) - AC_ARG_WITH(ftd2xx-lib, AS_HELP_STRING([--with-ftd2xx-lib], [Use static or shared ftd2xx libs on default static]), [ @@ -263,7 +260,6 @@ AS_HELP_STRING([--enable-rlink], [Enable building support for the Raisonance RLink JTAG Programmer]), [build_rlink=$enableval], [build_rlink=no]) - case $host in *-cygwin*) is_win32=yes @@ -314,7 +310,6 @@ AC_DEFINE(BUILD_DUMMY, 0, [0 if you don't want dummy driver.]) fi - if test $build_ep93xx = yes; then build_bitbang=yes AC_DEFINE(BUILD_EP93XX, 1, [1 if you want ep93xx.]) @@ -464,12 +459,12 @@ # And calculate the LDFLAGS for the machine case "$host_cpu" in i?86|x86_*) - LDFLAGS="$LFLAGS -L$with_ftd2xx_win32_zipdir/i386" + LDFLAGS="$LDFLAGS -L$with_ftd2xx_win32_zipdir/i386" LIBS="$LIBS -lftd2xx" f=$with_ftd2xx_win32_zipdir/i386/ftd2xx.lib ;; amd64) - LDFLAGS="$LFLAGS -L$with_ftd2xx_win32_zipdir/amd64" + LDFLAGS="$LDFLAGS -L$with_ftd2xx_win32_zipdir/amd64" LIBS="$LIBS -lftd2xx" f=$with_ftd2xx_win32_zipdir/amd64/ftd2xx.lib ;; @@ -487,7 +482,6 @@ fi fi - if test $is_win32 = no; then if test "${with_ftd2xx_win32_zipdir+set}" = set @@ -629,9 +623,7 @@ LDFLAGS=$LDFLAGS_SAVE CFLAGS=$CFLAGS_SAVE fi - - AM_CONFIG_HEADER(config.h) AM_INIT_AUTOMAKE(openocd, 1.0) @@ -713,6 +705,4 @@ AC_MSG_RESULT([$EXEEXT_FOR_BUILD]) AC_SUBST(EXEEXT_FOR_BUILD) -#AC_SUBST(WITH_FTD2XX, $with_ftd2xx) - AC_OUTPUT(Makefile src/Makefile src/helper/Makefile src/jtag/Makefile src/xsvf/Makefile src/target/Makefile src/server/Makefile src/flash/Makefile src/pld/Makefile doc/Makefile) |
From: ntfreak at B. <nt...@ma...> - 2009-01-13 14:45:11
|
Author: ntfreak Date: 2009-01-13 14:45:08 +0100 (Tue, 13 Jan 2009) New Revision: 1314 Modified: trunk/src/target/mips32.c Log: - fix mips issues with newer versions of gdb - we simply add more dummy registers Modified: trunk/src/target/mips32.c =================================================================== --- trunk/src/target/mips32.c 2009-01-13 11:33:19 UTC (rev 1313) +++ trunk/src/target/mips32.c 2009-01-13 13:45:08 UTC (rev 1314) @@ -85,18 +85,16 @@ {37, NULL, NULL}, }; -u8 mips32_gdb_dummy_fsr_value[] = {0, 0, 0, 0}; +/* number of mips dummy fp regs fp0 - fp31 + fsr and fir + * we also add 18 unknown registers to handle gdb requests */ -reg_t mips32_gdb_dummy_fsr_reg = -{ - "GDB dummy floating-point status register", mips32_gdb_dummy_fsr_value, 0, 1, 32, NULL, 0, NULL, 0 -}; +#define MIPS32NUMFPREGS 34 + 18 -u8 mips32_gdb_dummy_fir_value[] = {0, 0, 0, 0}; +u8 mips32_gdb_dummy_fp_value[] = {0, 0, 0, 0}; -reg_t mips32_gdb_dummy_fir_reg = +reg_t mips32_gdb_dummy_fp_reg = { - "GDB dummy floating-point register", mips32_gdb_dummy_fir_value, 0, 1, 32, NULL, 0, NULL, 0 + "GDB dummy floating-point register", mips32_gdb_dummy_fp_value, 0, 1, 32, NULL, 0, NULL, 0 }; int mips32_core_reg_arch_type = -1; @@ -198,8 +196,8 @@ mips32_common_t *mips32 = target->arch_info; int i; - /* include fsr/fir reg */ - *reg_list_size = MIPS32NUMCOREREGS + 2; + /* include floating point registers */ + *reg_list_size = MIPS32NUMCOREREGS + MIPS32NUMFPREGS; *reg_list = malloc(sizeof(reg_t*) * (*reg_list_size)); for (i = 0; i < MIPS32NUMCOREREGS; i++) @@ -208,9 +206,11 @@ } /* add dummy floating points regs */ - (*reg_list)[38] = &mips32_gdb_dummy_fsr_reg; - (*reg_list)[39] = &mips32_gdb_dummy_fir_reg; - + for (i = MIPS32NUMCOREREGS; i < (MIPS32NUMCOREREGS + MIPS32NUMFPREGS); i++) + { + (*reg_list)[i] = &mips32_gdb_dummy_fp_reg; + } + return ERROR_OK; } @@ -290,8 +290,7 @@ if (mips32_core_reg_arch_type == -1) mips32_core_reg_arch_type = register_reg_arch_type(mips32_get_core_reg, mips32_set_core_reg); - register_init_dummy(&mips32_gdb_dummy_fsr_reg); - register_init_dummy(&mips32_gdb_dummy_fir_reg); + register_init_dummy(&mips32_gdb_dummy_fp_reg); /* Build the process context cache */ cache->name = "mips32 registers"; |
From: ntfreak at B. <nt...@ma...> - 2009-01-13 12:33:22
|
Author: ntfreak Date: 2009-01-13 12:33:19 +0100 (Tue, 13 Jan 2009) New Revision: 1313 Modified: trunk/src/jtag/jtag.c trunk/src/target/mips32.h trunk/src/target/mips_m4k.c trunk/src/target/target/pic32mx.cfg Log: - added mips software breakpoint support - changed some jtag LOG_DEBUG to only output when _DEBUG_JTAG_IO_ defined. Makes debugging other parts of openocd not as noisy - updated correct jtag id for pic32mx Modified: trunk/src/jtag/jtag.c =================================================================== --- trunk/src/jtag/jtag.c 2009-01-09 13:04:37 UTC (rev 1312) +++ trunk/src/jtag/jtag.c 2009-01-13 11:33:19 UTC (rev 1313) @@ -40,7 +40,6 @@ */ int jtag_error=ERROR_OK; - typedef struct cmd_queue_page_s { void *address; @@ -1278,7 +1277,9 @@ bit_count = 0; +#ifdef _DEBUG_JTAG_IO_ LOG_DEBUG("num_fields: %i",cmd->num_fields); +#endif for (i = 0; i < cmd->num_fields; i++) { @@ -1295,7 +1296,9 @@ } bit_count += cmd->fields[i].num_bits; +#ifdef _DEBUG_JTAG_IO_ LOG_DEBUG("bit_count totalling: %i", bit_count ); +#endif } return bit_count; @@ -2950,7 +2953,6 @@ } } - /* map state number to SVF state string */ const char* jtag_state_name(enum tap_state state) { @@ -2979,4 +2981,3 @@ return ret; } - Modified: trunk/src/target/mips32.h =================================================================== --- trunk/src/target/mips32.h 2009-01-09 13:04:37 UTC (rev 1312) +++ trunk/src/target/mips32.h 2009-01-13 11:33:19 UTC (rev 1313) @@ -116,7 +116,11 @@ #define MIPS32_SB(reg, off, base) MIPS32_I_INST(MIPS32_OP_SB, base, reg, off) #define MIPS32_SH(reg, off, base) MIPS32_I_INST(MIPS32_OP_SH, base, reg, off) #define MIPS32_SW(reg, off, base) MIPS32_I_INST(MIPS32_OP_SW, base, reg, off) + +/* ejtag specific instructions */ #define MIPS32_DRET 0x4200001F +#define MIPS32_SDBBP 0x7000003F +#define MIPS16_SDBBP 0xE801 extern int mips32_arch_state(struct target_s *target); extern int mips32_init_arch_info(target_t *target, mips32_common_t *mips32, jtag_tap_t *tap); Modified: trunk/src/target/mips_m4k.c =================================================================== --- trunk/src/target/mips_m4k.c 2009-01-09 13:04:37 UTC (rev 1312) +++ trunk/src/target/mips_m4k.c 2009-01-13 11:33:19 UTC (rev 1313) @@ -490,7 +490,8 @@ { mips32_common_t *mips32 = target->arch_info; mips32_comparator_t * comparator_list = mips32->inst_break_list; - + int retval; + if (breakpoint->set) { LOG_WARNING("breakpoint already set"); @@ -519,7 +520,54 @@ } else if (breakpoint->type == BKPT_SOFT) { - + if (breakpoint->length == 4) + { + u32 verify = 0xffffffff; + + if((retval = target->type->read_memory(target, breakpoint->address, breakpoint->length, 1, breakpoint->orig_instr)) != ERROR_OK) + { + return retval; + } + if ((retval = target_write_u32(target, breakpoint->address, MIPS32_SDBBP)) != ERROR_OK) + { + return retval; + } + + if ((retval = target_read_u32(target, breakpoint->address, &verify)) != ERROR_OK) + { + return retval; + } + if (verify != MIPS32_SDBBP) + { + LOG_ERROR("Unable to set 32bit breakpoint at address %08x - check that memory is read/writable", breakpoint->address); + return ERROR_OK; + } + } + else + { + u16 verify = 0xffff; + + if((retval = target->type->read_memory(target, breakpoint->address, breakpoint->length, 1, breakpoint->orig_instr)) != ERROR_OK) + { + return retval; + } + if ((retval = target_write_u16(target, breakpoint->address, MIPS16_SDBBP)) != ERROR_OK) + { + return retval; + } + + if ((retval = target_read_u16(target, breakpoint->address, &verify)) != ERROR_OK) + { + return retval; + } + if (verify != MIPS16_SDBBP) + { + LOG_ERROR("Unable to set 16bit breakpoint at address %08x - check that memory is read/writable", breakpoint->address); + return ERROR_OK; + } + } + + breakpoint->set = 20; /* Any nice value but 0 */ } return ERROR_OK; @@ -530,7 +578,8 @@ /* get pointers to arch-specific information */ mips32_common_t *mips32 = target->arch_info; mips32_comparator_t * comparator_list = mips32->inst_break_list; - + int retval; + if (!breakpoint->set) { LOG_WARNING("breakpoint not set"); @@ -551,7 +600,42 @@ } else { - + /* restore original instruction (kept in target endianness) */ + if (breakpoint->length == 4) + { + u32 current_instr; + + /* check that user program has not modified breakpoint instruction */ + if ((retval = target->type->read_memory(target, breakpoint->address, 4, 1, (u8*)¤t_instr)) != ERROR_OK) + { + return retval; + } + if (current_instr == MIPS32_SDBBP) + { + if((retval = target->type->write_memory(target, breakpoint->address, 4, 1, breakpoint->orig_instr)) != ERROR_OK) + { + return retval; + } + } + } + else + { + u16 current_instr; + + /* check that user program has not modified breakpoint instruction */ + if ((retval = target->type->read_memory(target, breakpoint->address, 2, 1, (u8*)¤t_instr)) != ERROR_OK) + { + return retval; + } + + if (current_instr == MIPS16_SDBBP) + { + if((retval = target->type->write_memory(target, breakpoint->address, 2, 1, breakpoint->orig_instr)) != ERROR_OK) + { + return retval; + } + } + } } breakpoint->set = 0; @@ -562,16 +646,17 @@ { mips32_common_t *mips32 = target->arch_info; - if (mips32->num_inst_bpoints_avail < 1) + if (breakpoint->type == BKPT_HARD) { - LOG_INFO("no hardware breakpoint available"); - return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; - } + if (mips32->num_inst_bpoints_avail < 1) + { + LOG_INFO("no hardware breakpoint available"); + return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; + } + + mips32->num_inst_bpoints_avail--; + } - /* default to hardware for now */ - breakpoint->type = BKPT_HARD; - - mips32->num_inst_bpoints_avail--; mips_m4k_set_breakpoint(target, breakpoint); return ERROR_OK; Modified: trunk/src/target/target/pic32mx.cfg =================================================================== --- trunk/src/target/target/pic32mx.cfg 2009-01-09 13:04:37 UTC (rev 1312) +++ trunk/src/target/target/pic32mx.cfg 2009-01-13 11:33:19 UTC (rev 1313) @@ -15,7 +15,7 @@ set _CPUTAPID $CPUTAPID } else { # force an error till we get a good number - set _CPUTAPID 0xffffffff + set _CPUTAPID 0x30938053 } jtag_nsrst_delay 100 |
From: <oh...@ma...> - 2009-01-09 14:04:44
|
Author: oharboe Date: 2009-01-09 14:04:37 +0100 (Fri, 09 Jan 2009) New Revision: 1312 Modified: trunk/src/target/target/imx31.cfg Log: wip Modified: trunk/src/target/target/imx31.cfg =================================================================== --- trunk/src/target/target/imx31.cfg 2009-01-09 11:44:01 UTC (rev 1311) +++ trunk/src/target/target/imx31.cfg 2009-01-09 13:04:37 UTC (rev 1312) @@ -1,7 +1,8 @@ # imx31 config # -# NB! Does not work yet. Work in progress +reset_config trst_and_srst + if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { @@ -17,19 +18,24 @@ if { [info exists CPUTAPID ] } { set _CPUTAPID $CPUTAPID } else { - # force an error till we get a good number - set _CPUTAPID 0xffffffff + set _CPUTAPID 0x07b3601d } +if { [info exists SDMATAPID ] } { + set _SDMATAPID $SDMATAPID +} else { + set _SDMATAPID 0x2190101d +} + #======================================== # The "system jtag controller" # IMX31 reference manual, page 6-28 - figure 6-14 if { [info exists SJCTAPID ] } { set _SJCTAPID $SJCTAPID } else { - set _SJCTAPID 0xffffffff + set _SJCTAPID 0x2b900f0f } -jtag newtap $_CHIPNAME sjc -irlen 4 -ircapture 00 irmask 0x0 -expected-id $_SJCTAPID +jtag newtap $_CHIPNAME sjc -irlen 4 -ircapture 0x0 -irmask 0x0 -expected-id $_SJCTAPID # The "SDMA" - <S>mart <DMA> controller debug tap # Based on some IO pins - this can be disabled & removed @@ -38,28 +44,19 @@ # SJC_MOD - controls multiplexer - disables ARM1136 # SDMA_BYPASS - disables SDMA - # -if { [info exists SDMATAPID ] } { - set _SDMATAPID $SDMATAPID -} else { - set _SDMATAPID 0xffffffff -} -# Per section 40.17.1, table 40-85 the IR register is 4 bits -# But this conflicts with Diagram 6-13, "3bits ir and drs" -jtag newtap $_CHIPNAME smda -irlen 4 -ircapture 0xe -irmask 0xf -expected-id $_SJCTAPID - -# The ARM11 core tap -if { [info exists CPUTAPID ] } { - set _CPUTAPID $CPUTAPID -} else { - set _CPUTAPID 0xffffffff -} # Per ARM: DDI0211J_arm1136_r1p5_trm.pdf - the ARM 1136 as a 5 bit IR register -jtag newtap $_CHIPNAME cpu -irlen 5 -ircapture 0x1e irmask 0x1f -expected-id $_SJCTAPID +jtag newtap $_CHIPNAME cpu -irlen 5 -ircapture 0x1e -irmask 0x1f -expected-id $_CPUTAPID +# No IDCODE for this TAP +jtag newtap $_CHIPNAME whatchacallit -irlen 4 -ircapture 0 -irmask 0xf -expected-id 0x0 -jtag_nsrst_delay 500 -jtag_ntrst_delay 500 +# Per section 40.17.1, table 40-85 the IR register is 4 bits +# But this conflicts with Diagram 6-13, "3bits ir and drs" +jtag newtap $_CHIPNAME smda -irlen 4 -ircapture 0xe -irmask 0xf -expected-id $_SDMATAPID set _TARGETNAME [format "%s.cpu" $_CHIPNAME] target create $_TARGETNAME arm11 -endian $_ENDIAN -chain-position $_TARGETNAME - + + +proc power_restore {} { puts "Sensed power restore. No action." } +proc srst_deasserted {} { puts "Sensed nSRST deasserted. No action." } |
From: <oh...@ma...> - 2009-01-09 12:44:13
|
Author: oharboe Date: 2009-01-09 12:44:01 +0100 (Fri, 09 Jan 2009) New Revision: 1311 Modified: trunk/src/ecosboard.c trunk/src/helper/ioutil.c trunk/src/openocd.c Log: moved ioutil init to the right spot: before config scripts Modified: trunk/src/ecosboard.c =================================================================== --- trunk/src/ecosboard.c 2009-01-09 11:43:15 UTC (rev 1310) +++ trunk/src/ecosboard.c 2009-01-09 11:44:01 UTC (rev 1311) @@ -869,6 +869,8 @@ return ERROR_OK; } +int ioutil_init(struct command_context_s *cmd_ctx); + int main(int argc, char *argv[]) { /* ramblockdevice will be the same address every time. The deflate app uses a buffer 16mBytes out, so we @@ -1001,6 +1003,14 @@ command_set_output_handler(cmd_ctx, configuration_output_handler, NULL); command_context_mode(cmd_ctx, COMMAND_CONFIG); +#if BUILD_IOUTIL + if (ioutil_init(cmd_ctx) != ERROR_OK) + { + return EXIT_FAILURE; + } +#endif + + #ifdef CYGPKG_PROFILE_GPROF register_command(cmd_ctx, NULL, "ecosboard_profile", eCosBoard_handle_eCosBoard_profile_command, COMMAND_ANY, NULL); Modified: trunk/src/helper/ioutil.c =================================================================== --- trunk/src/helper/ioutil.c 2009-01-09 11:43:15 UTC (rev 1310) +++ trunk/src/helper/ioutil.c 2009-01-09 11:44:01 UTC (rev 1311) @@ -601,6 +601,7 @@ freeifaddrs(ifp); #else Jim_Obj *tclOutput = Jim_NewStringObj(interp, "fixme!!!", 0); + LOG_ERROR("NOT IMPLEMENTED!!!"); #endif Jim_SetResult(interp, tclOutput); Modified: trunk/src/openocd.c =================================================================== --- trunk/src/openocd.c 2009-01-09 11:43:15 UTC (rev 1310) +++ trunk/src/openocd.c 2009-01-09 11:44:01 UTC (rev 1311) @@ -139,13 +139,6 @@ atexit(exit_handler); -#if BUILD_IOUTIL - if (ioutil_init(cmd_ctx) != ERROR_OK) - { - return ERROR_FAIL; - } -#endif - if (target_init(cmd_ctx) != ERROR_OK) return ERROR_FAIL; LOG_DEBUG("target init complete"); @@ -251,6 +244,13 @@ cmd_ctx = setup_command_handler(); +#if BUILD_IOUTIL + if (ioutil_init(cmd_ctx) != ERROR_OK) + { + return EXIT_FAILURE; + } +#endif + LOG_OUTPUT("\n\nBUGS? Read http://svn.berlios.de/svnroot/repos/openocd/trunk/BUGS\n\n\n"); print_version(); |
From: <oh...@ma...> - 2009-01-09 12:43:26
|
Author: oharboe Date: 2009-01-09 12:43:15 +0100 (Fri, 09 Jan 2009) New Revision: 1310 Modified: trunk/src/jtag/jtag.c Log: allow issuing reset_config on the fly. Faster turnaround times in testing. Modified: trunk/src/jtag/jtag.c =================================================================== --- trunk/src/jtag/jtag.c 2009-01-09 10:12:43 UTC (rev 1309) +++ trunk/src/jtag/jtag.c 2009-01-09 11:43:15 UTC (rev 1310) @@ -2172,7 +2172,8 @@ register_command(cmd_ctx, NULL, "jtag_device", handle_jtag_device_command, COMMAND_CONFIG, "jtag_device <ir_length> <ir_expected> <ir_mask>"); register_command(cmd_ctx, NULL, "reset_config", handle_reset_config_command, - COMMAND_CONFIG, NULL); + COMMAND_ANY, + "[none/trst_only/srst_only/trst_and_srst] [srst_pulls_trst/trst_pulls_srst] [combined/separate] [trst_push_pull/trst_open_drain] [srst_push_pull/srst_open_drain]"); register_command(cmd_ctx, NULL, "jtag_nsrst_delay", handle_jtag_nsrst_delay_command, COMMAND_ANY, "jtag_nsrst_delay <ms> - delay after deasserting srst in ms"); register_command(cmd_ctx, NULL, "jtag_ntrst_delay", handle_jtag_ntrst_delay_command, |
From: <oh...@ma...> - 2009-01-09 11:12:45
|
Author: oharboe Date: 2009-01-09 11:12:43 +0100 (Fri, 09 Jan 2009) New Revision: 1309 Modified: trunk/src/ecosboard.c trunk/src/jtag/jtag.c trunk/src/jtag/zy1000.c Log: fixed warnings + added zy1000 jtag_add_clocks support. Modified: trunk/src/ecosboard.c =================================================================== --- trunk/src/ecosboard.c 2009-01-09 07:42:45 UTC (rev 1308) +++ trunk/src/ecosboard.c 2009-01-09 10:12:43 UTC (rev 1309) @@ -190,7 +190,7 @@ } #ifdef CYGPKG_PROFILE_GPROF -extern void start_profile(); +extern void start_profile(void); int eCosBoard_handle_eCosBoard_profile_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) { @@ -201,13 +201,13 @@ #endif -externC void phi_init_all_network_interfaces(); +externC void phi_init_all_network_interfaces(void); command_context_t *cmd_ctx; static bool webRunning = false; -void keep_webserver() +void keep_webserver(void) { // Target initialisation is only attempted at startup, so we sleep forever and // let the http server bail us out(i.e. get config files set up). @@ -261,12 +261,12 @@ (CYG_ADDRWORD) &filedata[0] ); #endif -void openocd_sleep_prelude() +void openocd_sleep_prelude(void) { cyg_mutex_unlock(&httpstate.jim_lock); } -void openocd_sleep_postlude() +void openocd_sleep_postlude(void) { cyg_mutex_lock(&httpstate.jim_lock); } @@ -422,7 +422,7 @@ extern Jim_Interp *interp; -static void zylinjtag_startNetwork() +static void zylinjtag_startNetwork(void) { // Bring TCP/IP up immediately before we're ready to accept commands. // @@ -857,7 +857,7 @@ int boolParam(char *var); -command_context_t *setup_command_handler(); +command_context_t *setup_command_handler(void); extern const char *zylin_config_dir; Modified: trunk/src/jtag/jtag.c =================================================================== --- trunk/src/jtag/jtag.c 2009-01-09 07:42:45 UTC (rev 1308) +++ trunk/src/jtag/jtag.c 2009-01-09 10:12:43 UTC (rev 1309) @@ -969,7 +969,7 @@ jtag_error=retval; } -int MINIDRIVER(interface_jtag_add_tlr)() +int MINIDRIVER(interface_jtag_add_tlr)(void) { enum tap_state state = TAP_RESET; jtag_command_t **last_cmd = jtag_get_last_command_p(); Modified: trunk/src/jtag/zy1000.c =================================================================== --- trunk/src/jtag/zy1000.c 2009-01-09 07:42:45 UTC (rev 1308) +++ trunk/src/jtag/zy1000.c 2009-01-09 10:12:43 UTC (rev 1309) @@ -83,7 +83,7 @@ return ERROR_OK; } -static bool readPowerDropout() +static bool readPowerDropout(void) { cyg_uint32 state; // sample and clear power dropout @@ -95,7 +95,7 @@ } -static bool readSRST() +static bool readSRST(void) { cyg_uint32 state; // sample and clear SRST sensing @@ -152,7 +152,7 @@ return -1; } -extern bool readSRST(); +extern bool readSRST(void); void zy1000_reset(int trst, int srst) { @@ -404,7 +404,7 @@ -static cyg_uint32 getShiftValue() +static cyg_uint32 getShiftValue(void) { cyg_uint32 value; waitIdle(); @@ -413,7 +413,7 @@ return value; } #if 0 -static cyg_uint32 getShiftValueFlip() +static cyg_uint32 getShiftValueFlip(void) { cyg_uint32 value; waitIdle(); @@ -438,7 +438,7 @@ extern int jtag_check_value(u8 *captured, void *priv); -static void gotoEndState() +static void gotoEndState(void) { setCurrentState(cmd_queue_end_state); } @@ -693,10 +693,10 @@ return ERROR_OK; } -int interface_jtag_add_runtest(int num_cycles, enum tap_state state) +static int zy1000_jtag_add_clocks(int num_cycles, enum tap_state state, enum tap_state clockstate) { /* num_cycles can be 0 */ - setCurrentState(TAP_IDLE); + setCurrentState(clockstate); /* execute num_cycles, 32 at the time. */ int i; @@ -708,7 +708,7 @@ { num=num_cycles-i; } - shiftValueInner(TAP_IDLE, TAP_IDLE, num, 0); + shiftValueInner(clockstate, clockstate, num, 0); } #if !TEST_MANUAL() @@ -734,6 +734,16 @@ return ERROR_OK; } +int interface_jtag_add_runtest(int num_cycles, enum tap_state state) +{ + return zy1000_jtag_add_clocks(num_cycles, state, TAP_IDLE); +} + +int interface_jtag_add_clocks(int num_cycles) +{ + return zy1000_jtag_add_clocks(num_cycles, cmd_queue_cur_state, cmd_queue_end_state); +} + int interface_jtag_add_sleep(u32 us) { jtag_sleep(us); @@ -843,3 +853,5 @@ free(name); return result; } + + |
From: <oh...@ma...> - 2009-01-09 08:42:53
|
Author: oharboe Date: 2009-01-09 08:42:45 +0100 (Fri, 09 Jan 2009) New Revision: 1308 Modified: trunk/src/jtag/bitbang.c trunk/src/jtag/dummy.c trunk/src/jtag/ft2232.c trunk/src/jtag/jtag.c trunk/src/jtag/jtag.h trunk/src/xsvf/xsvf.c Log: Dick Hollenbeck <di...@so...> adds jtag_add_clocks() and implements those in the bitbang and ft2232.c. nearly a full rewrite of the xsvf.c. improved some messaging only affected by _DEBUG_JTAG_IO_ Modified: trunk/src/jtag/bitbang.c =================================================================== --- trunk/src/jtag/bitbang.c 2009-01-08 17:23:55 UTC (rev 1307) +++ trunk/src/jtag/bitbang.c 2009-01-09 07:42:45 UTC (rev 1308) @@ -37,6 +37,10 @@ #include <stdlib.h> #include <unistd.h> + +static void bitbang_stableclocks(int num_cycles); + + bitbang_interface_t *bitbang_interface; /* DANGER!!!! clock absolutely *MUST* be 0 in idle or reset won't work! @@ -61,6 +65,8 @@ int bitbang_execute_queue(void); + + /* The bitbang driver leaves the TCK 0 when in idle */ void bitbang_end_state(enum tap_state state) @@ -153,6 +159,21 @@ bitbang_state_move(); } + +static void bitbang_stableclocks(int num_cycles) +{ + int i; + + /* send num_cycles clocks onto the cable */ + for (i = 0; i < num_cycles; i++) + { + bitbang_interface->write(1, 0, 0); + bitbang_interface->write(0, 0, 0); + } +} + + + void bitbang_scan(int ir_scan, enum scan_type type, u8 *buffer, int scan_size) { enum tap_state saved_end_state = end_state; @@ -247,7 +268,7 @@ { case JTAG_END_STATE: #ifdef _DEBUG_JTAG_IO_ - LOG_DEBUG("end_state: %i", cmd->cmd.end_state->end_state); + LOG_DEBUG("end_state: %s", jtag_state_name(cmd->cmd.end_state->end_state) ); #endif if (cmd->cmd.end_state->end_state != -1) bitbang_end_state(cmd->cmd.end_state->end_state); @@ -264,15 +285,20 @@ break; case JTAG_RUNTEST: #ifdef _DEBUG_JTAG_IO_ - LOG_DEBUG("runtest %i cycles, end in %i", cmd->cmd.runtest->num_cycles, cmd->cmd.runtest->end_state); + LOG_DEBUG("runtest %i cycles, end in %s", cmd->cmd.runtest->num_cycles, jtag_state_name(cmd->cmd.runtest->end_state) ); #endif if (cmd->cmd.runtest->end_state != -1) bitbang_end_state(cmd->cmd.runtest->end_state); bitbang_runtest(cmd->cmd.runtest->num_cycles); break; + + case JTAG_STABLECLOCKS: + bitbang_stableclocks(cmd->cmd.stableclocks->num_cycles); + break; + case JTAG_STATEMOVE: #ifdef _DEBUG_JTAG_IO_ - LOG_DEBUG("statemove end in %i", cmd->cmd.statemove->end_state); + LOG_DEBUG("statemove end in %s", jtag_state_name(cmd->cmd.statemove->end_state)); #endif if (cmd->cmd.statemove->end_state != -1) bitbang_end_state(cmd->cmd.statemove->end_state); @@ -280,13 +306,14 @@ break; case JTAG_PATHMOVE: #ifdef _DEBUG_JTAG_IO_ - LOG_DEBUG("pathmove: %i states, end in %i", cmd->cmd.pathmove->num_states, cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]); + LOG_DEBUG("pathmove: %i states, end in %s", cmd->cmd.pathmove->num_states, + jtag_state_name(cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1])); #endif bitbang_path_move(cmd->cmd.pathmove); break; case JTAG_SCAN: #ifdef _DEBUG_JTAG_IO_ - LOG_DEBUG("%s scan end in %i", (cmd->cmd.scan->ir_scan) ? "IR" : "DR", cmd->cmd.scan->end_state); + LOG_DEBUG("%s scan end in %s", (cmd->cmd.scan->ir_scan) ? "IR" : "DR", jtag_state_name(cmd->cmd.scan->end_state) ); #endif if (cmd->cmd.scan->end_state != -1) bitbang_end_state(cmd->cmd.scan->end_state); Modified: trunk/src/jtag/dummy.c =================================================================== --- trunk/src/jtag/dummy.c 2009-01-08 17:23:55 UTC (rev 1307) +++ trunk/src/jtag/dummy.c 2009-01-09 07:42:45 UTC (rev 1308) @@ -32,9 +32,14 @@ static int dummy_clock; /* edge detector */ +static int clock_count; /* count clocks in any stable state, only stable states */ + + static tap_state_t tap_state_transition(tap_state_t cur_state, int tms); +static u32 dummy_data; + int dummy_speed(int speed); int dummy_register_commands(struct command_context_s *cmd_ctx); int dummy_init(void); @@ -76,7 +81,9 @@ int dummy_read(void) { - return 1; + int data = 1 & dummy_data; + dummy_data = (dummy_data >> 1) | (1<<31); + return data; } @@ -88,9 +95,30 @@ if( tck ) { int old_state = dummy_state; - dummy_state = tap_state_transition( dummy_state, tms ); + dummy_state = tap_state_transition( old_state, tms ); + if( old_state != dummy_state ) - LOG_DEBUG( "dummy_tap=%s", jtag_state_name(dummy_state) ); + { + if( clock_count ) + { + LOG_DEBUG("dummy_tap: %d stable clocks", clock_count); + clock_count = 0; + } + + LOG_DEBUG("dummy_tap: %s", jtag_state_name(dummy_state) ); + +#if defined(DEBUG) + if(dummy_state == TAP_DRCAPTURE) + dummy_data = 0x01255043; +#endif + } + else + { + /* this is a stable state clock edge, no change of state here, + * simply increment clock_count for subsequent logging + */ + ++clock_count; + } } dummy_clock = tck; } @@ -99,8 +127,11 @@ void dummy_reset(int trst, int srst) { dummy_clock = 0; - dummy_state = TAP_RESET; - LOG_DEBUG( "reset to %s", jtag_state_name(dummy_state) ); + + if (trst || (srst && (jtag_reset_config & RESET_SRST_PULLS_TRST))) + dummy_state = TAP_RESET; + + LOG_DEBUG("reset to: %s", jtag_state_name(dummy_state) ); } static int dummy_khz(int khz, int *jtag_speed) Modified: trunk/src/jtag/ft2232.c =================================================================== --- trunk/src/jtag/ft2232.c 2009-01-08 17:23:55 UTC (rev 1307) +++ trunk/src/jtag/ft2232.c 2009-01-09 07:42:45 UTC (rev 1308) @@ -76,6 +76,18 @@ int ft2232_handle_vid_pid_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); int ft2232_handle_latency_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); + +/** + * Function ft2232_stableclocks + * will send out \a num_cycles on the TCK line while the TAP(s) + * are in a stable state. Calling code must ensure that current state is + * stable, that verification is not done in here. + * @param num_cycles is the count of clocks cycles to send. + * @return int - ERROR_OK or ERROR_JTAG_QUEUE_FAILED + */ +static int ft2232_stableclocks(int num_cycles, jtag_command_t *cmd); + + char *ft2232_device_desc = NULL; char *ft2232_serial = NULL; char *ft2232_layout = NULL; @@ -149,10 +161,15 @@ static struct ftdi_context ftdic; #endif + +static jtag_command_t *first_unsent; /* next command that has to be sent */ +static int require_send; + static u8 *ft2232_buffer = NULL; static int ft2232_buffer_size = 0; static int ft2232_read_pointer = 0; static int ft2232_expect_read = 0; + #define FT2232_BUFFER_SIZE 131072 #define BUFFER_ADD ft2232_buffer[ft2232_buffer_size++] #define BUFFER_READ ft2232_buffer[ft2232_read_pointer++] @@ -344,7 +361,7 @@ void ft2232_read_scan(enum scan_type type, u8* buffer, int scan_size) { - int num_bytes = ((scan_size + 7) / 8); + int num_bytes = (scan_size + 7) / 8; int bits_left = scan_size; int cur_byte = 0; @@ -903,14 +920,14 @@ if (type == SCAN_IN) /* only from device to host */ { /* complete bytes */ - predicted_size += (CEIL(num_bytes, 65536)) * 3; + predicted_size += CEIL(num_bytes, 65536) * 3; /* remaining bits - 1 (up to 7) */ predicted_size += ((scan_size - 1) % 8) ? 2 : 0; } else /* host to device, or bidirectional */ { /* complete bytes */ - predicted_size += num_bytes + (CEIL(num_bytes, 65536)) * 3; + predicted_size += num_bytes + CEIL(num_bytes, 65536) * 3; /* remaining bits -1 (up to 7) */ predicted_size += ((scan_size - 1) % 8) ? 3 : 0; } @@ -1185,15 +1202,16 @@ int ft2232_execute_queue() { jtag_command_t *cmd = jtag_command_queue; /* currently processed command */ - jtag_command_t *first_unsent = cmd; /* next command that has to be sent */ u8 *buffer; int scan_size; /* size of IR or DR scan */ enum scan_type type; int i; int predicted_size = 0; - int require_send = 0; int retval; + first_unsent = cmd; /* next command that has to be sent */ + require_send = 0; + /* return ERROR_OK, unless ft2232_send_and_recv reports a failed check * that wasn't handled by a caller-provided error handler */ @@ -1214,6 +1232,7 @@ if (cmd->cmd.end_state->end_state != -1) ft2232_end_state(cmd->cmd.end_state->end_state); break; + case JTAG_RESET: /* only send the maximum buffer size that FT2232C can handle */ predicted_size = 3; @@ -1236,6 +1255,7 @@ LOG_DEBUG("trst: %i, srst: %i", cmd->cmd.reset->trst, cmd->cmd.reset->srst); #endif break; + case JTAG_RUNTEST: /* only send the maximum buffer size that FT2232C can handle */ predicted_size = 0; @@ -1292,9 +1312,10 @@ } require_send = 1; #ifdef _DEBUG_JTAG_IO_ - LOG_DEBUG("runtest: %i, end in %i", cmd->cmd.runtest->num_cycles, end_state); + LOG_DEBUG("runtest: %i, end in %s", cmd->cmd.runtest->num_cycles, jtag_state_name(end_state)); #endif break; + case JTAG_STATEMOVE: /* only send the maximum buffer size that FT2232C can handle */ predicted_size = 3; @@ -1317,9 +1338,10 @@ cur_state = end_state; require_send = 1; #ifdef _DEBUG_JTAG_IO_ - LOG_DEBUG("statemove: %i", end_state); + LOG_DEBUG("statemove: %s", jtag_state_name(end_state)); #endif break; + case JTAG_PATHMOVE: /* only send the maximum buffer size that FT2232C can handle */ predicted_size = 3 * CEIL(cmd->cmd.pathmove->num_states, 7); @@ -1333,9 +1355,11 @@ ft2232_add_pathmove(cmd->cmd.pathmove); require_send = 1; #ifdef _DEBUG_JTAG_IO_ - LOG_DEBUG("pathmove: %i states, end in %i", cmd->cmd.pathmove->num_states, cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]); + LOG_DEBUG("pathmove: %i states, end in %s", cmd->cmd.pathmove->num_states, + jtag_state_name(cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1])); #endif break; + case JTAG_SCAN: scan_size = jtag_build_buffer(cmd->cmd.scan, &buffer); type = jtag_scan_type(cmd->cmd.scan); @@ -1375,18 +1399,45 @@ if (buffer) free(buffer); #ifdef _DEBUG_JTAG_IO_ - LOG_DEBUG("%s scan, %i bit, end in %i", (cmd->cmd.scan->ir_scan) ? "IR" : "DR", scan_size, end_state); + LOG_DEBUG("%s scan, %i bits, end in %s", (cmd->cmd.scan->ir_scan) ? "IR" : "DR", scan_size, + jtag_state_name(end_state)); #endif break; + case JTAG_SLEEP: if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK) retval = ERROR_JTAG_QUEUE_FAILED; first_unsent = cmd->next; jtag_sleep(cmd->cmd.sleep->us); #ifdef _DEBUG_JTAG_IO_ - LOG_DEBUG("sleep %i usec", cmd->cmd.sleep->us); + LOG_DEBUG("sleep %i usec while in %s", cmd->cmd.sleep->us, jtag_state_name(cur_state)); #endif break; + + case JTAG_STABLECLOCKS: + /* "if (tap_move_map[cur_state] != -1)" is of no help when cur_state==TAP_IDLE */ + switch(cur_state) + { + case TAP_DRSHIFT: + case TAP_IDLE: + case TAP_RESET: + case TAP_DRPAUSE: + case TAP_IRSHIFT: + case TAP_IRPAUSE: + break; /* above stable states are OK */ + default: + LOG_ERROR( "jtag_add_clocks() was called with TAP in non-stable state \"%s\"", + jtag_state_name(cur_state) ); + retval = ERROR_JTAG_QUEUE_FAILED; + } + + if (ft2232_stableclocks(cmd->cmd.stableclocks->num_cycles, cmd) != ERROR_OK) + retval = ERROR_JTAG_QUEUE_FAILED; +#ifdef _DEBUG_JTAG_IO_ + LOG_DEBUG("clocks %i while in %s", cmd->cmd.stableclocks->num_cycles, jtag_state_name(cur_state)); +#endif + break; + default: LOG_ERROR("BUG: unknown JTAG command type encountered"); exit(-1); @@ -2279,3 +2330,42 @@ return ERROR_OK; } + + +static int ft2232_stableclocks(int num_cycles, jtag_command_t *cmd) +{ + int retval = 0; + + while (num_cycles > 0) + { + /* the command 0x4b, "Clock Data to TMS/CS Pin (no Read)" handles + * at most 7 bits per invocation. Here we invoke it potentially + * several times. + */ + int bitcount_per_command = (num_cycles > 7) ? 7 : num_cycles; + + if (ft2232_buffer_size + 3 >= FT2232_BUFFER_SIZE) + { + if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK) + retval = ERROR_JTAG_QUEUE_FAILED; + + first_unsent = cmd; + } + + /* command "Clock Data to TMS/CS Pin (no Read)" */ + BUFFER_ADD = 0x4b; + + /* scan 7 bit */ + BUFFER_ADD = bitcount_per_command - 1; + + /* TMS data bits are all zeros to stay in the current stable state */ + BUFFER_ADD = 0x0; + + require_send = 1; + + num_cycles -= bitcount_per_command; + } + + return retval; +} + Modified: trunk/src/jtag/jtag.c =================================================================== --- trunk/src/jtag/jtag.c 2009-01-08 17:23:55 UTC (rev 1307) +++ trunk/src/jtag/jtag.c 2009-01-09 07:42:45 UTC (rev 1308) @@ -79,22 +79,22 @@ tap_transition_t tap_transitions[16] = { - {TAP_RESET, TAP_IDLE}, /* RESET */ - {TAP_IRSELECT, TAP_DRCAPTURE}, /* DRSELECT */ - {TAP_DREXIT1, TAP_DRSHIFT}, /* DRCAPTURE */ - {TAP_DREXIT1, TAP_DRSHIFT}, /* DRSHIFT */ + {TAP_RESET, TAP_IDLE}, /* RESET */ + {TAP_IRSELECT, TAP_DRCAPTURE}, /* DRSELECT */ + {TAP_DREXIT1, TAP_DRSHIFT}, /* DRCAPTURE */ + {TAP_DREXIT1, TAP_DRSHIFT}, /* DRSHIFT */ {TAP_DRUPDATE, TAP_DRPAUSE}, /* DREXIT1 */ - {TAP_DREXIT2, TAP_DRPAUSE}, /* DRPAUSE */ + {TAP_DREXIT2, TAP_DRPAUSE}, /* DRPAUSE */ {TAP_DRUPDATE, TAP_DRSHIFT}, /* DREXIT2 */ - {TAP_DRSELECT, TAP_IDLE}, /* DRUPDATE */ - {TAP_DRSELECT, TAP_IDLE}, /* IDLE */ - {TAP_RESET, TAP_IRCAPTURE}, /* IRSELECT */ - {TAP_IREXIT1, TAP_IRSHIFT}, /* IRCAPTURE */ - {TAP_IREXIT1, TAP_IRSHIFT}, /* IRSHIFT */ + {TAP_DRSELECT, TAP_IDLE}, /* DRUPDATE */ + {TAP_DRSELECT, TAP_IDLE}, /* IDLE */ + {TAP_RESET, TAP_IRCAPTURE}, /* IRSELECT */ + {TAP_IREXIT1, TAP_IRSHIFT}, /* IRCAPTURE */ + {TAP_IREXIT1, TAP_IRSHIFT}, /* IRSHIFT */ {TAP_IRUPDATE, TAP_IRPAUSE}, /* IREXIT1 */ - {TAP_IREXIT2, TAP_IRPAUSE}, /* IRPAUSE */ + {TAP_IREXIT2, TAP_IRPAUSE}, /* IRPAUSE */ {TAP_IRUPDATE, TAP_IRSHIFT}, /* IREXIT2 */ - {TAP_DRSELECT, TAP_IDLE} /* IRUPDATE */ + {TAP_DRSELECT, TAP_IDLE} /* IRUPDATE */ }; char* jtag_event_strings[] = @@ -983,7 +983,6 @@ (*last_cmd)->cmd.statemove = cmd_queue_alloc(sizeof(statemove_command_t)); (*last_cmd)->cmd.statemove->end_state = state; - return ERROR_OK; } @@ -1074,6 +1073,33 @@ jtag_error=retval; } + +int MINIDRIVER(interface_jtag_add_clocks)( int num_cycles ) +{ + jtag_command_t **last_cmd = jtag_get_last_command_p(); + + /* allocate memory for a new list member */ + *last_cmd = cmd_queue_alloc(sizeof(jtag_command_t)); + (*last_cmd)->next = NULL; + last_comand_pointer = &((*last_cmd)->next); + (*last_cmd)->type = JTAG_STABLECLOCKS; + + (*last_cmd)->cmd.stableclocks = cmd_queue_alloc(sizeof(stableclocks_command_t)); + (*last_cmd)->cmd.stableclocks->num_cycles = num_cycles; + return ERROR_OK; +} + +void jtag_add_clocks( int num_cycles ) +{ + int retval; + + jtag_prelude1(); + + retval=interface_jtag_add_clocks(num_cycles); + if (retval!=ERROR_OK) + jtag_error=retval; +} + void jtag_add_reset(int req_tlr_or_trst, int req_srst) { int trst_with_tlr = 0; @@ -1252,6 +1278,8 @@ bit_count = 0; + LOG_DEBUG("num_fields: %i",cmd->num_fields); + for (i = 0; i < cmd->num_fields; i++) { if (cmd->fields[i].out_value) @@ -1261,12 +1289,13 @@ #endif buf_set_buf(cmd->fields[i].out_value, 0, *buffer, bit_count, cmd->fields[i].num_bits); #ifdef _DEBUG_JTAG_IO_ - LOG_DEBUG("fields[%i].out_value: 0x%s", i, char_buf); + LOG_DEBUG("fields[%i].out_value[%i]: 0x%s", i, cmd->fields[i].num_bits, char_buf); free(char_buf); #endif } bit_count += cmd->fields[i].num_bits; + LOG_DEBUG("bit_count totalling: %i", bit_count ); } return bit_count; @@ -1292,10 +1321,8 @@ u8 *captured = buf_set_buf(buffer, bit_count, malloc(CEIL(num_bits, 8)), 0, num_bits); #ifdef _DEBUG_JTAG_IO_ - char *char_buf; - - char_buf = buf_to_str(captured, (num_bits > 64) ? 64 : num_bits, 16); - LOG_DEBUG("fields[%i].in_value: 0x%s", i, char_buf); + char *char_buf = buf_to_str(captured, (num_bits > 64) ? 64 : num_bits, 16); + LOG_DEBUG("fields[%i].in_value[%i]: 0x%s", i, num_bits, char_buf); free(char_buf); #endif Modified: trunk/src/jtag/jtag.h =================================================================== --- trunk/src/jtag/jtag.h 2009-01-08 17:23:55 UTC (rev 1307) +++ trunk/src/jtag/jtag.h 2009-01-09 07:42:45 UTC (rev 1308) @@ -29,6 +29,7 @@ #include "command.h" + #if 0 #define _DEBUG_JTAG_IO_ #endif @@ -112,6 +113,13 @@ enum tap_state end_state; /* TAP state in which JTAG commands should finish */ } runtest_command_t; + +typedef struct stableclocks_command_s +{ + int num_cycles; /* number of clock cycles that should be sent */ +} stableclocks_command_t; + + typedef struct reset_command_s { int trst; /* trst/srst 0: deassert, 1: assert, -1: don't change */ @@ -134,6 +142,7 @@ statemove_command_t *statemove; pathmove_command_t *pathmove; runtest_command_t *runtest; + stableclocks_command_t *stableclocks; reset_command_t *reset; end_state_command_t *end_state; sleep_command_t *sleep; @@ -144,7 +153,8 @@ JTAG_SCAN = 1, JTAG_STATEMOVE = 2, JTAG_RUNTEST = 3, JTAG_RESET = 4, JTAG_END_STATE = 5, - JTAG_PATHMOVE = 6, JTAG_SLEEP = 7 + JTAG_PATHMOVE = 6, JTAG_SLEEP = 7, + JTAG_STABLECLOCKS = 8 }; typedef struct jtag_command_s @@ -434,6 +444,16 @@ extern void jtag_add_sleep(u32 us); extern int interface_jtag_add_sleep(u32 us); + +/** + * Function jtag_add_stable_clocks + * first checks that the state in which the clocks are to be issued is + * stable, then queues up clock_count clocks for transmission. + */ +void jtag_add_clocks( int num_cycles ); +int interface_jtag_add_clocks( int num_cycles ); + + /* * For software FIFO implementations, the queued commands can be executed * during this call or earlier. A sw queue might decide to push out Modified: trunk/src/xsvf/xsvf.c =================================================================== --- trunk/src/xsvf/xsvf.c 2009-01-08 17:23:55 UTC (rev 1307) +++ trunk/src/xsvf/xsvf.c 2009-01-09 07:42:45 UTC (rev 1308) @@ -1,28 +1,42 @@ /*************************************************************************** - * Copyright (C) 2005 by Dominic Rath * - * Dom...@gm... * - * * - * Copyright (C) 2007,2008 vind Harboe * - * oyv...@zy... * - * * - * Copyright (C) 2008 Peter Hettkamp * - * pet...@ht... * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You 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. * + * Copyright (C) 2005 by Dominic Rath * + * Dom...@gm... * + * * + * Copyright (C) 2007,2008 vind Harboe * + * oyv...@zy... * + * * + * Copyright (C) 2008 Peter Hettkamp * + * pet...@ht... * + * * + * Copyright (C) 2009 SoftPLC Corporation. http://softplc.com * + * di...@so... * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You 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. * ***************************************************************************/ + + +/* The specification for SVF is available here: + * http://www.asset-intertech.com/support/svf.pdf + * Below, this document is refered to as the "SVF spec". + * + * The specification for XSVF is available here: + * http://www.xilinx.com/support/documentation/application_notes/xapp503.pdf + * Below, this document is refered to as the "XSVF spec". + */ + #ifdef HAVE_CONFIG_H #include "config.h" #endif @@ -43,50 +57,131 @@ #include <sys/time.h> #include <time.h> -#define XSTATE_MAX_PATH (12) -int handle_xsvf_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); +/* XSVF commands, from appendix B of xapp503.pdf */ +#define XCOMPLETE 0x00 +#define XTDOMASK 0x01 +#define XSIR 0x02 +#define XSDR 0x03 +#define XRUNTEST 0x04 +#define XREPEAT 0x07 +#define XSDRSIZE 0x08 +#define XSDRTDO 0x09 +#define XSETSDRMASKS 0x0A +#define XSDRINC 0x0B +#define XSDRB 0x0C +#define XSDRC 0x0D +#define XSDRE 0x0E +#define XSDRTDOB 0x0F +#define XSDRTDOC 0x10 +#define XSDRTDOE 0x11 +#define XSTATE 0x12 +#define XENDIR 0x13 +#define XENDDR 0x14 +#define XSIR2 0x15 +#define XCOMMENT 0x16 +#define XWAIT 0x17 -int xsvf_fd = 0; +/* XWAITSTATE is not in the xilinx XSVF spec, but the svf2xsvf.py translator + * generates this. Arguably it is needed because the XSVF XRUNTEST command + * was ill conceived and does not directly flow out of the SVF RUNTEST command. + * This XWAITSTATE does map directly from the SVF RUNTEST command. + */ +#define XWAITSTATE 0x18 -u8 *dr_out_buf; /* from host to device (TDI) */ -u8 *dr_in_buf; /* from device to host (TDO) */ -u8 *dr_in_mask; +/* Lattice has extended the SVF file format, and Dick Hollenbeck's python based + * SVF2XSVF converter supports these 3 additional XSVF opcodes, LCOUNT, LDELAY, LSDR. + * Here is an example of usage of the 3 lattice opcode extensions: -int xsdrsize = 0; -int xruntest = 0; /* number of TCK cycles / microseconds */ -int xrepeat = 0x20; /* number of XC9500 retries */ +! Set the maximum loop count to 25. +LCOUNT 25; +! Step to DRPAUSE give 5 clocks and wait for 1.00e+000 SEC. +LDELAY DRPAUSE 5 TCK 1.00E-003 SEC; +! Test for the completed status. Match means pass. +! Loop back to LDELAY line if not match and loop count less than 25. -int xendir = 0; -int xenddr = 0; +LSDR 1 TDI (0) + TDO (1); +*/ -enum tap_state xsvf_to_tap[] = -{ - TAP_RESET, TAP_IDLE, - TAP_DRSELECT, TAP_DRCAPTURE, TAP_DRSHIFT, TAP_DREXIT1, TAP_DRPAUSE, TAP_DREXIT2, TAP_DRUPDATE, - TAP_IRSELECT, TAP_IRCAPTURE, TAP_IRSHIFT, TAP_IREXIT1, TAP_IRPAUSE, TAP_IREXIT2, TAP_IRUPDATE, -}; +#define LCOUNT 0x19 +#define LDELAY 0x1A +#define LSDR 0x1B -int tap_to_xsvf[] = + +/* XSVF valid state values for the XSTATE command, from appendix B of xapp503.pdf */ +#define XSV_RESET 0x00 +#define XSV_IDLE 0x01 +#define XSV_DRSELECT 0x02 +#define XSV_DRCAPTURE 0x03 +#define XSV_DRSHIFT 0x04 +#define XSV_DREXIT1 0x05 +#define XSV_DRPAUSE 0x06 +#define XSV_DREXIT2 0x07 +#define XSV_DRUPDATE 0x08 +#define XSV_IRSELECT 0x09 +#define XSV_IRCAPTURE 0x0A +#define XSV_IRSHIFT 0x0B +#define XSV_IREXIT1 0x0C +#define XSV_IRPAUSE 0x0D +#define XSV_IREXIT2 0x0E +#define XSV_IRUPDATE 0x0F + + +#define XSTATE_MAX_PATH 12 + +static int handle_xsvf_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); + +static int xsvf_fd = 0; + + +/* map xsvf tap state to an openocd "enum tap_state" */ +static tap_state_t xsvf_to_tap( int xsvf_state ) { - 0x0, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x1, 0x9, 0xa, 0xb, 0xc, 0xe, 0xf -}; + tap_state_t ret; + switch( xsvf_state ) + { + case XSV_RESET: ret = TAP_RESET; break; + case XSV_IDLE: ret = TAP_IDLE; break; + case XSV_DRSELECT: ret = TAP_DRSELECT; break; + case XSV_DRCAPTURE: ret = TAP_DRCAPTURE; break; + case XSV_DRSHIFT: ret = TAP_DRSHIFT; break; + case XSV_DREXIT1: ret = TAP_DREXIT1; break; + case XSV_DRPAUSE: ret = TAP_DRPAUSE; break; + case XSV_DREXIT2: ret = TAP_DREXIT2; break; + case XSV_DRUPDATE: ret = TAP_DRUPDATE; break; + case XSV_IRSELECT: ret = TAP_IRSELECT; break; + case XSV_IRCAPTURE: ret = TAP_IRCAPTURE; break; + case XSV_IRSHIFT: ret = TAP_IRSHIFT; break; + case XSV_IREXIT1: ret = TAP_IREXIT1; break; + case XSV_IRPAUSE: ret = TAP_IRPAUSE; break; + case XSV_IREXIT2: ret = TAP_IREXIT2; break; + case XSV_IRUPDATE: ret = TAP_IRUPDATE; break; + default: + LOG_ERROR( "UNKNOWN XSVF STATE 0x%02X", xsvf_state ); + exit(1); + } + return ret; +} + + /* xsvf has it's own definition of a statemove. This needs - * to be handled according to the specs, which has nothing + * to be handled according to the xsvf spec, which has nothing * to do with the JTAG spec or OpenOCD as such. * * Implemented via jtag_add_pathmove(). */ -void xsvf_add_statemove(enum tap_state state) +static void xsvf_add_statemove(tap_state_t state) { - enum tap_state moves[7]; /* max # of transitions */ + tap_state_t moves[7]; /* max # of transitions */ + tap_state_t curstate = cmd_queue_cur_state; int i; - enum tap_state curstate = cmd_queue_cur_state; + u8 move = TAP_MOVE(cmd_queue_cur_state, state); - if ((state != TAP_RESET) && (state == cmd_queue_cur_state)) + if (state != TAP_RESET && state==cmd_queue_cur_state) return; if(state==TAP_RESET) @@ -94,13 +189,15 @@ jtag_add_tlr(); return; } + for (i=0; i<7; i++) { int j = (move >> i) & 1; if (j) { curstate = tap_transitions[curstate].high; - } else + } + else { curstate = tap_transitions[curstate].low; } @@ -113,17 +210,18 @@ int xsvf_register_commands(struct command_context_s *cmd_ctx) { register_command(cmd_ctx, NULL, "xsvf", handle_xsvf_command, - COMMAND_EXEC, "run xsvf <file>"); + COMMAND_EXEC, "run xsvf <file> [virt2]"); return ERROR_OK; } -int xsvf_read_buffer(int num_bits, int fd, u8* buf) +static int xsvf_read_buffer(int num_bits, int fd, u8* buf) { int num_bytes; for (num_bytes = (num_bits + 7) / 8; num_bytes > 0; num_bytes--) { + /* reverse the order of bytes as they are read sequentially from file */ if (read(fd, buf + num_bytes - 1, 1) < 0) return ERROR_XSVF_EOF; } @@ -131,13 +229,16 @@ return ERROR_OK; } -int xsvf_read_xstates(int fd, enum tap_state *path, int max_path, int *path_len) + +static int xsvf_read_xstates(int fd, tap_state_t *path, int max_path, int *path_len) { char c; - unsigned char uc; + u8 uc; - while ((read(fd, &c, 1) > 0) && (c == 0x12)) + while ((read(fd, &c, 1) > 0) && (c == XSTATE)) { + tap_state_t mystate; + if (*path_len > max_path) { LOG_WARNING("XSTATE path longer than max_path"); @@ -147,7 +248,12 @@ { return ERROR_XSVF_EOF; } - path[(*path_len)++] = xsvf_to_tap[uc]; + + mystate = xsvf_to_tap(uc); + + LOG_DEBUG("XSTATE %02X %s", uc, jtag_state_name(mystate) ); + + path[(*path_len)++] = mystate; } lseek(fd, -1, SEEK_CUR); @@ -155,273 +261,325 @@ return ERROR_OK; } -int handle_xsvf_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) + +static int handle_xsvf_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) { - char c; - u8 buf4[4], buf2[2]; - unsigned char uc, uc2; - unsigned int ui; - unsigned short us; + u8 *dr_out_buf = NULL; /* from host to device (TDI) */ + u8 *dr_in_buf = NULL; /* from device to host (TDO) */ + u8 *dr_in_mask = NULL; - int do_abort = 0; - int unsupported = 0; - int tdo_mismatch = 0; + int xsdrsize = 0; + int xruntest = 0; /* number of TCK cycles OR microseconds */ + int xrepeat = 0; /* number of retries */ - int runtest_requires_tck = 0; + tap_state_t xendir = TAP_IDLE; /* see page 8 of the SVF spec, initial xendir to be TAP_IDLE */ + tap_state_t xenddr = TAP_IDLE; - jtag_tap_t *tap = NULL; + u8 opcode; + u8 uc; + long file_offset = 0; + + int loop_count = 0; + tap_state_t loop_state = TAP_IDLE; + int loop_clocks = 0; + int loop_usecs = 0; + + int do_abort = 0; + int unsupported = 0; + int tdo_mismatch = 0; + int result; + + int runtest_requires_tck = 0; /* a flag telling whether to clock TCK during waits, or simply sleep, controled by virt2 */ + + /* use NULL to indicate a "plain" xsvf file which accounts for additional devices in the scan chain, otherwise the device - that should be affected */ + that should be affected + */ + jtag_tap_t *tap = NULL; if (argc < 2) { command_print(cmd_ctx, "usage: xsvf <device#|plain> <file> <variant>"); - return ERROR_OK; + return ERROR_FAIL; } if (strcmp(args[0], "plain") != 0) { - tap = jtag_TapByString( args[0] ); - if( !tap ){ - command_print( cmd_ctx, "Tap: %s unknown", args[0] ); - return ERROR_OK; - } + tap = jtag_TapByString( args[0] ); + if (!tap ) + { + command_print( cmd_ctx, "Tap: %s unknown", args[0] ); + return ERROR_FAIL; + } } if ((xsvf_fd = open(args[1], O_RDONLY)) < 0) { - command_print(cmd_ctx, "file %s not found", args[0]); - return ERROR_OK; + command_print(cmd_ctx, "file \"%s\" not found", args[1]); + return ERROR_FAIL; } + /* if this argument is present, then interpret xruntest counts as TCK cycles rather than as usecs */ if ((argc > 2) && (strcmp(args[2], "virt2") == 0)) { runtest_requires_tck = 1; } - while (read(xsvf_fd, &c, 1) > 0) + LOG_USER("xsvf processing file: \"%s\"", args[1]); + + while( read(xsvf_fd, &opcode, 1) > 0 ) { - switch (c) + /* record the position of the just read opcode within the file */ + file_offset = lseek(xsvf_fd, 0, SEEK_CUR) - 1; + + switch (opcode) { - case 0x00: /* XCOMPLETE */ + case XCOMPLETE: LOG_DEBUG("XCOMPLETE"); - if (jtag_execute_queue() != ERROR_OK) + + result = jtag_execute_queue(); + if (result != ERROR_OK) { tdo_mismatch = 1; break; } break; - case 0x01: /* XTDOMASK */ + + case XTDOMASK: LOG_DEBUG("XTDOMASK"); if (dr_in_mask && (xsvf_read_buffer(xsdrsize, xsvf_fd, dr_in_mask) != ERROR_OK)) do_abort = 1; break; - case 0x02: /* XSIR */ - LOG_DEBUG("XSIR"); - if (read(xsvf_fd, &c, 1) < 0) - do_abort = 1; - else + + case XRUNTEST: { - u8 *ir_buf = malloc((c + 7) / 8); - if (xsvf_read_buffer(c, xsvf_fd, ir_buf) != ERROR_OK) + u8 xruntest_buf[4]; + + if (read(xsvf_fd, xruntest_buf, 4) < 0) + { do_abort = 1; - else - { - scan_field_t field; - field.tap = tap; - field.num_bits = c; - field.out_value = ir_buf; - field.out_mask = NULL; - field.in_value = NULL; - field.in_check_value = NULL; - field.in_check_mask = NULL; - field.in_handler = NULL; - field.in_handler_priv = NULL; - if (tap == NULL) - jtag_add_plain_ir_scan(1, &field, TAP_IRPAUSE); - else - jtag_add_ir_scan(1, &field, TAP_IRPAUSE); - if (jtag_execute_queue() != ERROR_OK) - { - tdo_mismatch = 1; - free(ir_buf); - break; - } - if (xruntest) - { - if (runtest_requires_tck) - jtag_add_runtest(xruntest, xsvf_to_tap[xendir]); - else - { - xsvf_add_statemove(TAP_IDLE); - jtag_add_sleep(xruntest); - xsvf_add_statemove(xsvf_to_tap[xendir]); - } - } - else if (xendir != 0xd) /* Pause-IR */ - xsvf_add_statemove(xsvf_to_tap[xendir]); + break; } - free(ir_buf); + + xruntest = be_to_h_u32(xruntest_buf); + LOG_DEBUG("XRUNTEST %d 0x%08X", xruntest, xruntest); } break; - case 0x03: /* XSDR */ - LOG_DEBUG("XSDR"); - if (xsvf_read_buffer(xsdrsize, xsvf_fd, dr_out_buf) != ERROR_OK) - do_abort = 1; - else + + case XREPEAT: { - scan_field_t field; - field.tap = tap; - field.num_bits = xsdrsize; - field.out_value = dr_out_buf; - field.out_mask = NULL; - field.in_value = NULL; - jtag_set_check_value(&field, dr_in_buf, dr_in_mask, NULL); - if (tap == NULL) - jtag_add_plain_dr_scan(1, &field, TAP_DRPAUSE); + u8 myrepeat; + + if (read(xsvf_fd, &myrepeat, 1) < 0) + do_abort = 1; else - jtag_add_dr_scan(1, &field, TAP_DRPAUSE); - if (jtag_execute_queue() != ERROR_OK) { - tdo_mismatch = 1; - break; + xrepeat = myrepeat; + LOG_DEBUG("XREPEAT %d", xrepeat ); } - if (xruntest) - { - if (runtest_requires_tck) - jtag_add_runtest(xruntest, xsvf_to_tap[xenddr]); - else - { - xsvf_add_statemove(TAP_IDLE); - jtag_add_sleep(xruntest); - xsvf_add_statemove(xsvf_to_tap[xenddr]); - } - } - else if (xendir != 0x6) /* Pause-DR */ - xsvf_add_statemove(xsvf_to_tap[xenddr]); } break; - case 0x04: /* XRUNTEST */ - LOG_DEBUG("XRUNTEST"); - if (read(xsvf_fd, buf4, 4) < 0) - do_abort = 1; - else + + case XSDRSIZE: { - xruntest = be_to_h_u32(buf4); - } - break; - case 0x07: /* XREPEAT */ - LOG_DEBUG("XREPEAT"); - if (read(xsvf_fd, &c, 1) < 0) - do_abort = 1; - else - { - xrepeat = c; - } - break; - case 0x08: /* XSDRSIZE */ - LOG_DEBUG("XSDRSIZE"); - if (read(xsvf_fd, buf4, 4) < 0) - do_abort = 1; - else - { - xsdrsize = be_to_h_u32(buf4); - free(dr_out_buf); - free(dr_in_buf); - free(dr_in_mask); + u8 xsdrsize_buf[4]; + + if (read(xsvf_fd, xsdrsize_buf, 4) < 0) + { + do_abort = 1; + break; + } + + xsdrsize = be_to_h_u32(xsdrsize_buf); + LOG_DEBUG("XSDRSIZE %d", xsdrsize); + + if( dr_out_buf ) free(dr_out_buf); + if( dr_in_buf) free(dr_in_buf); + if( dr_in_mask) free(dr_in_mask); + dr_out_buf = malloc((xsdrsize + 7) / 8); dr_in_buf = malloc((xsdrsize + 7) / 8); dr_in_mask = malloc((xsdrsize + 7) / 8); } break; - case 0x09: /* XSDRTDO */ - LOG_DEBUG("XSDRTDO"); - if (xsvf_read_buffer(xsdrsize, xsvf_fd, dr_out_buf) != ERROR_OK) - do_abort = 1; - else + + case XSDR: /* these two are identical except for the dr_in_buf */ + case XSDRTDO: { - if (xsvf_read_buffer(xsdrsize, xsvf_fd, dr_in_buf) != ERROR_OK) + int limit = xrepeat; + int matched = 0; + int attempt; + + const char* op_name = (opcode == XSDR ? "XSDR" : "XSDRTDO"); + + if (xsvf_read_buffer(xsdrsize, xsvf_fd, dr_out_buf) != ERROR_OK) + { do_abort = 1; - else + break; + } + + if (opcode == XSDRTDO) { + if(xsvf_read_buffer(xsdrsize, xsvf_fd, dr_in_buf) != ERROR_OK ) + { + do_abort = 1; + break; + } + } + + if (limit < 1) + limit = 1; + + LOG_DEBUG("%s %d", op_name, xsdrsize); + + for( attempt=0; attempt<limit; ++attempt ) + { scan_field_t field; + + if( attempt>0 ) + { + /* perform the XC9500 exception handling sequence shown in xapp067.pdf and + illustrated in psuedo code at end of this file. We start from state + DRPAUSE: + go to Exit2-DR + go to Shift-DR + go to Exit1-DR + go to Update-DR + go to Run-Test/Idle + + This sequence should be harmless for other devices, and it + will be skipped entirely if xrepeat is set to zero. + */ + + static tap_state_t exception_path[] = { + TAP_DREXIT2, + TAP_DRSHIFT, + TAP_DREXIT1, + TAP_DRUPDATE, + TAP_IDLE, + }; + + jtag_add_pathmove( sizeof(exception_path)/sizeof(exception_path[0]), exception_path); + + LOG_USER("%s %d retry %d", op_name, xsdrsize, attempt); + } + field.tap = tap; field.num_bits = xsdrsize; field.out_value = dr_out_buf; field.out_mask = NULL; field.in_value = NULL; + jtag_set_check_value(&field, dr_in_buf, dr_in_mask, NULL); + if (tap == NULL) jtag_add_plain_dr_scan(1, &field, TAP_DRPAUSE); else jtag_add_dr_scan(1, &field, TAP_DRPAUSE); - if (jtag_execute_queue() != ERROR_OK) + + /* LOG_DEBUG("FLUSHING QUEUE"); */ + result = jtag_execute_queue(); + if (result == ERROR_OK) { - tdo_mismatch = 1; + matched = 1; break; } - if (xruntest) - { - if (runtest_requires_tck) - jtag_add_runtest(xruntest, xsvf_to_tap[xenddr]); - else - { - xsvf_add_statemove(TAP_IDLE); - jtag_add_sleep(xruntest); - xsvf_add_statemove(xsvf_to_tap[xenddr]); - } - } - else if (xendir != 0x6) /* Pause-DR */ - xsvf_add_statemove(xsvf_to_tap[xenddr]); } + + if (!matched) + { + LOG_USER( "%s mismatch", op_name); + tdo_mismatch = 1; + break; + } + + /* See page 19 of XSVF spec regarding opcode "XSDR" */ + if (xruntest) + { + xsvf_add_statemove(TAP_IDLE); + + if (runtest_requires_tck) + jtag_add_clocks(xruntest); + else + jtag_add_sleep(xruntest); + } + else if (xendir != TAP_DRPAUSE) /* we are already in TAP_DRPAUSE */ + xsvf_add_statemove(xenddr); } break; - case 0x0a: /* XSETDRMASKS */ + + case XSETSDRMASKS: LOG_ERROR("unsupported XSETSDRMASKS\n"); unsupported = 1; break; - case 0x0b: /* XSDRINC */ + + case XSDRINC: LOG_ERROR("unsupported XSDRINC\n"); unsupported = 1; break; - case 0x0c: /* XSDRB */ + + case XSDRB: + LOG_ERROR("unsupported XSDRB\n"); unsupported = 1; break; - case 0x0d: /* XSDRC */ + + case XSDRC: + LOG_ERROR("unsupported XSDRC\n"); unsupported = 1; break; - case 0x0e: /* XSDRE */ + + case XSDRE: + LOG_ERROR("unsupported XSDRE\n"); unsupported = 1; break; - case 0x0f: /* XSDRTDOB */ + + case XSDRTDOB: + LOG_ERROR("unsupported XSDRTDOB\n"); unsupported = 1; break; - case 0x10: /* XSDRTDOB */ + + case XSDRTDOC: + LOG_ERROR("unsupported XSDRTDOC\n"); unsupported = 1; break; - case 0x11: /* XSDRTDOB */ + + case XSDRTDOE: + LOG_ERROR("unsupported XSDRTDOE\n"); unsupported = 1; break; - case 0x12: /* XSTATE */ - LOG_DEBUG("XSTATE"); - if (read(xsvf_fd, &uc, 1) < 0) - do_abort = 1; - else + + case XSTATE: { - enum tap_state *path = calloc(XSTATE_MAX_PATH, 4); - int path_len = 1; - path[0] = xsvf_to_tap[uc]; + tap_state_t mystate; + tap_state_t *path; + int path_len; + + if (read(xsvf_fd, &uc, 1) < 0) + { + do_abort = 1; + break; + } + + mystate = xsvf_to_tap(uc); + + LOG_DEBUG("XSTATE 0x%02X %s", uc, jtag_state_name(mystate) ); + + path = calloc(XSTATE_MAX_PATH, 4); + path_len = 1; + + path[0] = mystate; if (xsvf_read_xstates(xsvf_fd, path, XSTATE_MAX_PATH, &path_len) != ERROR_OK) do_abort = 1; else { int i,lasti; + /* here the trick is that jtag_add_pathmove() must end in a stable - state, so we must only invoke jtag_add_tlr() when we absolutely - have to - */ - for(i=0,lasti=0;i<path_len;i++) + * state, so we must only invoke jtag_add_tlr() when we absolutely + * have to + */ + for(i=0,lasti=0; i<path_len; i++) { if(path[i]==TAP_RESET) { @@ -441,56 +599,100 @@ free(path); } break; - case 0x13: /* XENDIR */ - LOG_DEBUG("XENDIR"); - if (read(xsvf_fd, &c, 1) < 0) - do_abort = 1; - else + + case XENDIR: { - if (c == 0) - xendir = 1; - else if (c == 1) - xendir = 0xd; - else + tap_state_t mystate; + + if (read(xsvf_fd, &uc, 1) < 0) { - LOG_ERROR("unknown XENDIR endstate"); + do_abort = 1; + break; + } + + /* see page 22 of XSVF spec */ + mystate = uc == 1 ? TAP_IRPAUSE : TAP_IDLE; + + LOG_DEBUG("XENDIR 0x%02X %s", uc, jtag_state_name(mystate)); + + /* assuming that the XRUNTEST comes from SVF RUNTEST, then only these states + * should come here because the SVF spec only allows these with a RUNTEST + */ + if (mystate != TAP_IRPAUSE && mystate != TAP_DRPAUSE && mystate != TAP_RESET && mystate != TAP_IDLE ) + { + LOG_ERROR("illegal XENDIR endstate: \"%s\"", jtag_state_name(mystate)); unsupported = 1; + break; } + xendir = mystate; } break; - case 0x14: /* XENDDR */ - LOG_DEBUG("XENDDR"); - if (read(xsvf_fd, &c, 1) < 0) - do_abort = 1; - else + + case XENDDR: { - if (c == 0) - xenddr = 1; - else if (c == 1) - xenddr = 0x6; - else + tap_state_t mystate; + + if (read(xsvf_fd, &uc, 1) < 0) { - LOG_ERROR("unknown XENDDR endstate"); + do_abort = 1; + break; + } + + /* see page 22 of XSVF spec */ + mystate = uc == 1 ? TAP_DRPAUSE : TAP_IDLE; + + LOG_DEBUG("XENDDR %02X %s", uc, jtag_state_name(mystate)); + + if (mystate != TAP_IRPAUSE && mystate != TAP_DRPAUSE && mystate != TAP_RESET && mystate != TAP_IDLE ) + { + LOG_ERROR("illegal XENDDR endstate: \"%s\"", jtag_state_name( mystate )); unsupported = 1; + break; } + xenddr = mystate; } break; - case 0x15: /* XSIR2 */ - LOG_DEBUG("XSIR2"); - if (read(xsvf_fd, buf2, 2) < 0) - do_abort = 1; - else + + case XSIR: + case XSIR2: { - u8 *ir_buf; - us = be_to_h_u16(buf2); - ir_buf = malloc((us + 7) / 8); - if (xsvf_read_buffer(us, xsvf_fd, ir_buf) != ERROR_OK) + u8 short_buf[2]; + u8* ir_buf; + int bitcount; + tap_state_t my_end_state = xruntest ? TAP_IDLE : xendir; + + if( opcode == XSIR ) + { + /* one byte bitcount */ + if (read(xsvf_fd, short_buf, 1) < 0) + { + do_abort = 1; + break; + } + bitcount = short_buf[0]; + LOG_DEBUG("XSIR %d", bitcount); + } + else + { + if (read(xsvf_fd, short_buf, 2) < 0) + { + do_abort = 1; + break; + } + bitcount = be_to_h_u16(short_buf); + LOG_DEBUG("XSIR2 %d", bitcount); + } + + ir_buf = malloc((bitcount+7) / 8); + + if (xsvf_read_buffer(bitcount, xsvf_fd, ir_buf) != ERROR_OK) do_abort = 1; else { scan_field_t field; + field.tap = tap; - field.num_bits = us; + field.num_bits = bitcount; field.out_value = ir_buf; field.out_mask = NULL; field.in_value = NULL; @@ -498,61 +700,297 @@ field.in_check_mask = NULL; field.in_handler = NULL; field.in_handler_priv = NULL; + if (tap == NULL) - jtag_add_plain_ir_scan(1, &field, xsvf_to_tap[xendir]); + jtag_add_plain_ir_scan(1, &field, my_end_state); else - jtag_add_ir_scan(1, &field, xsvf_to_tap[xendir]); + jtag_add_ir_scan(1, &field, my_end_state); + + if (xruntest) + { + if (runtest_requires_tck) + jtag_add_clocks(xruntest); + else + jtag_add_sleep(xruntest); + } + + /* Note that an -irmask of non-zero in your config file + * can cause this to fail. Setting -irmask to zero cand work + * around the problem. + */ + + /* LOG_DEBUG("FLUSHING QUEUE"); */ + result = jtag_execute_queue(); + if(result != ERROR_OK) + { + tdo_mismatch = 1; + } } free(ir_buf); } break; - case 0x16: /* XCOMMENT */ - do + + case XCOMMENT: { - if (read(xsvf_fd, &c, 1) < 0) + int ndx = 0; + char comment[128]; + + do { + if (read(xsvf_fd, &uc, 1) < 0) + { + do_abort = 1; + break; + } + + if ( ndx < sizeof(comment)-1 ) + comment[ndx++] = uc; + + } while (uc != 0); + + comment[sizeof(comment)-1] = 0; /* regardless, terminate */ + LOG_USER(comment); + } + break; + + case XWAIT: + { + /* expected in stream: + XWAIT <u8 wait_state> <u8 end_state> <u32 usecs> + */ + + u8 wait; + u8 end; + u8 delay_buf[4]; + + tap_state_t wait_state; + tap_state_t end_state; + int delay; + + if ( read(xsvf_fd, &wait, 1) < 0 + || read(xsvf_fd, &end, 1) < 0 + || read(xsvf_fd, delay_buf, 4) < 0) + { do_abort = 1; break; } - } while (c != 0); + + wait_state = xsvf_to_tap(wait); + end_state = xsvf_to_tap(end); + delay = be_to_h_u32(delay_buf); + + LOG_DEBUG("XWAIT %s %s usecs:%d", jtag_state_name(wait_state), jtag_state_name(end_state), delay); + + if (runtest_requires_tck && wait_state == TAP_IDLE ) + { + jtag_add_runtest(delay, end_state); + } + else + { + xsvf_add_statemove( wait_state ); + jtag_add_sleep(delay); + xsvf_add_statemove( end_state ); + } + } break; - case 0x17: /* XWAIT */ - LOG_DEBUG("XWAIT"); - if ((read(xsvf_fd, &uc, 1) < 0) || (read(xsvf_fd, &uc2, 1) < 0) || (read(xsvf_fd, buf4, 4) < 0)) - do_abort = 1; - else + + case XWAITSTATE: { - xsvf_add_statemove(xsvf_to_tap[uc]); - ui = be_to_h_u32(buf4); - jtag_add_sleep(ui); - xsvf_add_statemove(xsvf_to_tap[uc2]); + /* expected in stream: + XWAITSTATE <u8 wait_state> <u8 end_state> <u32 clock_count> <u32 usecs> + */ + + u8 clock_buf[4]; + u8 usecs_buf[4]; + u8 wait; + u8 end; + tap_state_t wait_state; + tap_state_t end_state; + int clock_count; + int usecs; + + if ( read(xsvf_fd, &wait, 1) < 0 + || read(xsvf_fd, &end, 1) < 0 + || read(xsvf_fd, clock_buf, 4) < 0 + || read(xsvf_fd, usecs_buf, 4) < 0 ) + { + do_abort = 1; + break; + } + + wait_state = xsvf_to_tap( wait ); + end_state = xsvf_to_tap( end ); + + clock_count = be_to_h_u32(clock_buf); + usecs = be_to_h_u32(usecs_buf); + + LOG_DEBUG("XWAITSTATE %s %s clocks:%i usecs:%i", + jtag_state_name(wait_state), + jtag_state_name(end_state), + clock_count, usecs); + + /* the following states are 'stable', meaning that they have a transition + * in the state diagram back to themselves. This is necessary because we will + * be issuing a number of clocks in this state. This set of allowed states is also + * determined by the SVF RUNTEST command's allowed states. + */ + if (wait_state != TAP_IRPAUSE && wait_state != TAP_DRPAUSE && wait_state != TAP_RESET && wait_state != TAP_IDLE) + { + LOG_ERROR("illegal XWAITSTATE wait_state: \"%s\"", jtag_state_name( wait_state )); + unsupported = 1; + } + + xsvf_add_statemove( wait_state ); + + jtag_add_clocks( clock_count ); + + jtag_add_sleep( usecs ); + + xsvf_add_statemove( end_state ); } break; + + case LCOUNT: + { + /* expected in stream: + LCOUNT <u32 loop_count> + */ + u8 count_buf[4]; + + if ( read(xsvf_fd, count_buf, 4) < 0 ) + { + do_abort = 1; + break; + } + + loop_count = be_to_h_u32(count_buf); + LOG_DEBUG("LCOUNT %d", loop_count); + } + break; + + case LDELAY: + { + /* expected in stream: + LDELAY <u8 wait_state> <u32 clock_count> <u32 usecs_to_sleep> + */ + u8 state; + u8 clock_buf[4]; + u8 usecs_buf[4]; + + if ( read(xsvf_fd, &state, 1) < 0 + || read(xsvf_fd, clock_buf, 4) < 0 + || read(xsvf_fd, usecs_buf, 4) < 0 ) + { + do_abort = 1; + break; + } + + loop_state = xsvf_to_tap(state); + loop_clocks = be_to_h_u32(clock_buf); + loop_usecs = be_to_h_u32(usecs_buf); + + LOG_DEBUG("LDELAY %s clocks:%d usecs:%d", jtag_state_name(loop_state), loop_clocks, loop_usecs); + } + break; + + /* LSDR is more like XSDRTDO than it is like XSDR. It uses LDELAY which + * comes with clocks !AND! sleep requirements. + */ + case LSDR: + { + int limit = loop_count; + int matched = 0; + int attempt; + + LOG_DEBUG("LSDR"); + + if ( xsvf_read_buffer(xsdrsize, xsvf_fd, dr_out_buf) != ERROR_OK + || xsvf_read_buffer(xsdrsize, xsvf_fd, dr_in_buf) != ERROR_OK ) + { + do_abort = 1; + break; + } + + if (limit < 1) + limit = 1; + + for( attempt=0; attempt<limit; ++attempt ) + { + scan_field_t field; + + field.tap = tap; + field.num_bits = xsdrsize; + field.out_value = dr_out_buf; + field.out_mask = NULL; + field.in_value = NULL; + + if (attempt > 0) + LOG_USER("LSDR retry %d", attempt); + + jtag_set_check_value(&field, dr_in_buf, dr_in_mask, NULL); + if (tap == NULL) + jtag_add_plain_dr_scan(1, &field, loop_state); + else + jtag_add_dr_scan(1, &field, loop_state); + + /* LOG_DEBUG("FLUSHING QUEUE"); */ + result = jtag_execute_queue(); + if(result == ERROR_OK) + { + matched = 1; + break; + } + + jtag_add_clocks(loop_clocks); + jtag_add_sleep(loop_usecs); + } + + if (!matched ) + { + LOG_USER( "LSDR mismatch" ); + tdo_mismatch = 1; + break; + } + } + break; + default: - LOG_ERROR("unknown xsvf command (0x%2.2x)\n", c); + LOG_ERROR("unknown xsvf command (0x%02X)\n", uc); unsupported = 1; } if (do_abort || unsupported || tdo_mismatch) + { + LOG_DEBUG("xsvf failed, setting taps to reasonable state"); + + /* upon error, return the TAPs to a reasonable state */ + xsvf_add_statemove( TAP_IDLE ); + jtag_execute_queue(); break; + } } if (tdo_mismatch) { - command_print(cmd_ctx, "TDO mismatch, aborting"); - return ERROR_OK; + command_print(cmd_ctx, "TDO mismatch, somewhere near offset %lu in xsvf file, aborting", + file_offset ); + + + return ERROR_FAIL; } if (unsupported) { - command_print(cmd_ctx, "unsupported xsvf command encountered, aborting"); - return ERROR_OK; + command_print(cmd_ctx, + "unsupported xsvf command: 0x%02X in xsvf file at offset %ld, aborting", + uc, lseek(xsvf_fd, 0, SEEK_CUR)-1 ); + return ERROR_FAIL; } if (do_abort) { - command_print(cmd_ctx, "premature end detected, aborting"); - return ERROR_OK; + command_print(cmd_ctx, "premature end of xsvf file detected, aborting"); + return ERROR_FAIL; } if (dr_out_buf) @@ -570,3 +1008,54 @@ return ERROR_OK; } + + +/* PSUEDO-Code from Xilinx Appnote XAPP067.pdf: + +the following pseudo code clarifies the intent of the xrepeat support. The +flow given is for the entire processing of an SVF file, not an XSVF file. +No idea if this is just for the XC9500/XL/XV devices or all Xilinx parts. + +"Pseudo-Code Algorithm for SVF-Based ISP" + +1. Go to Test-Logic-Reset state +2. Go to Run-Test Idle state +3. Read SVF record + +4. if SIR record then + go to Shift-IR state + Scan in <TDI value> + +5. else if SDR record then + set <repeat count> to 0 + store <TDI value> as <current TDI value> + store <TDO value> as <current TDO value> +6. go to Shift-DR state + scan in <current TDI value> + if <current TDO value> is specified then + if <current TDO value> does not equal <actual TDO value> then + if <repeat count> > 32 then + LOG ERROR + go to Run-Test Idle state + go to Step 3 + end if + go to Pause-DR + go to Exit2-DR + go to Shift-DR + go to Exit1-DR + go to Update-DR + go to Run-Test/Idle + increment <repeat count> by 1 + pause <current pause time> microseconds + go to Step 6) + end if + else + go to Run-Test Idle state + go to Step 3 + endif +else if RUNTEST record then + pause tester for <TCK value> microseconds + store <TCK value> as <current pause time> +end if + +*/ |
From: ntfreak at B. <nt...@ma...> - 2009-01-08 18:23:56
|
Author: ntfreak Date: 2009-01-08 18:23:55 +0100 (Thu, 08 Jan 2009) New Revision: 1307 Modified: trunk/doc/openocd.1 Log: Updates and fixes for the manpage from Uwe Hermann - Mention that MIPS systems are supported - Mention Jim Tcl engine - Point to info page (not README) for a list of supported stuff - Document missing --pipe option - Fix copy-paste error ("flex" should have been "openocd") Modified: trunk/doc/openocd.1 =================================================================== --- trunk/doc/openocd.1 2009-01-08 11:46:55 UTC (rev 1306) +++ trunk/doc/openocd.1 2009-01-08 17:23:55 UTC (rev 1307) @@ -1,37 +1,39 @@ -.TH "OPENOCD" "1" "February 29, 2008" +.TH "OPENOCD" "1" "January 08, 2009" .SH "NAME" openocd \- A free and open on\-chip debugging, in\-system programming and -boundary\-scan testing tool for ARM systems +boundary\-scan testing tool for ARM and MIPS systems .SH "SYNOPSIS" -.B openocd \fR[\fB\-fsdlchv\fR] [\fB\-\-file\fR <filename>] [\fB\-\-search\fR <dirname>] [\fB\-\-debug\fR <debuglevel>] [\fB\-\-log_output\fR <filename>] [\fB\-\-command\fR <cmd>] [\fB\-\-help\fR] [\fB\-\-version\fR] +.B openocd \fR[\fB\-fsdlcphv\fR] [\fB\-\-file\fR <filename>] [\fB\-\-search\fR <dirname>] [\fB\-\-debug\fR <debuglevel>] [\fB\-\-log_output\fR <filename>] [\fB\-\-command\fR <cmd>] [\fB\-\-pipe\fR] [\fB\-\-help\fR] [\fB\-\-version\fR] .SH "DESCRIPTION" .B OpenOCD is an on\-chip debugging, in\-system programming and boundary\-scan -testing tool for ARM systems. +testing tool for various ARM and MIPS systems. .PP The debugger uses an IEEE 1149\-1 compliant JTAG TAP bus master to access -on\-chip debug functionality available on ARM7/9, XScale, Cortex-M3, and -Marvell Feroceon (as found in the Orion SoC family) based -microcontrollers / system\-on\-chip solutions. +on\-chip debug functionality available on ARM based microcontrollers or +system-on-chip solutions. For MIPS systems the EJTAG interface is supported. .PP -User interaction is realized through a telnet command line interface and -a gdb (the GNU debugger) remote protocol server. +User interaction is realized through a telnet command line interface, +a gdb (the GNU debugger) remote protocol server, and a simplified RPC +connection that can be used to interface with OpenOCD's Jim Tcl engine. .PP OpenOCD supports various different types of JTAG interfaces/programmers, -please check the README for the complete list. +please check the \fIopenocd\fR info page for the complete list. .SH "OPTIONS" .TP .B "\-f, \-\-file <filename>" Use configuration file .BR <filename> . -If this option is omitted, the config file +In order to specify multiple config files, you can use multiple +.B \-\-file +arguments. If this option is omitted, the config file .B openocd.cfg in the current working directory will be used. .TP .B "\-s, \-\-search <dirname>" Search for config files and scripts in the directory .BR <dirname> . -If this option is omitted, openocd searches for config files and scripts +If this option is omitted, OpenOCD searches for config files and scripts in the current directory. .TP .B "\-d, \-\-debug <debuglevel>" @@ -58,6 +60,9 @@ Run the command .BR <cmd> . .TP +.B "\-p, \-\-pipe" +Use pipes when talking to gdb. +.TP .B "\-h, \-\-help" Show a help text and exit. .TP @@ -78,10 +83,12 @@ .B openocd is maintained as a Texinfo manual. If the .BR info +(or +.BR pinfo ) and .BR openocd programs are properly installed at your site, the command -.B info flex +.B info openocd should give you access to the complete manual. .PP Also, the OpenOCD wiki contains some more information and examples: |
From: ntfreak at B. <nt...@ma...> - 2009-01-08 12:46:59
|
Author: ntfreak Date: 2009-01-08 12:46:55 +0100 (Thu, 08 Jan 2009) New Revision: 1306 Modified: trunk/doc/openocd.texi Log: - a few more docs tweaks Modified: trunk/doc/openocd.texi =================================================================== --- trunk/doc/openocd.texi 2009-01-07 21:16:06 UTC (rev 1305) +++ trunk/doc/openocd.texi 2009-01-08 11:46:55 UTC (rev 1306) @@ -3184,24 +3184,29 @@ @* In digital circuit design it is often refered to as ``clock -syncronization'' the JTAG interface uses one clock (TCK or TCLK) +synchronisation'' the JTAG interface uses one clock (TCK or TCLK) operating at some speed, your target is operating at another. The two -clocks are not syncronized, they are ``asynchronous'' +clocks are not synchronised, they are ``asynchronous'' -In order for the two to work together they must syncronize. Otherwise +In order for the two to work together they must be synchronised. Otherwise the two systems will get out of sync with each other and nothing will -work. There are 2 basic options. @b{1.} use a special circuit or -@b{2.} one clock must be some multile slower the the other. +work. There are 2 basic options. +@enumerate +@item +Use a special circuit. +@item +One clock must be some multiple slower the the other. +@end enumerate @b{Does this really matter?} For some chips and some situations, this -is a non-issue (ie: A 500mhz ARM926) but for others - for example some -ATMEL SAM7 and SAM9 chips start operation from reset at 32khz - +is a non-issue (ie: A 500MHz ARM926) but for others - for example some +ATMEL SAM7 and SAM9 chips start operation from reset at 32kHz - program/enable the oscillators and eventually the main clock. It is in those critical times you must slow the jtag clock to sometimes 1 to -4khz. +4kHz. -Imagine debugging that 500mhz arm926 hand held battery powered device -that ``deep sleeps'' at 32khz between every keystroke. It can be +Imagine debugging that 500MHz ARM926 hand held battery powered device +that ``deep sleeps'' at 32kHz between every keystroke. It can be painful. @b{Solution #1 - A special circuit} @@ -3213,14 +3218,14 @@ this problem. ARM has a good description of the problem described at this link: @url{http://www.arm.com/support/faqdev/4170.html} [checked 28/nov/2008]. Link title: ``How does the jtag synchronisation logic -work? / how does adaptive clocking working?''. +work? / how does adaptive clocking work?''. The nice thing about adaptive clocking is that ``battery powered hand held device example'' - the adaptiveness works perfectly all the time. One can set a break point or halt the system in the deep power down code, slow step out until the system speeds up. -@b{Solution #2 - Always works - but is slower} +@b{Solution #2 - Always works - but may be slower} Often this is a perfectly acceptable solution. @@ -3230,7 +3235,7 @@ based systems require an 8:1 division. @b{Xilinx Rule of thumb} is 1/12 the clock speed. -Note: Many FTDI2232C based JTAG dongles are limited to 6mhz. +Note: Many FTDI2232C based JTAG dongles are limited to 6MHz. You can still debug the 'lower power' situations - you just need to manually adjust the clock speed at every step. While painful and @@ -3244,7 +3249,7 @@ To set the JTAG frequency use the command: @example - # Example: 1.234mhz + # Example: 1.234MHz jtag_khz 1234 @end example @@ -3390,7 +3395,7 @@ Many newer devices have multiple JTAG taps. For example: ST Microsystems STM32 chips have two taps, a ``boundary scan tap'' and -``cortexM3'' tap. Example: The STM32 reference manual, Document ID: +``CortexM3'' tap. Example: The STM32 reference manual, Document ID: RM0008, Section 26.5, Figure 259, page 651/681, the ``TDI'' pin is connected to the Boundary Scan Tap, which then connects to the CortexM3 Tap, which then connects to the TDO pin. |
From: ntfreak at B. <nt...@ma...> - 2009-01-07 22:16:07
|
Author: ntfreak Date: 2009-01-07 22:16:06 +0100 (Wed, 07 Jan 2009) New Revision: 1305 Modified: trunk/doc/openocd.texi Log: - minor doc updates regarding tap creation and gdb connection using pipes Modified: trunk/doc/openocd.texi =================================================================== --- trunk/doc/openocd.texi 2009-01-07 14:55:52 UTC (rev 1304) +++ trunk/doc/openocd.texi 2009-01-07 21:16:06 UTC (rev 1305) @@ -1517,8 +1517,6 @@ bits long, during Capture-IR 0x42 is loaded into the IR, and bits [6,4,2,0] are checked. -FIXME: The IDCODE - this was not used in the old code, it should be? -Right? -Duane. @item @b{Optional configparams} @comment START Optional @itemize @bullet @@ -1613,13 +1611,13 @@ @* @b{Removed: 28/nov/2008} This command has been removed and replaced by the ``jtag newtap'' command. The documentation remains here so that one can easily convert the old syntax to the new syntax. About the old -syntax: The old syntax is positional, ie: The 4th parameter is the +syntax: The old syntax is positional, ie: The 3rd parameter is the ``irmask''. The new syntax requires named prefixes, and supports -additional options, for example ``-irmask 4''. Please refer to the +additional options, for example ``-expected-id 0x3f0f0f0f''. Please refer to the @b{jtag newtap} command for details. @example -OLD: jtag_device 8 0x01 0x0e3 0xfe -NEW: jtag newtap CHIPNAME TAPNAME -irlen 8 -ircapture 0xe3 -irmask 0xfe +OLD: jtag_device 8 0x01 0xe3 0xfe +NEW: jtag newtap CHIPNAME TAPNAME -irlen 8 -ircapture 0x01 -irmask 0xe3 @end example @section Enable/Disable Taps @@ -2990,10 +2988,11 @@ @item A pipe connection is typically started as follows: @example -target remote openocd --pipe +target remote | openocd --pipe @end example This would cause GDB to run OpenOCD and communicate using pipes (stdin/stdout). -Using this method has the advantage of GDB starting/stopping OpenOCD for debug session. +Using this method has the advantage of GDB starting/stopping OpenOCD for the debug +session. @end enumerate @*To see a list of available OpenOCD commands type @option{monitor help} on the |
From: <oh...@ma...> - 2009-01-07 15:55:56
|
Author: oharboe Date: 2009-01-07 15:55:52 +0100 (Wed, 07 Jan 2009) New Revision: 1304 Modified: trunk/tools/xsvf_tools/svf2xsvf.py trunk/tools/xsvf_tools/xsvfdump.py Log: Dick Hollenbeck <di...@so...> SVF to XSVF converter and the XSVF dumper take #2 Modified: trunk/tools/xsvf_tools/svf2xsvf.py =================================================================== --- trunk/tools/xsvf_tools/svf2xsvf.py 2009-01-07 07:08:02 UTC (rev 1303) +++ trunk/tools/xsvf_tools/svf2xsvf.py 2009-01-07 14:55:52 UTC (rev 1304) @@ -1,693 +1,699 @@ -#!/usr/bin/python3.0 - -# Copyright 2008, SoftPLC Corporation http://softplc.com -# Dick Hollenbeck di...@so... - - -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, you may find one here: -# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html -# or you may search the http://www.gnu.org website for the version 2 license, -# or you may write to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - - -# A python program to convert an SVF file to an XSVF file. There is an -# option to include comments containing the source file line number from the origin -# SVF file before each outputted XSVF statement. -# -# We deviate from the XSVF spec in that we introduce a new command called -# XWAITSTATE which directly flows from the SVF RUNTEST command. Unfortunately -# XRUNSTATE was ill conceived and is not used here. We also add support for the -# three Lattice extensions to SVF: LCOUNT, LDELAY, and LSDR. The xsvf file -# generated from this program is suitable for use with the xsvf player in -# OpenOCD with my modifications to xsvf.c. -# -# This program is written for python 3.0, and it is not easy to change this -# back to 2.x. You may find it easier to use python 3.x even if that means -# building it. - - -import re -import sys -import struct - - -# There are both ---<Lexer>--- and ---<Parser>--- sections to this program - - -if len( sys.argv ) < 3: - print("usage %s <svf_filename> <xsvf_filename>" % sys.argv[0]) - exit(1) - - -inputFilename = sys.argv[1] -outputFilename = sys.argv[2] - -doCOMMENTs = True # Save XCOMMENTs in the output xsvf file -#doCOMMENTs = False # Save XCOMMENTs in the output xsvf file - -xrepeat = 0 # argument to XREPEAT, gives retry count for masked compares - - -#-----< Lexer >--------------------------------------------------------------- - -StateBin = (RESET,IDLE, - DRSELECT,DRCAPTURE,DRSHIFT,DREXIT1,DRPAUSE,DREXIT2,DRUPDATE, - IRSELECT,IRCAPTURE,IRSHIFT,IREXIT1,IRPAUSE,IREXIT2,IRUPDATE) = range(16) - -# Any integer index into this tuple will be equal to its corresponding StateBin value -StateTxt = ("RESET","IDLE", - "DRSELECT","DRCAPTURE","DRSHIFT","DREXIT1","DRPAUSE","DREXIT2","DRUPDATE", - "IRSELECT","IRCAPTURE","IRSHIFT","IREXIT1","IRPAUSE","IREXIT2","IRUPDATE") - - -(XCOMPLETE,XTDOMASK,XSIR,XSDR,XRUNTEST,hole0,hole1,XREPEAT,XSDRSIZE,XSDRTDO, - XSETSDRMASKS,XSDRINC,XSDRB,XSDRC,XSDRE,XSDRTDOB,XSDRTDOC, - XSDRTDOE,XSTATE,XENDIR,XENDDR,XSIR2,XCOMMENT,XWAIT,XWAITSTATE,LCOUNT,LDELAY,LSDR) = range(28) - -#Note: LCOUNT, LDELAY, and LSDR are Lattice extensions to SVF and provide a way to loop back -# and check a completion status, essentially waiting on a part until it signals that it is done. -# For example below: loop 25 times, each time through the loop do a LDELAY (same as a true RUNTEST) -# and exit loop when LSDR compares match. -""" -LCOUNT 25; -! Step to DRPAUSE give 5 clocks and wait for 1.00e+000 SEC. -LDELAY DRPAUSE 5 TCK 1.00E-003 SEC; -! Test for the completed status. Match means pass. -! Loop back to LDELAY line if not match and loop count less than 25. -LSDR 1 TDI (0) - TDO (1); -""" - -LineNumber = 1 - -def s_ident(scanner, token): return ("ident", token.upper(), LineNumber) - -def s_hex(scanner, token): - global LineNumber - LineNumber = LineNumber + token.count('\n') - token = ''.join(token.split()) - return ("hex", token[1:-1], LineNumber) - -def s_int(scanner, token): return ("int", int(token), LineNumber) -def s_float(scanner, token): return ("float", float(token), LineNumber) -#def s_comment(scanner, token): return ("comment", token, LineNumber) -def s_semicolon(scanner, token): return ("semi", token, LineNumber) - -def s_nl(scanner,token): - global LineNumber - LineNumber = LineNumber + 1 - #print( 'LineNumber=', LineNumber, file=sys.stderr ) - return None - -#2.00E-002 - -scanner = re.Scanner([ - (r"[a-zA-Z]\w*", s_ident), -# (r"[-+]?[0-9]+[.]?[0-9]*([eE][-+]?[0-9]+)?", s_float), - (r"[-+]?[0-9]+(([.][0-9eE+-]*)|([eE]+[-+]?[0-9]+))", s_float), - (r"\d+", s_int), - (r"\(([0-9a-fA-F]|\s)*\)", s_hex), - (r"(!|//).*$", None), - (r";", s_semicolon), - (r"\n",s_nl), - (r"\s*", None), - ], - re.MULTILINE - ) - -# read all svf file input into string "input" -input = open( sys.argv[1] ).read() - -# Lexer: -# create a list of tuples containing (tokenType, tokenValue, LineNumber) -tokens = scanner.scan( input )[0] - -input = None # allow gc to reclaim memory holding file - -#for tokenType, tokenValue, ln in tokens: print( "line %d: %s" % (ln, tokenType), tokenValue ) - - -#-----<parser>----------------------------------------------------------------- - -tokVal = tokType = tokLn = None - -tup = iter( tokens ) - -def nextTok(): - """ - Function to read the next token from tup into tokType, tokVal, tokLn (linenumber) - which are globals. - """ - global tokType, tokVal, tokLn, tup - tokType, tokVal, tokLn = tup.__next__() - - -class ParseError(Exception): - """A class to hold a parsing error message""" - def __init__(self, linenumber, token, message): - self.linenumber = linenumber - self.token = token - self.message = message - def __str__(self): - global inputFilename - return "Error in file \'%s\' at line %d near token %s\n %s" % ( - inputFilename, self.linenumber, repr(self.token), self.message) - - -class MASKSET(object): - """ - Class MASKSET holds a set of bit vectors, all of which are related, will all - have the same length, and are associated with one of the seven shiftOps: - HIR, HDR, TIR, TDR, SIR, SDR, LSDR. One of these holds a mask, smask, tdi, tdo, and a - size. - """ - def __init__(self, name): - self.empty() - self.name = name - - def empty(self): - self.mask = bytearray() - self.smask = bytearray() - self.tdi = bytearray() - self.tdo = bytearray() - self.size = 0 - - def syncLengths( self, sawTDI, sawTDO, sawMASK, sawSMASK, newSize ): - """ - Set all the lengths equal in the event some of the masks were - not seen as part of the last change set. - """ - if self.size == newSize: - return - - if newSize == 0: - self.empty() - return - - # If an SIR was given without a MASK(), then use a mask of all zeros. - # this is not consistent with the SVF spec, but it makes sense because - # it would be odd to be testing an instruction register read out of a - # tap without giving a mask for it. Also, lattice seems to agree and is - # generating SVF files that comply with this philosophy. - if self.name == 'SIR' and not sawMASK: - self.mask = bytearray( newSize ) - - if newSize != len(self.mask): - self.mask = bytearray( newSize ) - if self.name == 'SDR': # leave mask for HIR,HDR,TIR,TDR,SIR zeros - for i in range( newSize ): - self.mask[i] = 1 - - if newSize != len(self.tdo): - self.tdo = bytearray( newSize ) - - if newSize != len(self.tdi): - self.tdi = bytearray( newSize ) - - if newSize != len(self.smask): - self.smask = bytearray( newSize ) - - self.size = newSize -#-----</MASKSET>----- - - -def makeBitArray( hexString, bitCount ): - """ - Converts a packed sequence of hex ascii characters into a bytearray where - each element in the array holds exactly one bit. Only "bitCount" bits are - scanned and these must be the least significant bits in the hex number. That - is, it is legal to have some unused bits in the must significant hex nibble - of the input "hexString". The string is scanned starting from the backend, - then just before returning we reverse the array. This way the append() - method can be used, which I assume is faster than an insert. - """ - global tokLn - a = bytearray() - length = bitCount - hexString = list(hexString) - hexString.reverse() - #print(hexString) - for c in hexString: - if length <= 0: - break; - c = int(c, 16) - for mask in [1,2,4,8]: - if length <= 0: - break; - length = length - 1 - a.append( (c & mask) != 0 ) - if length > 0: - raise ParseError( tokLn, hexString, "Insufficient hex characters for given length of %d" % bitCount ) - a.reverse() - #print(a) - return a - - -def makeXSVFbytes( bitarray ): - """ - Make a bytearray which is contains the XSVF bits which will be written - directly to disk. The number of bytes needed is calculated from the size - of the argument bitarray. - """ - bitCount = len(bitarray) - byteCount = (bitCount+7)//8 - ba = bytearray( byteCount ) - firstBit = (bitCount % 8) - 1 - if firstBit == -1: - firstBit = 7 - bitNdx = 0 - for byteNdx in range(byteCount): - mask = 1<<firstBit - byte = 0 - while mask: - if bitarray[bitNdx]: - byte |= mask; - mask = mask >> 1 - bitNdx = bitNdx + 1 - ba[byteNdx] = byte - firstBit = 7 - return ba - - -def writeComment( outputFile, shiftOp_linenum, shiftOp ): - """ - Write an XCOMMENT record to outputFile - """ - comment = "%s @%d\0" % (shiftOp, shiftOp_linenum) # \0 is terminating nul - ba = bytearray(1) - ba[0] = XCOMMENT - ba += comment.encode() - outputFile.write( ba ) - - -def combineBitVectors( trailer, meat, header ): - """ - Combine the 3 bit vectors comprizing a transmission. Since the least - significant bits are sent first, the header is put onto the list last so - they are sent first from that least significant position. - """ - ret = bytearray() - ret.extend( trailer ) - ret.extend( meat ) - ret.extend( header ) - return ret - - -def writeRUNTEST( outputFile, run_state, end_state, run_count, min_time, tokenTxt ): - """ - Write the output for the SVF RUNTEST command. - run_count - the number of clocks - min_time - the number of seconds - tokenTxt - either RUNTEST or LDELAY - """ - # convert from secs to usecs - min_time = int( min_time * 1000000) - - # the SVF RUNTEST command does NOT map to the XSVF XRUNTEST command. Check the SVF spec, then - # read the XSVF command. They are not the same. Use an XSVF XWAITSTATE to - # implement the required behavior of the SVF RUNTEST command. - if doCOMMENTs: - writeComment( output, tokLn, tokenTxt ) - - if tokenTxt == 'RUNTEST': - obuf = bytearray(11) - obuf[0] = XWAITSTATE - obuf[1] = run_state - obuf[2] = end_state - struct.pack_into(">i", obuf, 3, run_count ) # big endian 4 byte int to obuf - struct.pack_into(">i", obuf, 7, min_time ) # big endian 4 byte int to obuf - outputFile.write( obuf ) - else: # == 'LDELAY' - obuf = bytearray(10) - obuf[0] = LDELAY - obuf[1] = run_state - # LDELAY has no end_state - struct.pack_into(">i", obuf, 2, run_count ) # big endian 4 byte int to obuf - struct.pack_into(">i", obuf, 6, min_time ) # big endian 4 byte int to obuf - outputFile.write( obuf ) - - -output = open( outputFilename, mode='wb' ) - -hir = MASKSET('HIR') -hdr = MASKSET('HDR') -tir = MASKSET('TIR') -tdr = MASKSET('TDR') -sir = MASKSET('SIR') -sdr = MASKSET('SDR') - - -expecting_eof = True - - -# one of the commands that take the shiftParts after the length, the parse -# template for all of these commands is identical -shiftOps = ('SDR', 'SIR', 'LSDR', 'HDR', 'HIR', 'TDR', 'TIR') - -# the order must correspond to shiftOps, this holds the MASKSETS. 'LSDR' shares sdr with 'SDR' -shiftSets = (sdr, sir, sdr, hdr, hir, tdr, tir ) - -# what to expect as parameters to a shiftOp, i.e. after a SDR length or SIR length -shiftParts = ('TDI', 'TDO', 'MASK', 'SMASK') - -# the set of legal states which can trail the RUNTEST command -run_state_allowed = ('IRPAUSE', 'DRPAUSE', 'RESET', 'IDLE') - -enddr_state_allowed = ('DRPAUSE', 'IDLE', 'RESET') -endir_state_allowed = ('IRPAUSE', 'IDLE', 'RESET') - -enddr_state = IDLE -endir_state = IDLE - -frequency = 1.00e+006 # HZ; - -# change detection for xsdrsize and xtdomask -xsdrsize = -1 # the last one sent, send only on change -xtdomask = bytearray() # the last one sent, send only on change - - -# we use a number of single byte writes for the XSVF command below -cmdbuf = bytearray(1) - - -# Save the XREPEAT setting into the file as first thing. -obuf = bytearray(2) -obuf[0] = XREPEAT -obuf[1] = xrepeat -output.write( obuf ) - - -try: - while 1: - expecting_eof = True - nextTok() - expecting_eof = False - # print( tokType, tokVal, tokLn ) - - if tokVal in shiftOps: - shiftOp_linenum = tokLn - shiftOp = tokVal - - set = shiftSets[shiftOps.index(shiftOp)] - - # set flags false, if we see one later, set that one true later - sawTDI = sawTDO = sawMASK = sawSMASK = False - - nextTok() - if tokType != 'int': - raise ParseError( tokLn, tokVal, "Expecting 'int' giving %s length, got '%s'" % (shiftOp, tokType) ) - length = tokVal - - nextTok() - - while tokVal != ';': - if tokVal not in shiftParts: - raise ParseError( tokLn, tokVal, "Expecting TDI, TDO, MASK, SMASK, or ';'") - shiftPart = tokVal - - nextTok() - - if tokType != 'hex': - raise ParseError( tokLn, tokVal, "Expecting hex bits" ) - bits = makeBitArray( tokVal, length ) - - if shiftPart == 'TDI': - sawTDI = True - set.tdi = bits - - elif shiftPart == 'TDO': - sawTDO = True - set.tdo = bits - - elif shiftPart == 'MASK': - sawMASK = True - set.mask = bits - - elif shiftPart == 'SMASK': - sawSMASK = True - set.smask = bits - - nextTok() - - set.syncLengths( sawTDI, sawTDO, sawMASK, sawSMASK, length ) - - # process all the gathered parameters and generate outputs here - if shiftOp == 'SIR': - if doCOMMENTs: - writeComment( output, shiftOp_linenum, 'SIR' ) - - tdi = combineBitVectors( tir.tdi, sir.tdi, hir.tdi ) - if len(tdi) > 255: - obuf = bytearray(3) - obuf[0] = XSIR2 - struct.pack_into( ">h", obuf, 1, len(tdi) ) - else: - obuf = bytearray(2) - obuf[0] = XSIR - obuf[1] = len(tdi) - output.write( obuf ) - obuf = makeXSVFbytes( tdi ) - output.write( obuf ) - - elif shiftOp == 'SDR': - if doCOMMENTs: - writeComment( output, shiftOp_linenum, shiftOp ) - - if not sawTDO: - # pass a zero filled bit vector for the sdr.mask - mask = combineBitVectors( tdr.mask, bytearray(sdr.size), hdr.mask ) - tdi = combineBitVectors( tdr.tdi, sdr.tdi, hdr.tdi ) - - if xsdrsize != len(tdi): - xsdrsize = len(tdi) - cmdbuf[0] = XSDRSIZE - output.write( cmdbuf ) - obuf = bytearray(4) - struct.pack_into( ">i", obuf, 0, xsdrsize ) # big endian 4 byte int to obuf - output.write( obuf ) - - if xtdomask != mask: - xtdomask = mask - cmdbuf[0] = XTDOMASK - output.write( cmdbuf ) - obuf = makeXSVFbytes( mask ) - output.write( obuf ) - - cmdbuf[0] = XSDR - output.write( cmdbuf ) - obuf = makeXSVFbytes( tdi ) - output.write( obuf ) - - else: - mask = combineBitVectors( tdr.mask, sdr.mask, hdr.mask ) - tdi = combineBitVectors( tdr.tdi, sdr.tdi, hdr.tdi ) - tdo = combineBitVectors( tdr.tdo, sdr.tdo, hdr.tdo ) - - if xsdrsize != len(tdi): - xsdrsize = len(tdi) - cmdbuf[0] = XSDRSIZE - output.write( cmdbuf ) - obuf = bytearray(4) - struct.pack_into(">i", obuf, 0, xsdrsize ) # big endian 4 byte int to obuf - output.write( obuf ) - - if xtdomask != mask: - xtdomask = mask - cmdbuf[0] = XTDOMASK - output.write( cmdbuf ) - obuf = makeXSVFbytes( mask ) - output.write( obuf ) - - cmdbuf[0] = XSDRTDO - output.write( cmdbuf ) - obuf = makeXSVFbytes( tdi ) - output.write( obuf ) - obuf = makeXSVFbytes( tdo ) - output.write( obuf ) - #print( "len(tdo)=", len(tdo), "len(tdr.tdo)=", len(tdr.tdo), "len(sdr.tdo)=", len(sdr.tdo), "len(hdr.tdo)=", len(hdr.tdo) ) - - elif shiftOp == 'LSDR': - if doCOMMENTs: - writeComment( output, shiftOp_linenum, shiftOp ) - - mask = combineBitVectors( tdr.mask, sdr.mask, hdr.mask ) - tdi = combineBitVectors( tdr.tdi, sdr.tdi, hdr.tdi ) - tdo = combineBitVectors( tdr.tdo, sdr.tdo, hdr.tdo ) - - if xsdrsize != len(tdi): - xsdrsize = len(tdi) - cmdbuf[0] = XSDRSIZE - output.write( cmdbuf ) - obuf = bytearray(4) - struct.pack_into(">i", obuf, 0, xsdrsize ) # big endian 4 byte int to obuf - output.write( obuf ) - - if xtdomask != mask: - xtdomask = mask - cmdbuf[0] = XTDOMASK - output.write( cmdbuf ) - obuf = makeXSVFbytes( mask ) - output.write( obuf ) - - cmdbuf[0] = LSDR - output.write( cmdbuf ) - obuf = makeXSVFbytes( tdi ) - output.write( obuf ) - obuf = makeXSVFbytes( tdo ) - output.write( obuf ) - #print( "len(tdo)=", len(tdo), "len(tdr.tdo)=", len(tdr.tdo), "len(sdr.tdo)=", len(sdr.tdo), "len(hdr.tdo)=", len(hdr.tdo) ) - - elif tokVal == 'RUNTEST' or tokVal == 'LDELAY': - # e.g. from lattice tools: - # "RUNTEST IDLE 5 TCK 1.00E-003 SEC;" - saveTok = tokVal - nextTok() - min_time = 0 - run_count = 0 - max_time = 600 # ten minutes - if tokVal in run_state_allowed: - run_state = StateTxt.index(tokVal) - end_state = run_state # bottom of page 17 of SVF spec - nextTok() - if tokType != 'int' and tokType != 'float': - raise ParseError( tokLn, tokVal, "Expecting 'int' or 'float' after RUNTEST [run_state]") - timeval = tokVal; - nextTok() - if tokVal != 'TCK' and tokVal != 'SEC' and tokVal != 'SCK': - raise ParseError( tokLn, tokVal, "Expecting 'TCK' or 'SEC' or 'SCK' after RUNTEST [run_state] (run_count|min_time)") - if tokVal == 'TCK' or tokVal == 'SCK': - run_count = int( timeval ) - else: - min_time = timeval - nextTok() - if tokType == 'int' or tokType == 'float': - min_time = tokVal - nextTok() - if tokVal != 'SEC': - raise ParseError( tokLn, tokVal, "Expecting 'SEC' after RUNTEST [run_state] run_count min_time") - nextTok() - if tokVal == 'MAXIMUM': - nextTok() - if tokType != 'int' and tokType != 'float': - raise ParseError( tokLn, tokVal, "Expecting 'max_time' after RUNTEST [run_state] min_time SEC MAXIMUM") - max_time = tokVal - nextTok() - if tokVal != 'SEC': - raise ParseError( tokLn, tokVal, "Expecting 'max_time' after RUNTEST [run_state] min_time SEC MAXIMUM max_time") - nextTok() - if tokVal == 'ENDSTATE': - nextTok() - if tokVal not in run_state_allowed: - raise ParseError( tokLn, tokVal, "Expecting 'run_state' after RUNTEST .... ENDSTATE") - end_state = StateTxt.index(tokVal) - nextTok() - if tokVal != ';': - raise ParseError( tokLn, tokVal, "Expecting ';' after RUNTEST ....") - # print( "run_count=", run_count, "min_time=", min_time, - # "max_time=", max_time, "run_state=", State[run_state], "end_state=", State[end_state] ) - writeRUNTEST( output, run_state, end_state, run_count, min_time, saveTok ) - - elif tokVal == 'LCOUNT': - nextTok() - if tokType != 'int': - raise ParseError( tokLn, tokVal, "Expecting integer 'count' after LCOUNT") - loopCount = tokVal - nextTok() - if tokVal != ';': - raise ParseError( tokLn, tokVal, "Expecting ';' after LCOUNT count") - if doCOMMENTs: - writeComment( output, tokLn, 'LCOUNT' ) - obuf = bytearray(5) - obuf[0] = LCOUNT - struct.pack_into(">i", obuf, 1, loopCount ) # big endian 4 byte int to obuf - output.write( obuf ) - - elif tokVal == 'ENDDR': - nextTok() - if tokVal not in enddr_state_allowed: - raise ParseError( tokLn, tokVal, "Expecting 'stable_state' after ENDDR. (one of: DRPAUSE, IDLE, RESET)") - enddr_state = StateTxt.index(tokVal) - nextTok() - if tokVal != ';': - raise ParseError( tokLn, tokVal, "Expecting ';' after ENDDR stable_state") - if doCOMMENTs: - writeComment( output, tokLn, 'ENDDR' ) - obuf = bytearray(2) - obuf[0] = XENDDR - obuf[1] = enddr_state - output.write( obuf ) - - elif tokVal == 'ENDIR': - nextTok() - if tokVal not in endir_state_allowed: - raise ParseError( tokLn, tokVal, "Expecting 'stable_state' after ENDIR. (one of: IRPAUSE, IDLE, RESET)") - endir_state = StateTxt.index(tokVal) - nextTok() - if tokVal != ';': - raise ParseError( tokLn, tokVal, "Expecting ';' after ENDIR stable_state") - if doCOMMENTs: - writeComment( output, tokLn, 'ENDIR' ) - obuf = bytearray(2) - obuf[0] = XENDIR - obuf[1] = endir_state - output.write( obuf ) - - elif tokVal == 'STATE': - nextTok() - ln = tokLn - while tokVal != ';': - if tokVal not in StateTxt: - raise ParseError( tokLn, tokVal, "Expecting 'stable_state' after STATE") - stable_state = StateTxt.index( tokVal ) - - if doCOMMENTs and ln != -1: - writeComment( output, ln, 'STATE' ) - ln = -1 # save comment only once - - obuf = bytearray(2) - obuf[0] = XSTATE - obuf[1] = stable_state - output.write( obuf ) - nextTok() - - elif tokVal == 'FREQUENCY': - nextTok() - if tokVal != ';': - if tokType != 'int' and tokType != 'float': - raise ParseError( tokLn, tokVal, "Expecting 'cycles HZ' after FREQUENCY") - frequency = tokVal - nextTok() - if tokVal != 'HZ': - raise ParseError( tokLn, tokVal, "Expecting 'HZ' after FREQUENCY cycles") - nextTok() - if tokVal != ';': - raise ParseError( tokLn, tokVal, "Expecting ';' after FREQUENCY cycles HZ") - - else: - raise ParseError( tokLn, tokVal, "Unknown token '%s'" % tokVal) - -except StopIteration: - if not expecting_eof: - print( "Unexpected End of File at line ", tokLn ) - -except ParseError as pe: - print( "\n", pe ) - -finally: - # print( "closing file" ) - cmdbuf[0] = XCOMPLETE - output.write( cmdbuf ) - output.close() - +#!/usr/bin/python3.0 + +# Copyright 2008, SoftPLC Corporation http://softplc.com +# Dick Hollenbeck di...@so... + + +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, you may find one here: +# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html +# or you may search the http://www.gnu.org website for the version 2 license, +# or you may write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + + +# A python program to convert an SVF file to an XSVF file. There is an +# option to include comments containing the source file line number from the origin +# SVF file before each outputted XSVF statement. +# +# We deviate from the XSVF spec in that we introduce a new command called +# XWAITSTATE which directly flows from the SVF RUNTEST command. Unfortunately +# XRUNSTATE was ill conceived and is not used here. We also add support for the +# three Lattice extensions to SVF: LCOUNT, LDELAY, and LSDR. The xsvf file +# generated from this program is suitable for use with the xsvf player in +# OpenOCD with my modifications to xsvf.c. +# +# This program is written for python 3.0, and it is not easy to change this +# back to 2.x. You may find it easier to use python 3.x even if that means +# building it. + + +import re +import sys +import struct + + +# There are both ---<Lexer>--- and ---<Parser>--- sections to this program + + +if len( sys.argv ) < 3: + print("usage %s <svf_filename> <xsvf_filename>" % sys.argv[0]) + exit(1) + + +inputFilename = sys.argv[1] +outputFilename = sys.argv[2] + +doCOMMENTs = True # Save XCOMMENTs in the output xsvf file +#doCOMMENTs = False # Save XCOMMENTs in the output xsvf file + +xrepeat = 0 # argument to XREPEAT, gives retry count for masked compares + + +#-----< Lexer >--------------------------------------------------------------- + +StateBin = (RESET,IDLE, + DRSELECT,DRCAPTURE,DRSHIFT,DREXIT1,DRPAUSE,DREXIT2,DRUPDATE, + IRSELECT,IRCAPTURE,IRSHIFT,IREXIT1,IRPAUSE,IREXIT2,IRUPDATE) = range(16) + +# Any integer index into this tuple will be equal to its corresponding StateBin value +StateTxt = ("RESET","IDLE", + "DRSELECT","DRCAPTURE","DRSHIFT","DREXIT1","DRPAUSE","DREXIT2","DRUPDATE", + "IRSELECT","IRCAPTURE","IRSHIFT","IREXIT1","IRPAUSE","IREXIT2","IRUPDATE") + + +(XCOMPLETE,XTDOMASK,XSIR,XSDR,XRUNTEST,hole0,hole1,XREPEAT,XSDRSIZE,XSDRTDO, + XSETSDRMASKS,XSDRINC,XSDRB,XSDRC,XSDRE,XSDRTDOB,XSDRTDOC, + XSDRTDOE,XSTATE,XENDIR,XENDDR,XSIR2,XCOMMENT,XWAIT,XWAITSTATE,LCOUNT,LDELAY,LSDR) = range(28) + +#Note: LCOUNT, LDELAY, and LSDR are Lattice extensions to SVF and provide a way to loop back +# and check a completion status, essentially waiting on a part until it signals that it is done. +# For example below: loop 25 times, each time through the loop do a LDELAY (same as a true RUNTEST) +# and exit loop when LSDR compares match. +""" +LCOUNT 25; +! Step to DRPAUSE give 5 clocks and wait for 1.00e+000 SEC. +LDELAY DRPAUSE 5 TCK 1.00E-003 SEC; +! Test for the completed status. Match means pass. +! Loop back to LDELAY line if not match and loop count less than 25. +LSDR 1 TDI (0) + TDO (1); +""" + +LineNumber = 1 + +def s_ident(scanner, token): return ("ident", token.upper(), LineNumber) + +def s_hex(scanner, token): + global LineNumber + LineNumber = LineNumber + token.count('\n') + token = ''.join(token.split()) + return ("hex", token[1:-1], LineNumber) + +def s_int(scanner, token): return ("int", int(token), LineNumber) +def s_float(scanner, token): return ("float", float(token), LineNumber) +#def s_comment(scanner, token): return ("comment", token, LineNumber) +def s_semicolon(scanner, token): return ("semi", token, LineNumber) + +def s_nl(scanner,token): + global LineNumber + LineNumber = LineNumber + 1 + #print( 'LineNumber=', LineNumber, file=sys.stderr ) + return None + +#2.00E-002 + +scanner = re.Scanner([ + (r"[a-zA-Z]\w*", s_ident), +# (r"[-+]?[0-9]+[.]?[0-9]*([eE][-+]?[0-9]+)?", s_float), + (r"[-+]?[0-9]+(([.][0-9eE+-]*)|([eE]+[-+]?[0-9]+))", s_float), + (r"\d+", s_int), + (r"\(([0-9a-fA-F]|\s)*\)", s_hex), + (r"(!|//).*$", None), + (r";", s_semicolon), + (r"\n",s_nl), + (r"\s*", None), + ], + re.MULTILINE + ) + +# read all svf file input into string "input" +input = open( sys.argv[1] ).read() + +# Lexer: +# create a list of tuples containing (tokenType, tokenValue, LineNumber) +tokens = scanner.scan( input )[0] + +input = None # allow gc to reclaim memory holding file + +#for tokenType, tokenValue, ln in tokens: print( "line %d: %s" % (ln, tokenType), tokenValue ) + + +#-----<parser>----------------------------------------------------------------- + +tokVal = tokType = tokLn = None + +tup = iter( tokens ) + +def nextTok(): + """ + Function to read the next token from tup into tokType, tokVal, tokLn (linenumber) + which are globals. + """ + global tokType, tokVal, tokLn, tup + tokType, tokVal, tokLn = tup.__next__() + + +class ParseError(Exception): + """A class to hold a parsing error message""" + def __init__(self, linenumber, token, message): + self.linenumber = linenumber + self.token = token + self.message = message + def __str__(self): + global inputFilename + return "Error in file \'%s\' at line %d near token %s\n %s" % ( + inputFilename, self.linenumber, repr(self.token), self.message) + + +class MASKSET(object): + """ + Class MASKSET holds a set of bit vectors, all of which are related, will all + have the same length, and are associated with one of the seven shiftOps: + HIR, HDR, TIR, TDR, SIR, SDR, LSDR. One of these holds a mask, smask, tdi, tdo, and a + size. + """ + def __init__(self, name): + self.empty() + self.name = name + + def empty(self): + self.mask = bytearray() + self.smask = bytearray() + self.tdi = bytearray() + self.tdo = bytearray() + self.size = 0 + + def syncLengths( self, sawTDI, sawTDO, sawMASK, sawSMASK, newSize ): + """ + Set all the lengths equal in the event some of the masks were + not seen as part of the last change set. + """ + if self.size == newSize: + return + + if newSize == 0: + self.empty() + return + + # If an SIR was given without a MASK(), then use a mask of all zeros. + # this is not consistent with the SVF spec, but it makes sense because + # it would be odd to be testing an instruction register read out of a + # tap without giving a mask for it. Also, lattice seems to agree and is + # generating SVF files that comply with this philosophy. + if self.name == 'SIR' and not sawMASK: + self.mask = bytearray( newSize ) + + if newSize != len(self.mask): + self.mask = bytearray( newSize ) + if self.name == 'SDR': # leave mask for HIR,HDR,TIR,TDR,SIR zeros + for i in range( newSize ): + self.mask[i] = 1 + + if newSize != len(self.tdo): + self.tdo = bytearray( newSize ) + + if newSize != len(self.tdi): + self.tdi = bytearray( newSize ) + + if newSize != len(self.smask): + self.smask = bytearray( newSize ) + + self.size = newSize +#-----</MASKSET>----- + + +def makeBitArray( hexString, bitCount ): + """ + Converts a packed sequence of hex ascii characters into a bytearray where + each element in the array holds exactly one bit. Only "bitCount" bits are + scanned and these must be the least significant bits in the hex number. That + is, it is legal to have some unused bits in the must significant hex nibble + of the input "hexString". The string is scanned starting from the backend, + then just before returning we reverse the array. This way the append() + method can be used, which I assume is faster than an insert. + """ + global tokLn + a = bytearray() + length = bitCount + hexString = list(hexString) + hexString.reverse() + #print(hexString) + for c in hexString: + if length <= 0: + break; + c = int(c, 16) + for mask in [1,2,4,8]: + if length <= 0: + break; + length = length - 1 + a.append( (c & mask) != 0 ) + if length > 0: + raise ParseError( tokLn, hexString, "Insufficient hex characters for given length of %d" % bitCount ) + a.reverse() + #print(a) + return a + + +def makeXSVFbytes( bitarray ): + """ + Make a bytearray which is contains the XSVF bits which will be written + directly to disk. The number of bytes needed is calculated from the size + of the argument bitarray. + """ + bitCount = len(bitarray) + byteCount = (bitCount+7)//8 + ba = bytearray( byteCount ) + firstBit = (bitCount % 8) - 1 + if firstBit == -1: + firstBit = 7 + bitNdx = 0 + for byteNdx in range(byteCount): + mask = 1<<firstBit + byte = 0 + while mask: + if bitarray[bitNdx]: + byte |= mask; + mask = mask >> 1 + bitNdx = bitNdx + 1 + ba[byteNdx] = byte + firstBit = 7 + return ba + + +def writeComment( outputFile, shiftOp_linenum, shiftOp ): + """ + Write an XCOMMENT record to outputFile + """ + comment = "%s @%d\0" % (shiftOp, shiftOp_linenum) # \0 is terminating nul + ba = bytearray(1) + ba[0] = XCOMMENT + ba += comment.encode() + outputFile.write( ba ) + + +def combineBitVectors( trailer, meat, header ): + """ + Combine the 3 bit vectors comprizing a transmission. Since the least + significant bits are sent first, the header is put onto the list last so + they are sent first from that least significant position. + """ + ret = bytearray() + ret.extend( trailer ) + ret.extend( meat ) + ret.extend( header ) + return ret + + +def writeRUNTEST( outputFile, run_state, end_state, run_count, min_time, tokenTxt ): + """ + Write the output for the SVF RUNTEST command. + run_count - the number of clocks + min_time - the number of seconds + tokenTxt - either RUNTEST or LDELAY + """ + # convert from secs to usecs + min_time = int( min_time * 1000000) + + # the SVF RUNTEST command does NOT map to the XSVF XRUNTEST command. Check the SVF spec, then + # read the XSVF command. They are not the same. Use an XSVF XWAITSTATE to + # implement the required behavior of the SVF RUNTEST command. + if doCOMMENTs: + writeComment( output, tokLn, tokenTxt ) + + if tokenTxt == 'RUNTEST': + obuf = bytearray(11) + obuf[0] = XWAITSTATE + obuf[1] = run_state + obuf[2] = end_state + struct.pack_into(">i", obuf, 3, run_count ) # big endian 4 byte int to obuf + struct.pack_into(">i", obuf, 7, min_time ) # big endian 4 byte int to obuf + outputFile.write( obuf ) + else: # == 'LDELAY' + obuf = bytearray(10) + obuf[0] = LDELAY + obuf[1] = run_state + # LDELAY has no end_state + struct.pack_into(">i", obuf, 2, run_count ) # big endian 4 byte int to obuf + struct.pack_into(">i", obuf, 6, min_time ) # big endian 4 byte int to obuf + outputFile.write( obuf ) + + +output = open( outputFilename, mode='wb' ) + +hir = MASKSET('HIR') +hdr = MASKSET('HDR') +tir = MASKSET('TIR') +tdr = MASKSET('TDR') +sir = MASKSET('SIR') +sdr = MASKSET('SDR') + + +expecting_eof = True + + +# one of the commands that take the shiftParts after the length, the parse +# template for all of these commands is identical +shiftOps = ('SDR', 'SIR', 'LSDR', 'HDR', 'HIR', 'TDR', 'TIR') + +# the order must correspond to shiftOps, this holds the MASKSETS. 'LSDR' shares sdr with 'SDR' +shiftSets = (sdr, sir, sdr, hdr, hir, tdr, tir ) + +# what to expect as parameters to a shiftOp, i.e. after a SDR length or SIR length +shiftParts = ('TDI', 'TDO', 'MASK', 'SMASK') + +# the set of legal states which can trail the RUNTEST command +run_state_allowed = ('IRPAUSE', 'DRPAUSE', 'RESET', 'IDLE') + +enddr_state_allowed = ('DRPAUSE', 'IDLE') +endir_state_allowed = ('IRPAUSE', 'IDLE') + +enddr_state = IDLE +endir_state = IDLE + +frequency = 1.00e+006 # HZ; + +# change detection for xsdrsize and xtdomask +xsdrsize = -1 # the last one sent, send only on change +xtdomask = bytearray() # the last one sent, send only on change + + +# we use a number of single byte writes for the XSVF command below +cmdbuf = bytearray(1) + + +# Save the XREPEAT setting into the file as first thing. +obuf = bytearray(2) +obuf[0] = XREPEAT +obuf[1] = xrepeat +output.write( obuf ) + + +try: + while 1: + expecting_eof = True + nextTok() + expecting_eof = False + # print( tokType, tokVal, tokLn ) + + if tokVal in shiftOps: + shiftOp_linenum = tokLn + shiftOp = tokVal + + set = shiftSets[shiftOps.index(shiftOp)] + + # set flags false, if we see one later, set that one true later + sawTDI = sawTDO = sawMASK = sawSMASK = False + + nextTok() + if tokType != 'int': + raise ParseError( tokLn, tokVal, "Expecting 'int' giving %s length, got '%s'" % (shiftOp, tokType) ) + length = tokVal + + nextTok() + + while tokVal != ';': + if tokVal not in shiftParts: + raise ParseError( tokLn, tokVal, "Expecting TDI, TDO, MASK, SMASK, or ';'") + shiftPart = tokVal + + nextTok() + + if tokType != 'hex': + raise ParseError( tokLn, tokVal, "Expecting hex bits" ) + bits = makeBitArray( tokVal, length ) + + if shiftPart == 'TDI': + sawTDI = True + set.tdi = bits + + elif shiftPart == 'TDO': + sawTDO = True + set.tdo = bits + + elif shiftPart == 'MASK': + sawMASK = True + set.mask = bits + + elif shiftPart == 'SMASK': + sawSMASK = True + set.smask = bits + + nextTok() + + set.syncLengths( sawTDI, sawTDO, sawMASK, sawSMASK, length ) + + # process all the gathered parameters and generate outputs here + if shiftOp == 'SIR': + if doCOMMENTs: + writeComment( output, shiftOp_linenum, 'SIR' ) + + tdi = combineBitVectors( tir.tdi, sir.tdi, hir.tdi ) + if len(tdi) > 255: + obuf = bytearray(3) + obuf[0] = XSIR2 + struct.pack_into( ">h", obuf, 1, len(tdi) ) + else: + obuf = bytearray(2) + obuf[0] = XSIR + obuf[1] = len(tdi) + output.write( obuf ) + obuf = makeXSVFbytes( tdi ) + output.write( obuf ) + + elif shiftOp == 'SDR': + if doCOMMENTs: + writeComment( output, shiftOp_linenum, shiftOp ) + + if not sawTDO: + # pass a zero filled bit vector for the sdr.mask + mask = combineBitVectors( tdr.mask, bytearray(sdr.size), hdr.mask ) + tdi = combineBitVectors( tdr.tdi, sdr.tdi, hdr.tdi ) + + if xsdrsize != len(tdi): + xsdrsize = len(tdi) + cmdbuf[0] = XSDRSIZE + output.write( cmdbuf ) + obuf = bytearray(4) + struct.pack_into( ">i", obuf, 0, xsdrsize ) # big endian 4 byte int to obuf + output.write( obuf ) + + if xtdomask != mask: + xtdomask = mask + cmdbuf[0] = XTDOMASK + output.write( cmdbuf ) + obuf = makeXSVFbytes( mask ) + output.write( obuf ) + + cmdbuf[0] = XSDR + output.write( cmdbuf ) + obuf = makeXSVFbytes( tdi ) + output.write( obuf ) + + else: + mask = combineBitVectors( tdr.mask, sdr.mask, hdr.mask ) + tdi = combineBitVectors( tdr.tdi, sdr.tdi, hdr.tdi ) + tdo = combineBitVectors( tdr.tdo, sdr.tdo, hdr.tdo ) + + if xsdrsize != len(tdi): + xsdrsize = len(tdi) + cmdbuf[0] = XSDRSIZE + output.write( cmdbuf ) + obuf = bytearray(4) + struct.pack_into(">i", obuf, 0, xsdrsize ) # big endian 4 byte int to obuf + output.write( obuf ) + + if xtdomask != mask: + xtdomask = mask + cmdbuf[0] = XTDOMASK + output.write( cmdbuf ) + obuf = makeXSVFbytes( mask ) + output.write( obuf ) + + cmdbuf[0] = XSDRTDO + output.write( cmdbuf ) + obuf = makeXSVFbytes( tdi ) + output.write( obuf ) + obuf = makeXSVFbytes( tdo ) + output.write( obuf ) + #print( "len(tdo)=", len(tdo), "len(tdr.tdo)=", len(tdr.tdo), "len(sdr.tdo)=", len(sdr.tdo), "len(hdr.tdo)=", len(hdr.tdo) ) + + elif shiftOp == 'LSDR': + if doCOMMENTs: + writeComment( output, shiftOp_linenum, shiftOp ) + + mask = combineBitVectors( tdr.mask, sdr.mask, hdr.mask ) + tdi = combineBitVectors( tdr.tdi, sdr.tdi, hdr.tdi ) + tdo = combineBitVectors( tdr.tdo, sdr.tdo, hdr.tdo ) + + if xsdrsize != len(tdi): + xsdrsize = len(tdi) + cmdbuf[0] = XSDRSIZE + output.write( cmdbuf ) + obuf = bytearray(4) + struct.pack_into(">i", obuf, 0, xsdrsize ) # big endian 4 byte int to obuf + output.write( obuf ) + + if xtdomask != mask: + xtdomask = mask + cmdbuf[0] = XTDOMASK + output.write( cmdbuf ) + obuf = makeXSVFbytes( mask ) + output.write( obuf ) + + cmdbuf[0] = LSDR + output.write( cmdbuf ) + obuf = makeXSVFbytes( tdi ) + output.write( obuf ) + obuf = makeXSVFbytes( tdo ) + output.write( obuf ) + #print( "len(tdo)=", len(tdo), "len(tdr.tdo)=", len(tdr.tdo), "len(sdr.tdo)=", len(sdr.tdo), "len(hdr.tdo)=", len(hdr.tdo) ) + + elif tokVal == 'RUNTEST' or tokVal == 'LDELAY': + # e.g. from lattice tools: + # "RUNTEST IDLE 5 TCK 1.00E-003 SEC;" + saveTok = tokVal + nextTok() + min_time = 0 + run_count = 0 + max_time = 600 # ten minutes + if tokVal in run_state_allowed: + run_state = StateTxt.index(tokVal) + end_state = run_state # bottom of page 17 of SVF spec + nextTok() + if tokType != 'int' and tokType != 'float': + raise ParseError( tokLn, tokVal, "Expecting 'int' or 'float' after RUNTEST [run_state]") + timeval = tokVal; + nextTok() + if tokVal != 'TCK' and tokVal != 'SEC' and tokVal != 'SCK': + raise ParseError( tokLn, tokVal, "Expecting 'TCK' or 'SEC' or 'SCK' after RUNTEST [run_state] (run_count|min_time)") + if tokVal == 'TCK' or tokVal == 'SCK': + run_count = int( timeval ) + else: + min_time = timeval + nextTok() + if tokType == 'int' or tokType == 'float': + min_time = tokVal + nextTok() + if tokVal != 'SEC': + raise ParseError( tokLn, tokVal, "Expecting 'SEC' after RUNTEST [run_state] run_count min_time") + nextTok() + if tokVal == 'MAXIMUM': + nextTok() + if tokType != 'int' and tokType != 'float': + raise ParseError( tokLn, tokVal, "Expecting 'max_time' after RUNTEST [run_state] min_time SEC MAXIMUM") + max_time = tokVal + nextTok() + if tokVal != 'SEC': + raise ParseError( tokLn, tokVal, "Expecting 'max_time' after RUNTEST [run_state] min_time SEC MAXIMUM max_time") + nextTok() + if tokVal == 'ENDSTATE': + nextTok() + if tokVal not in run_state_allowed: + raise ParseError( tokLn, tokVal, "Expecting 'run_state' after RUNTEST .... ENDSTATE") + end_state = StateTxt.index(tokVal) + nextTok() + if tokVal != ';': + raise ParseError( tokLn, tokVal, "Expecting ';' after RUNTEST ....") + # print( "run_count=", run_count, "min_time=", min_time, + # "max_time=", max_time, "run_state=", State[run_state], "end_state=", State[end_state] ) + writeRUNTEST( output, run_state, end_state, run_count, min_time, saveTok ) + + elif tokVal == 'LCOUNT': + nextTok() + if tokType != 'int': + raise ParseError( tokLn, tokVal, "Expecting integer 'count' after LCOUNT") + loopCount = tokVal + nextTok() + if tokVal != ';': + raise ParseError( tokLn, tokVal, "Expecting ';' after LCOUNT count") + if doCOMMENTs: + writeComment( output, tokLn, 'LCOUNT' ) + obuf = bytearray(5) + obuf[0] = LCOUNT + struct.pack_into(">i", obuf, 1, loopCount ) # big endian 4 byte int to obuf + output.write( obuf ) + + elif tokVal == 'ENDDR': + nextTok() + if tokVal not in enddr_state_allowed: + raise ParseError( tokLn, tokVal, "Expecting 'stable_state' after ENDDR. (one of: DRPAUSE, IDLE)") + enddr_state = StateTxt.index(tokVal) + nextTok() + if tokVal != ';': + raise ParseError( tokLn, tokVal, "Expecting ';' after ENDDR stable_state") + if doCOMMENTs: + writeComment( output, tokLn, 'ENDDR' ) + obuf = bytearray(2) + obuf[0] = XENDDR + # Page 10 of the March 1999 SVF spec shows that RESET is also allowed here. + # Yet the XSVF spec has no provision for that, and uses a non-standard, i.e. + # boolean argument to XENDDR which only handles two of the 3 intended states. + obuf[1] = 1 if enddr_state == DRPAUSE else 0 + output.write( obuf ) + + elif tokVal == 'ENDIR': + nextTok() + if tokVal not in endir_state_allowed: + raise ParseError( tokLn, tokVal, "Expecting 'stable_state' after ENDIR. (one of: IRPAUSE, IDLE)") + endir_state = StateTxt.index(tokVal) + nextTok() + if tokVal != ';': + raise ParseError( tokLn, tokVal, "Expecting ';' after ENDIR stable_state") + if doCOMMENTs: + writeComment( output, tokLn, 'ENDIR' ) + obuf = bytearray(2) + obuf[0] = XENDIR + # Page 10 of the March 1999 SVF spec shows that RESET is also allowed here. + # Yet the XSVF spec has no provision for that, and uses a non-standard, i.e. + # boolean argument to XENDDR which only handles two of the 3 intended states. + obuf[1] = 1 if endir_state == IRPAUSE else 0 + output.write( obuf ) + + elif tokVal == 'STATE': + nextTok() + ln = tokLn + while tokVal != ';': + if tokVal not in StateTxt: + raise ParseError( tokLn, tokVal, "Expecting 'stable_state' after STATE") + stable_state = StateTxt.index( tokVal ) + + if doCOMMENTs and ln != -1: + writeComment( output, ln, 'STATE' ) + ln = -1 # save comment only once + + obuf = bytearray(2) + obuf[0] = XSTATE + obuf[1] = stable_state + output.write( obuf ) + nextTok() + + elif tokVal == 'FREQUENCY': + nextTok() + if tokVal != ';': + if tokType != 'int' and tokType != 'float': + raise ParseError( tokLn, tokVal, "Expecting 'cycles HZ' after FREQUENCY") + frequency = tokVal + nextTok() + if tokVal != 'HZ': + raise ParseError( tokLn, tokVal, "Expecting 'HZ' after FREQUENCY cycles") + nextTok() + if tokVal != ';': + raise ParseError( tokLn, tokVal, "Expecting ';' after FREQUENCY cycles HZ") + + else: + raise ParseError( tokLn, tokVal, "Unknown token '%s'" % tokVal) + +except StopIteration: + if not expecting_eof: + print( "Unexpected End of File at line ", tokLn ) + +except ParseError as pe: + print( "\n", pe ) + +finally: + # print( "closing file" ) + cmdbuf[0] = XCOMPLETE + output.write( cmdbuf ) + output.close() + Property changes on: trunk/tools/xsvf_tools/svf2xsvf.py ___________________________________________________________________ Name: svn:eol-style + native Modified: trunk/tools/xsvf_tools/xsvfdump.py =================================================================== --- trunk/tools/xsvf_tools/xsvfdump.py 2009-01-07 07:08:02 UTC (rev 1303) +++ trunk/tools/xsvf_tools/xsvfdump.py 2009-01-07 14:55:52 UTC (rev 1304) @@ -1,255 +1,255 @@ -#!/usr/bin/python3.0 - -# Copyright 2008, SoftPLC Corporation http://softplc.com -# Dick Hollenbeck di...@so... - -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, you may find one here: -# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html -# or you may search the http://www.gnu.org website for the version 2 license, -# or you may write to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - -# Dump an Xilinx XSVF file to stdout - -# This program is written for python 3.0, and it is not easy to change this -# back to 2.x. You may find it easier to use python 3.x even if that means -# building it. - - -import sys -import struct - - -LABEL = "A script to dump an XSVF file to stdout" - - -Xsdrsize = 0 - - -(XCOMPLETE,XTDOMASK,XSIR,XSDR,XRUNTEST,hole0,hole1,XREPEAT,XSDRSIZE,XSDRTDO, - XSETSDRMASKS,XSDRINC,XSDRB,XSDRC,XSDRE,XSDRTDOB,XSDRTDOC, - XSDRTDOE,XSTATE,XENDIR,XENDDR,XSIR2,XCOMMENT,XWAIT,XWAITSTATE,LCOUNT,LDELAY,LSDR) = range(28) - - -(RESET,IDLE, - DRSELECT,DRCAPTURE,DRSHIFT,DREXIT1,DRPAUSE,DREXIT2,DRUPDATE, - IRSELECT,IRCAPTURE,IRSHIFT,IREXIT1,IRPAUSE,IREXIT2,IRUPDATE) = range(16) - - -State = ("RESET","IDLE", - "DRSELECT","DRCAPTURE","DRSHIFT","DREXIT1","DRPAUSE","DREXIT2","DRUPDATE", - "IRSELECT","IRCAPTURE","IRSHIFT","IREXIT1","IRPAUSE","IREXIT2","IRUPDATE") - -Setsdrmasks = 0 -SetsdrmasksOnesCount = 0 - -def ReadSDRMASKS( f, len ): - global Setsdrmasks, SetsdrmasksOnesCount - byteCount = (len+7)//8 - Setsdrmasks = f.read( byteCount ) - ls = [] - SetsdrmasksOnesCount = 0 - for b in Setsdrmasks: - ls.append( "%x" % ((b & 0xf0) >> 4) ) - ls.append( "%x" % ( b & 0x0f ) ) - for i in range(8): - if b & (1<<i): - SetsdrmasksOnesCount = SetsdrmasksOnesCount +1 - return ''.join(ls) - - -def bytes2hexString( f, len ): - byteCount = (len+7)//8 - bytebuf = f.read( byteCount ) - ls = [] - for b in bytebuf: - ls.append( "%x" % ((b & 0xf0) >> 4) ) - ls.append( "%x" % ( b & 0x0f ) ) - return ''.join(ls) - - -def ReadByte( f ): - """Read a byte from a file and return it as an int in least significant 8 bits""" - b = f.read(1) - if b: - return 0xff & b[0]; - else: - return -1 - - -def ShowState( state ): - """return the given state int as a state string""" - #return "0x%02x" % state # comment this out to get textual state form - global State - if 0 <= state <= IRUPDATE: - return State[state] - else: - return "Unknown state 0x%02x" % state - - -def ShowOpcode( op, f ): - """return the given byte as an opcode string""" - global Xsdrsize - if op == XCOMPLETE: - print("XCOMPLETE") - - elif op == XTDOMASK: - buf = bytes2hexString( f, Xsdrsize ) - print("XTDOMASK 0x%s" % buf) - - elif op == XSIR: - len = ReadByte( f ) - buf = bytes2hexString( f, len ) - print("XSIR 0x%02X 0x%s" % (len, buf)) - - elif op == XSDR: - tdi = bytes2hexString( f, Xsdrsize ) - print("XSDR 0x%s" % tdi) - - elif op == XRUNTEST: - len = struct.unpack( '>i', f.read(4) )[0] - print("XRUNTEST 0x%08X" % len) - - elif op == XREPEAT: - len = ReadByte( f ) - print("XREPEAT 0x%02X" % len) - - elif op == XSDRSIZE: - Xsdrsize = struct.unpack( '>i', f.read(4) )[0] - #print("XSDRSIZE 0x%08X" % Xsdrsize, file=sys.stderr ) - print("XSDRSIZE 0x%08X %d" % (Xsdrsize, Xsdrsize) ) - - elif op == XSDRTDO: - tdi = bytes2hexString( f, Xsdrsize ) - tdo = bytes2hexString( f, Xsdrsize ) - print("XSDRTDO 0x%s 0x%s" % (tdi, tdo) ) - - elif op == XSETSDRMASKS: - addrmask = bytes2hexString( f, Xsdrsize ) - datamask = ReadSDRMASKS( f, Xsdrsize ) - print("XSETSDRMASKS 0x%s 0x%s" % (addrmask, datamask) ) - - elif op == XSDRINC: - startaddr = bytes2hexString( f, Xsdrsize ) - len = ReadByte(f) - print("XSDRINC 0x%s 0x%02X" % (startaddr, len), end='' ) - for numTimes in range(len): - data = bytes2hexString( f, SetsdrmasksOnesCount) - print(" 0x%s" % data ) - print() # newline - - elif op == XSDRB: - tdi = bytes2hexString( f, Xsdrsize ) - print("XSDRB 0x%s" % tdi ) - - elif op == XSDRC: - tdi = bytes2hexString( f, Xsdrsize ) - print("XSDRC 0x%s" % tdi ) - - elif op == XSDRE: - tdi = bytes2hexString( f, Xsdrsize ) - print("XSDRE 0x%s" % tdi ) - - elif op == XSDRTDOB: - tdo = bytes2hexString( f, Xsdrsize ) - print("XSDRTDOB 0x%s" % tdo ) - - elif op == XSDRTDOC: - tdi = bytes2hexString( f, Xsdrsize ) - tdo = bytes2hexString( f, Xsdrsize ) - print("XSDRTDOC 0x%s 0x%s" % (tdi, tdo) ) - - elif op == XSDRTDOE: - tdi = bytes2hexString( f, Xsdrsize ) - tdo = bytes2hexString( f, Xsdrsize ) - print("XSDRTDOE 0x%s 0x%s" % (tdi, tdo) ) - - elif op == XSTATE: - b = ReadByte(f) - print("XSTATE %s" % ShowState(b)) - - elif op == XENDIR: - b = ReadByte( f ) - print("XENDIR %s" % ShowState(b)) - - elif op == XENDDR: - b = ReadByte( f ) - print("XENDDR %s" % ShowState(b)) - - elif op == XSIR2: - len = struct.unpack( '>H', f.read(2) )[0] - buf = bytes2hexString( f, len ) - print("XSIR2 0x%04X 0x%s" % (len, buf)) - - elif op == XCOMMENT: - cmt = [] - while 1: - b = ReadByte(f) - if b == 0: # terminating nul - break; - cmt.append( chr(b) ) - print("XCOMMENT \"%s\"" % ''.join(cmt) ) - - elif op == XWAIT: - run_state = ReadByte(f) - end_state = ReadByte(f) - useconds = struct.unpack( '>i', f.read(4) )[0] - print("XWAIT %s %s" % (ShowState(run_state), ShowState(end_state)), useconds) - - elif op == XWAITSTATE: - run_state = ReadByte(f) - end_state = ReadByte(f) - clocks = struct.unpack( '>i', f.read(4) )[0] - useconds = struct.unpack( '>i', f.read(4) )[0] - print("XWAITSTATE %s %s CLOCKS=%d USECS=%d" % (ShowState(run_state), ShowState(end_state), clocks, useconds) ) - - elif op == LCOUNT: - loop_count = struct.unpack( '>i', f.read(4) )[0] - print("LCOUNT", loop_count ) - - elif op == LDELAY: - run_state = ReadByte(f) - clocks = struct.unpack( '>i', f.read(4) )[0] - useconds = struct.unpack( '>i', f.read(4) )[0] - print("LDELAY %s CLOCKS=%d USECS=%d" % (ShowState(run_state), clocks, useconds) ) - - elif op == LSDR: - tdi = bytes2hexString( f, Xsdrsize ) - tdo = bytes2hexString( f, Xsdrsize ) - print("LSDR 0x%s 0x%s" % (tdi, tdo) ) - - else: - print("UNKNOWN op 0x%02X %d" % (op, op)) - ... [truncated message content] |
From: <oh...@ma...> - 2009-01-07 08:08:04
|
Author: oharboe Date: 2009-01-07 08:08:02 +0100 (Wed, 07 Jan 2009) New Revision: 1303 Added: trunk/tools/xsvf_tools/ trunk/tools/xsvf_tools/svf2xsvf.py trunk/tools/xsvf_tools/xsvfdump.py Log: Dick Hollenbeck <di...@so...> SVF to XSVF converter and the XSVF dumper Added: trunk/tools/xsvf_tools/svf2xsvf.py =================================================================== --- trunk/tools/xsvf_tools/svf2xsvf.py 2009-01-05 13:45:16 UTC (rev 1302) +++ trunk/tools/xsvf_tools/svf2xsvf.py 2009-01-07 07:08:02 UTC (rev 1303) @@ -0,0 +1,693 @@ +#!/usr/bin/python3.0 + +# Copyright 2008, SoftPLC Corporation http://softplc.com +# Dick Hollenbeck di...@so... + + +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, you may find one here: +# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html +# or you may search the http://www.gnu.org website for the version 2 license, +# or you may write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + + +# A python program to convert an SVF file to an XSVF file. There is an +# option to include comments containing the source file line number from the origin +# SVF file before each outputted XSVF statement. +# +# We deviate from the XSVF spec in that we introduce a new command called +# XWAITSTATE which directly flows from the SVF RUNTEST command. Unfortunately +# XRUNSTATE was ill conceived and is not used here. We also add support for the +# three Lattice extensions to SVF: LCOUNT, LDELAY, and LSDR. The xsvf file +# generated from this program is suitable for use with the xsvf player in +# OpenOCD with my modifications to xsvf.c. +# +# This program is written for python 3.0, and it is not easy to change this +# back to 2.x. You may find it easier to use python 3.x even if that means +# building it. + + +import re +import sys +import struct + + +# There are both ---<Lexer>--- and ---<Parser>--- sections to this program + + +if len( sys.argv ) < 3: + print("usage %s <svf_filename> <xsvf_filename>" % sys.argv[0]) + exit(1) + + +inputFilename = sys.argv[1] +outputFilename = sys.argv[2] + +doCOMMENTs = True # Save XCOMMENTs in the output xsvf file +#doCOMMENTs = False # Save XCOMMENTs in the output xsvf file + +xrepeat = 0 # argument to XREPEAT, gives retry count for masked compares + + +#-----< Lexer >--------------------------------------------------------------- + +StateBin = (RESET,IDLE, + DRSELECT,DRCAPTURE,DRSHIFT,DREXIT1,DRPAUSE,DREXIT2,DRUPDATE, + IRSELECT,IRCAPTURE,IRSHIFT,IREXIT1,IRPAUSE,IREXIT2,IRUPDATE) = range(16) + +# Any integer index into this tuple will be equal to its corresponding StateBin value +StateTxt = ("RESET","IDLE", + "DRSELECT","DRCAPTURE","DRSHIFT","DREXIT1","DRPAUSE","DREXIT2","DRUPDATE", + "IRSELECT","IRCAPTURE","IRSHIFT","IREXIT1","IRPAUSE","IREXIT2","IRUPDATE") + + +(XCOMPLETE,XTDOMASK,XSIR,XSDR,XRUNTEST,hole0,hole1,XREPEAT,XSDRSIZE,XSDRTDO, + XSETSDRMASKS,XSDRINC,XSDRB,XSDRC,XSDRE,XSDRTDOB,XSDRTDOC, + XSDRTDOE,XSTATE,XENDIR,XENDDR,XSIR2,XCOMMENT,XWAIT,XWAITSTATE,LCOUNT,LDELAY,LSDR) = range(28) + +#Note: LCOUNT, LDELAY, and LSDR are Lattice extensions to SVF and provide a way to loop back +# and check a completion status, essentially waiting on a part until it signals that it is done. +# For example below: loop 25 times, each time through the loop do a LDELAY (same as a true RUNTEST) +# and exit loop when LSDR compares match. +""" +LCOUNT 25; +! Step to DRPAUSE give 5 clocks and wait for 1.00e+000 SEC. +LDELAY DRPAUSE 5 TCK 1.00E-003 SEC; +! Test for the completed status. Match means pass. +! Loop back to LDELAY line if not match and loop count less than 25. +LSDR 1 TDI (0) + TDO (1); +""" + +LineNumber = 1 + +def s_ident(scanner, token): return ("ident", token.upper(), LineNumber) + +def s_hex(scanner, token): + global LineNumber + LineNumber = LineNumber + token.count('\n') + token = ''.join(token.split()) + return ("hex", token[1:-1], LineNumber) + +def s_int(scanner, token): return ("int", int(token), LineNumber) +def s_float(scanner, token): return ("float", float(token), LineNumber) +#def s_comment(scanner, token): return ("comment", token, LineNumber) +def s_semicolon(scanner, token): return ("semi", token, LineNumber) + +def s_nl(scanner,token): + global LineNumber + LineNumber = LineNumber + 1 + #print( 'LineNumber=', LineNumber, file=sys.stderr ) + return None + +#2.00E-002 + +scanner = re.Scanner([ + (r"[a-zA-Z]\w*", s_ident), +# (r"[-+]?[0-9]+[.]?[0-9]*([eE][-+]?[0-9]+)?", s_float), + (r"[-+]?[0-9]+(([.][0-9eE+-]*)|([eE]+[-+]?[0-9]+))", s_float), + (r"\d+", s_int), + (r"\(([0-9a-fA-F]|\s)*\)", s_hex), + (r"(!|//).*$", None), + (r";", s_semicolon), + (r"\n",s_nl), + (r"\s*", None), + ], + re.MULTILINE + ) + +# read all svf file input into string "input" +input = open( sys.argv[1] ).read() + +# Lexer: +# create a list of tuples containing (tokenType, tokenValue, LineNumber) +tokens = scanner.scan( input )[0] + +input = None # allow gc to reclaim memory holding file + +#for tokenType, tokenValue, ln in tokens: print( "line %d: %s" % (ln, tokenType), tokenValue ) + + +#-----<parser>----------------------------------------------------------------- + +tokVal = tokType = tokLn = None + +tup = iter( tokens ) + +def nextTok(): + """ + Function to read the next token from tup into tokType, tokVal, tokLn (linenumber) + which are globals. + """ + global tokType, tokVal, tokLn, tup + tokType, tokVal, tokLn = tup.__next__() + + +class ParseError(Exception): + """A class to hold a parsing error message""" + def __init__(self, linenumber, token, message): + self.linenumber = linenumber + self.token = token + self.message = message + def __str__(self): + global inputFilename + return "Error in file \'%s\' at line %d near token %s\n %s" % ( + inputFilename, self.linenumber, repr(self.token), self.message) + + +class MASKSET(object): + """ + Class MASKSET holds a set of bit vectors, all of which are related, will all + have the same length, and are associated with one of the seven shiftOps: + HIR, HDR, TIR, TDR, SIR, SDR, LSDR. One of these holds a mask, smask, tdi, tdo, and a + size. + """ + def __init__(self, name): + self.empty() + self.name = name + + def empty(self): + self.mask = bytearray() + self.smask = bytearray() + self.tdi = bytearray() + self.tdo = bytearray() + self.size = 0 + + def syncLengths( self, sawTDI, sawTDO, sawMASK, sawSMASK, newSize ): + """ + Set all the lengths equal in the event some of the masks were + not seen as part of the last change set. + """ + if self.size == newSize: + return + + if newSize == 0: + self.empty() + return + + # If an SIR was given without a MASK(), then use a mask of all zeros. + # this is not consistent with the SVF spec, but it makes sense because + # it would be odd to be testing an instruction register read out of a + # tap without giving a mask for it. Also, lattice seems to agree and is + # generating SVF files that comply with this philosophy. + if self.name == 'SIR' and not sawMASK: + self.mask = bytearray( newSize ) + + if newSize != len(self.mask): + self.mask = bytearray( newSize ) + if self.name == 'SDR': # leave mask for HIR,HDR,TIR,TDR,SIR zeros + for i in range( newSize ): + self.mask[i] = 1 + + if newSize != len(self.tdo): + self.tdo = bytearray( newSize ) + + if newSize != len(self.tdi): + self.tdi = bytearray( newSize ) + + if newSize != len(self.smask): + self.smask = bytearray( newSize ) + + self.size = newSize +#-----</MASKSET>----- + + +def makeBitArray( hexString, bitCount ): + """ + Converts a packed sequence of hex ascii characters into a bytearray where + each element in the array holds exactly one bit. Only "bitCount" bits are + scanned and these must be the least significant bits in the hex number. That + is, it is legal to have some unused bits in the must significant hex nibble + of the input "hexString". The string is scanned starting from the backend, + then just before returning we reverse the array. This way the append() + method can be used, which I assume is faster than an insert. + """ + global tokLn + a = bytearray() + length = bitCount + hexString = list(hexString) + hexString.reverse() + #print(hexString) + for c in hexString: + if length <= 0: + break; + c = int(c, 16) + for mask in [1,2,4,8]: + if length <= 0: + break; + length = length - 1 + a.append( (c & mask) != 0 ) + if length > 0: + raise ParseError( tokLn, hexString, "Insufficient hex characters for given length of %d" % bitCount ) + a.reverse() + #print(a) + return a + + +def makeXSVFbytes( bitarray ): + """ + Make a bytearray which is contains the XSVF bits which will be written + directly to disk. The number of bytes needed is calculated from the size + of the argument bitarray. + """ + bitCount = len(bitarray) + byteCount = (bitCount+7)//8 + ba = bytearray( byteCount ) + firstBit = (bitCount % 8) - 1 + if firstBit == -1: + firstBit = 7 + bitNdx = 0 + for byteNdx in range(byteCount): + mask = 1<<firstBit + byte = 0 + while mask: + if bitarray[bitNdx]: + byte |= mask; + mask = mask >> 1 + bitNdx = bitNdx + 1 + ba[byteNdx] = byte + firstBit = 7 + return ba + + +def writeComment( outputFile, shiftOp_linenum, shiftOp ): + """ + Write an XCOMMENT record to outputFile + """ + comment = "%s @%d\0" % (shiftOp, shiftOp_linenum) # \0 is terminating nul + ba = bytearray(1) + ba[0] = XCOMMENT + ba += comment.encode() + outputFile.write( ba ) + + +def combineBitVectors( trailer, meat, header ): + """ + Combine the 3 bit vectors comprizing a transmission. Since the least + significant bits are sent first, the header is put onto the list last so + they are sent first from that least significant position. + """ + ret = bytearray() + ret.extend( trailer ) + ret.extend( meat ) + ret.extend( header ) + return ret + + +def writeRUNTEST( outputFile, run_state, end_state, run_count, min_time, tokenTxt ): + """ + Write the output for the SVF RUNTEST command. + run_count - the number of clocks + min_time - the number of seconds + tokenTxt - either RUNTEST or LDELAY + """ + # convert from secs to usecs + min_time = int( min_time * 1000000) + + # the SVF RUNTEST command does NOT map to the XSVF XRUNTEST command. Check the SVF spec, then + # read the XSVF command. They are not the same. Use an XSVF XWAITSTATE to + # implement the required behavior of the SVF RUNTEST command. + if doCOMMENTs: + writeComment( output, tokLn, tokenTxt ) + + if tokenTxt == 'RUNTEST': + obuf = bytearray(11) + obuf[0] = XWAITSTATE + obuf[1] = run_state + obuf[2] = end_state + struct.pack_into(">i", obuf, 3, run_count ) # big endian 4 byte int to obuf + struct.pack_into(">i", obuf, 7, min_time ) # big endian 4 byte int to obuf + outputFile.write( obuf ) + else: # == 'LDELAY' + obuf = bytearray(10) + obuf[0] = LDELAY + obuf[1] = run_state + # LDELAY has no end_state + struct.pack_into(">i", obuf, 2, run_count ) # big endian 4 byte int to obuf + struct.pack_into(">i", obuf, 6, min_time ) # big endian 4 byte int to obuf + outputFile.write( obuf ) + + +output = open( outputFilename, mode='wb' ) + +hir = MASKSET('HIR') +hdr = MASKSET('HDR') +tir = MASKSET('TIR') +tdr = MASKSET('TDR') +sir = MASKSET('SIR') +sdr = MASKSET('SDR') + + +expecting_eof = True + + +# one of the commands that take the shiftParts after the length, the parse +# template for all of these commands is identical +shiftOps = ('SDR', 'SIR', 'LSDR', 'HDR', 'HIR', 'TDR', 'TIR') + +# the order must correspond to shiftOps, this holds the MASKSETS. 'LSDR' shares sdr with 'SDR' +shiftSets = (sdr, sir, sdr, hdr, hir, tdr, tir ) + +# what to expect as parameters to a shiftOp, i.e. after a SDR length or SIR length +shiftParts = ('TDI', 'TDO', 'MASK', 'SMASK') + +# the set of legal states which can trail the RUNTEST command +run_state_allowed = ('IRPAUSE', 'DRPAUSE', 'RESET', 'IDLE') + +enddr_state_allowed = ('DRPAUSE', 'IDLE', 'RESET') +endir_state_allowed = ('IRPAUSE', 'IDLE', 'RESET') + +enddr_state = IDLE +endir_state = IDLE + +frequency = 1.00e+006 # HZ; + +# change detection for xsdrsize and xtdomask +xsdrsize = -1 # the last one sent, send only on change +xtdomask = bytearray() # the last one sent, send only on change + + +# we use a number of single byte writes for the XSVF command below +cmdbuf = bytearray(1) + + +# Save the XREPEAT setting into the file as first thing. +obuf = bytearray(2) +obuf[0] = XREPEAT +obuf[1] = xrepeat +output.write( obuf ) + + +try: + while 1: + expecting_eof = True + nextTok() + expecting_eof = False + # print( tokType, tokVal, tokLn ) + + if tokVal in shiftOps: + shiftOp_linenum = tokLn + shiftOp = tokVal + + set = shiftSets[shiftOps.index(shiftOp)] + + # set flags false, if we see one later, set that one true later + sawTDI = sawTDO = sawMASK = sawSMASK = False + + nextTok() + if tokType != 'int': + raise ParseError( tokLn, tokVal, "Expecting 'int' giving %s length, got '%s'" % (shiftOp, tokType) ) + length = tokVal + + nextTok() + + while tokVal != ';': + if tokVal not in shiftParts: + raise ParseError( tokLn, tokVal, "Expecting TDI, TDO, MASK, SMASK, or ';'") + shiftPart = tokVal + + nextTok() + + if tokType != 'hex': + raise ParseError( tokLn, tokVal, "Expecting hex bits" ) + bits = makeBitArray( tokVal, length ) + + if shiftPart == 'TDI': + sawTDI = True + set.tdi = bits + + elif shiftPart == 'TDO': + sawTDO = True + set.tdo = bits + + elif shiftPart == 'MASK': + sawMASK = True + set.mask = bits + + elif shiftPart == 'SMASK': + sawSMASK = True + set.smask = bits + + nextTok() + + set.syncLengths( sawTDI, sawTDO, sawMASK, sawSMASK, length ) + + # process all the gathered parameters and generate outputs here + if shiftOp == 'SIR': + if doCOMMENTs: + writeComment( output, shiftOp_linenum, 'SIR' ) + + tdi = combineBitVectors( tir.tdi, sir.tdi, hir.tdi ) + if len(tdi) > 255: + obuf = bytearray(3) + obuf[0] = XSIR2 + struct.pack_into( ">h", obuf, 1, len(tdi) ) + else: + obuf = bytearray(2) + obuf[0] = XSIR + obuf[1] = len(tdi) + output.write( obuf ) + obuf = makeXSVFbytes( tdi ) + output.write( obuf ) + + elif shiftOp == 'SDR': + if doCOMMENTs: + writeComment( output, shiftOp_linenum, shiftOp ) + + if not sawTDO: + # pass a zero filled bit vector for the sdr.mask + mask = combineBitVectors( tdr.mask, bytearray(sdr.size), hdr.mask ) + tdi = combineBitVectors( tdr.tdi, sdr.tdi, hdr.tdi ) + + if xsdrsize != len(tdi): + xsdrsize = len(tdi) + cmdbuf[0] = XSDRSIZE + output.write( cmdbuf ) + obuf = bytearray(4) + struct.pack_into( ">i", obuf, 0, xsdrsize ) # big endian 4 byte int to obuf + output.write( obuf ) + + if xtdomask != mask: + xtdomask = mask + cmdbuf[0] = XTDOMASK + output.write( cmdbuf ) + obuf = makeXSVFbytes( mask ) + output.write( obuf ) + + cmdbuf[0] = XSDR + output.write( cmdbuf ) + obuf = makeXSVFbytes( tdi ) + output.write( obuf ) + + else: + mask = combineBitVectors( tdr.mask, sdr.mask, hdr.mask ) + tdi = combineBitVectors( tdr.tdi, sdr.tdi, hdr.tdi ) + tdo = combineBitVectors( tdr.tdo, sdr.tdo, hdr.tdo ) + + if xsdrsize != len(tdi): + xsdrsize = len(tdi) + cmdbuf[0] = XSDRSIZE + output.write( cmdbuf ) + obuf = bytearray(4) + struct.pack_into(">i", obuf, 0, xsdrsize ) # big endian 4 byte int to obuf + output.write( obuf ) + + if xtdomask != mask: + xtdomask = mask + cmdbuf[0] = XTDOMASK + output.write( cmdbuf ) + obuf = makeXSVFbytes( mask ) + output.write( obuf ) + + cmdbuf[0] = XSDRTDO + output.write( cmdbuf ) + obuf = makeXSVFbytes( tdi ) + output.write( obuf ) + obuf = makeXSVFbytes( tdo ) + output.write( obuf ) + #print( "len(tdo)=", len(tdo), "len(tdr.tdo)=", len(tdr.tdo), "len(sdr.tdo)=", len(sdr.tdo), "len(hdr.tdo)=", len(hdr.tdo) ) + + elif shiftOp == 'LSDR': + if doCOMMENTs: + writeComment( output, shiftOp_linenum, shiftOp ) + + mask = combineBitVectors( tdr.mask, sdr.mask, hdr.mask ) + tdi = combineBitVectors( tdr.tdi, sdr.tdi, hdr.tdi ) + tdo = combineBitVectors( tdr.tdo, sdr.tdo, hdr.tdo ) + + if xsdrsize != len(tdi): + xsdrsize = len(tdi) + cmdbuf[0] = XSDRSIZE + output.write( cmdbuf ) + obuf = bytearray(4) + struct.pack_into(">i", obuf, 0, xsdrsize ) # big endian 4 byte int to obuf + output.write( obuf ) + + if xtdomask != mask: + xtdomask = mask + cmdbuf[0] = XTDOMASK + output.write( cmdbuf ) + obuf = makeXSVFbytes( mask ) + output.write( obuf ) + + cmdbuf[0] = LSDR + output.write( cmdbuf ) + obuf = makeXSVFbytes( tdi ) + output.write( obuf ) + obuf = makeXSVFbytes( tdo ) + output.write( obuf ) + #print( "len(tdo)=", len(tdo), "len(tdr.tdo)=", len(tdr.tdo), "len(sdr.tdo)=", len(sdr.tdo), "len(hdr.tdo)=", len(hdr.tdo) ) + + elif tokVal == 'RUNTEST' or tokVal == 'LDELAY': + # e.g. from lattice tools: + # "RUNTEST IDLE 5 TCK 1.00E-003 SEC;" + saveTok = tokVal + nextTok() + min_time = 0 + run_count = 0 + max_time = 600 # ten minutes + if tokVal in run_state_allowed: + run_state = StateTxt.index(tokVal) + end_state = run_state # bottom of page 17 of SVF spec + nextTok() + if tokType != 'int' and tokType != 'float': + raise ParseError( tokLn, tokVal, "Expecting 'int' or 'float' after RUNTEST [run_state]") + timeval = tokVal; + nextTok() + if tokVal != 'TCK' and tokVal != 'SEC' and tokVal != 'SCK': + raise ParseError( tokLn, tokVal, "Expecting 'TCK' or 'SEC' or 'SCK' after RUNTEST [run_state] (run_count|min_time)") + if tokVal == 'TCK' or tokVal == 'SCK': + run_count = int( timeval ) + else: + min_time = timeval + nextTok() + if tokType == 'int' or tokType == 'float': + min_time = tokVal + nextTok() + if tokVal != 'SEC': + raise ParseError( tokLn, tokVal, "Expecting 'SEC' after RUNTEST [run_state] run_count min_time") + nextTok() + if tokVal == 'MAXIMUM': + nextTok() + if tokType != 'int' and tokType != 'float': + raise ParseError( tokLn, tokVal, "Expecting 'max_time' after RUNTEST [run_state] min_time SEC MAXIMUM") + max_time = tokVal + nextTok() + if tokVal != 'SEC': + raise ParseError( tokLn, tokVal, "Expecting 'max_time' after RUNTEST [run_state] min_time SEC MAXIMUM max_time") + nextTok() + if tokVal == 'ENDSTATE': + nextTok() + if tokVal not in run_state_allowed: + raise ParseError( tokLn, tokVal, "Expecting 'run_state' after RUNTEST .... ENDSTATE") + end_state = StateTxt.index(tokVal) + nextTok() + if tokVal != ';': + raise ParseError( tokLn, tokVal, "Expecting ';' after RUNTEST ....") + # print( "run_count=", run_count, "min_time=", min_time, + # "max_time=", max_time, "run_state=", State[run_state], "end_state=", State[end_state] ) + writeRUNTEST( output, run_state, end_state, run_count, min_time, saveTok ) + + elif tokVal == 'LCOUNT': + nextTok() + if tokType != 'int': + raise ParseError( tokLn, tokVal, "Expecting integer 'count' after LCOUNT") + loopCount = tokVal + nextTok() + if tokVal != ';': + raise ParseError( tokLn, tokVal, "Expecting ';' after LCOUNT count") + if doCOMMENTs: + writeComment( output, tokLn, 'LCOUNT' ) + obuf = bytearray(5) + obuf[0] = LCOUNT + struct.pack_into(">i", obuf, 1, loopCount ) # big endian 4 byte int to obuf + output.write( obuf ) + + elif tokVal == 'ENDDR': + nextTok() + if tokVal not in enddr_state_allowed: + raise ParseError( tokLn, tokVal, "Expecting 'stable_state' after ENDDR. (one of: DRPAUSE, IDLE, RESET)") + enddr_state = StateTxt.index(tokVal) + nextTok() + if tokVal != ';': + raise ParseError( tokLn, tokVal, "Expecting ';' after ENDDR stable_state") + if doCOMMENTs: + writeComment( output, tokLn, 'ENDDR' ) + obuf = bytearray(2) + obuf[0] = XENDDR + obuf[1] = enddr_state + output.write( obuf ) + + elif tokVal == 'ENDIR': + nextTok() + if tokVal not in endir_state_allowed: + raise ParseError( tokLn, tokVal, "Expecting 'stable_state' after ENDIR. (one of: IRPAUSE, IDLE, RESET)") + endir_state = StateTxt.index(tokVal) + nextTok() + if tokVal != ';': + raise ParseError( tokLn, tokVal, "Expecting ';' after ENDIR stable_state") + if doCOMMENTs: + writeComment( output, tokLn, 'ENDIR' ) + obuf = bytearray(2) + obuf[0] = XENDIR + obuf[1] = endir_state + output.write( obuf ) + + elif tokVal == 'STATE': + nextTok() + ln = tokLn + while tokVal != ';': + if tokVal not in StateTxt: + raise ParseError( tokLn, tokVal, "Expecting 'stable_state' after STATE") + stable_state = StateTxt.index( tokVal ) + + if doCOMMENTs and ln != -1: + writeComment( output, ln, 'STATE' ) + ln = -1 # save comment only once + + obuf = bytearray(2) + obuf[0] = XSTATE + obuf[1] = stable_state + output.write( obuf ) + nextTok() + + elif tokVal == 'FREQUENCY': + nextTok() + if tokVal != ';': + if tokType != 'int' and tokType != 'float': + raise ParseError( tokLn, tokVal, "Expecting 'cycles HZ' after FREQUENCY") + frequency = tokVal + nextTok() + if tokVal != 'HZ': + raise ParseError( tokLn, tokVal, "Expecting 'HZ' after FREQUENCY cycles") + nextTok() + if tokVal != ';': + raise ParseError( tokLn, tokVal, "Expecting ';' after FREQUENCY cycles HZ") + + else: + raise ParseError( tokLn, tokVal, "Unknown token '%s'" % tokVal) + +except StopIteration: + if not expecting_eof: + print( "Unexpected End of File at line ", tokLn ) + +except ParseError as pe: + print( "\n", pe ) + +finally: + # print( "closing file" ) + cmdbuf[0] = XCOMPLETE + output.write( cmdbuf ) + output.close() + Added: trunk/tools/xsvf_tools/xsvfdump.py =================================================================== --- trunk/tools/xsvf_tools/xsvfdump.py 2009-01-05 13:45:16 UTC (rev 1302) +++ trunk/tools/xsvf_tools/xsvfdump.py 2009-01-07 07:08:02 UTC (rev 1303) @@ -0,0 +1,255 @@ +#!/usr/bin/python3.0 + +# Copyright 2008, SoftPLC Corporation http://softplc.com +# Dick Hollenbeck di...@so... + +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, you may find one here: +# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html +# or you may search the http://www.gnu.org website for the version 2 license, +# or you may write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + +# Dump an Xilinx XSVF file to stdout + +# This program is written for python 3.0, and it is not easy to change this +# back to 2.x. You may find it easier to use python 3.x even if that means +# building it. + + +import sys +import struct + + +LABEL = "A script to dump an XSVF file to stdout" + + +Xsdrsize = 0 + + +(XCOMPLETE,XTDOMASK,XSIR,XSDR,XRUNTEST,hole0,hole1,XREPEAT,XSDRSIZE,XSDRTDO, + XSETSDRMASKS,XSDRINC,XSDRB,XSDRC,XSDRE,XSDRTDOB,XSDRTDOC, + XSDRTDOE,XSTATE,XENDIR,XENDDR,XSIR2,XCOMMENT,XWAIT,XWAITSTATE,LCOUNT,LDELAY,LSDR) = range(28) + + +(RESET,IDLE, + DRSELECT,DRCAPTURE,DRSHIFT,DREXIT1,DRPAUSE,DREXIT2,DRUPDATE, + IRSELECT,IRCAPTURE,IRSHIFT,IREXIT1,IRPAUSE,IREXIT2,IRUPDATE) = range(16) + + +State = ("RESET","IDLE", + "DRSELECT","DRCAPTURE","DRSHIFT","DREXIT1","DRPAUSE","DREXIT2","DRUPDATE", + "IRSELECT","IRCAPTURE","IRSHIFT","IREXIT1","IRPAUSE","IREXIT2","IRUPDATE") + +Setsdrmasks = 0 +SetsdrmasksOnesCount = 0 + +def ReadSDRMASKS( f, len ): + global Setsdrmasks, SetsdrmasksOnesCount + byteCount = (len+7)//8 + Setsdrmasks = f.read( byteCount ) + ls = [] + SetsdrmasksOnesCount = 0 + for b in Setsdrmasks: + ls.append( "%x" % ((b & 0xf0) >> 4) ) + ls.append( "%x" % ( b & 0x0f ) ) + for i in range(8): + if b & (1<<i): + SetsdrmasksOnesCount = SetsdrmasksOnesCount +1 + return ''.join(ls) + + +def bytes2hexString( f, len ): + byteCount = (len+7)//8 + bytebuf = f.read( byteCount ) + ls = [] + for b in bytebuf: + ls.append( "%x" % ((b & 0xf0) >> 4) ) + ls.append( "%x" % ( b & 0x0f ) ) + return ''.join(ls) + + +def ReadByte( f ): + """Read a byte from a file and return it as an int in least significant 8 bits""" + b = f.read(1) + if b: + return 0xff & b[0]; + else: + return -1 + + +def ShowState( state ): + """return the given state int as a state string""" + #return "0x%02x" % state # comment this out to get textual state form + global State + if 0 <= state <= IRUPDATE: + return State[state] + else: + return "Unknown state 0x%02x" % state + + +def ShowOpcode( op, f ): + """return the given byte as an opcode string""" + global Xsdrsize + if op == XCOMPLETE: + print("XCOMPLETE") + + elif op == XTDOMASK: + buf = bytes2hexString( f, Xsdrsize ) + print("XTDOMASK 0x%s" % buf) + + elif op == XSIR: + len = ReadByte( f ) + buf = bytes2hexString( f, len ) + print("XSIR 0x%02X 0x%s" % (len, buf)) + + elif op == XSDR: + tdi = bytes2hexString( f, Xsdrsize ) + print("XSDR 0x%s" % tdi) + + elif op == XRUNTEST: + len = struct.unpack( '>i', f.read(4) )[0] + print("XRUNTEST 0x%08X" % len) + + elif op == XREPEAT: + len = ReadByte( f ) + print("XREPEAT 0x%02X" % len) + + elif op == XSDRSIZE: + Xsdrsize = struct.unpack( '>i', f.read(4) )[0] + #print("XSDRSIZE 0x%08X" % Xsdrsize, file=sys.stderr ) + print("XSDRSIZE 0x%08X %d" % (Xsdrsize, Xsdrsize) ) + + elif op == XSDRTDO: + tdi = bytes2hexString( f, Xsdrsize ) + tdo = bytes2hexString( f, Xsdrsize ) + print("XSDRTDO 0x%s 0x%s" % (tdi, tdo) ) + + elif op == XSETSDRMASKS: + addrmask = bytes2hexString( f, Xsdrsize ) + datamask = ReadSDRMASKS( f, Xsdrsize ) + print("XSETSDRMASKS 0x%s 0x%s" % (addrmask, datamask) ) + + elif op == XSDRINC: + startaddr = bytes2hexString( f, Xsdrsize ) + len = ReadByte(f) + print("XSDRINC 0x%s 0x%02X" % (startaddr, len), end='' ) + for numTimes in range(len): + data = bytes2hexString( f, SetsdrmasksOnesCount) + print(" 0x%s" % data ) + print() # newline + + elif op == XSDRB: + tdi = bytes2hexString( f, Xsdrsize ) + print("XSDRB 0x%s" % tdi ) + + elif op == XSDRC: + tdi = bytes2hexString( f, Xsdrsize ) + print("XSDRC 0x%s" % tdi ) + + elif op == XSDRE: + tdi = bytes2hexString( f, Xsdrsize ) + print("XSDRE 0x%s" % tdi ) + + elif op == XSDRTDOB: + tdo = bytes2hexString( f, Xsdrsize ) + print("XSDRTDOB 0x%s" % tdo ) + + elif op == XSDRTDOC: + tdi = bytes2hexString( f, Xsdrsize ) + tdo = bytes2hexString( f, Xsdrsize ) + print("XSDRTDOC 0x%s 0x%s" % (tdi, tdo) ) + + elif op == XSDRTDOE: + tdi = bytes2hexString( f, Xsdrsize ) + tdo = bytes2hexString( f, Xsdrsize ) + print("XSDRTDOE 0x%s 0x%s" % (tdi, tdo) ) + + elif op == XSTATE: + b = ReadByte(f) + print("XSTATE %s" % ShowState(b)) + + elif op == XENDIR: + b = ReadByte( f ) + print("XENDIR %s" % ShowState(b)) + + elif op == XENDDR: + b = ReadByte( f ) + print("XENDDR %s" % ShowState(b)) + + elif op == XSIR2: + len = struct.unpack( '>H', f.read(2) )[0] + buf = bytes2hexString( f, len ) + print("XSIR2 0x%04X 0x%s" % (len, buf)) + + elif op == XCOMMENT: + cmt = [] + while 1: + b = ReadByte(f) + if b == 0: # terminating nul + break; + cmt.append( chr(b) ) + print("XCOMMENT \"%s\"" % ''.join(cmt) ) + + elif op == XWAIT: + run_state = ReadByte(f) + end_state = ReadByte(f) + useconds = struct.unpack( '>i', f.read(4) )[0] + print("XWAIT %s %s" % (ShowState(run_state), ShowState(end_state)), useconds) + + elif op == XWAITSTATE: + run_state = ReadByte(f) + end_state = ReadByte(f) + clocks = struct.unpack( '>i', f.read(4) )[0] + useconds = struct.unpack( '>i', f.read(4) )[0] + print("XWAITSTATE %s %s CLOCKS=%d USECS=%d" % (ShowState(run_state), ShowState(end_state), clocks, useconds) ) + + elif op == LCOUNT: + loop_count = struct.unpack( '>i', f.read(4) )[0] + print("LCOUNT", loop_count ) + + elif op == LDELAY: + run_state = ReadByte(f) + clocks = struct.unpack( '>i', f.read(4) )[0] + useconds = struct.unpack( '>i', f.read(4) )[0] + print("LDELAY %s CLOCKS=%d USECS=%d" % (ShowState(run_state), clocks, useconds) ) + + elif op == LSDR: + tdi = bytes2hexString( f, Xsdrsize ) + tdo = bytes2hexString( f, Xsdrsize ) + print("LSDR 0x%s 0x%s" % (tdi, tdo) ) + + else: + print("UNKNOWN op 0x%02X %d" % (op, op)) + exit(1) + + +def main(): + + if len( sys.argv ) < 2: + print("usage %s <xsvf_filename>" % sys.argv[0]) + exit(1) + + f = open( sys.argv[1], 'rb' ) + + opcode = ReadByte( f ) + while opcode != -1: + # print the position within the file, then the command + print( "%d: " % f.tell(), end='' ) + ShowOpcode( opcode, f ) + opcode = ReadByte(f) + + +if __name__ == "__main__": + main() + |
From: ntfreak at B. <nt...@ma...> - 2009-01-05 14:45:17
|
Author: ntfreak Date: 2009-01-05 14:45:16 +0100 (Mon, 05 Jan 2009) New Revision: 1302 Modified: trunk/src/target/board/x300t.cfg trunk/src/target/interface/parport_dlc5.cfg trunk/src/target/target/smp8634.cfg Log: - add missing svn props from r1299 commit Modified: trunk/src/target/board/x300t.cfg =================================================================== --- trunk/src/target/board/x300t.cfg 2009-01-05 09:32:23 UTC (rev 1301) +++ trunk/src/target/board/x300t.cfg 2009-01-05 13:45:16 UTC (rev 1302) @@ -1,17 +1,17 @@ -# This is for the T-Home X300T / X301T IPTV box, -# which are based on IPTV reference designs from Kiss/Cisco KMM-32** -# -# It has Sigma Designs SMP8634 chip. -source [find target/smp8634.cfg] - -$_TARGETNAME configure -event reset-init { x300t_init } - -# 1MB CFI capable flash -# flash bank <driver> <base> <size> <chip_width> <bus_width> -flash bank cfi 0xac000000 0x100000 2 2 0 - -proc x300t_init { } { - # Setup SDRAM config and flash mapping - # map flash to CPU address space REG_BASE_cpu_block+CPU_remap4 - mww 0x6f010 0x48000000 -} +# This is for the T-Home X300T / X301T IPTV box, +# which are based on IPTV reference designs from Kiss/Cisco KMM-32** +# +# It has Sigma Designs SMP8634 chip. +source [find target/smp8634.cfg] + +$_TARGETNAME configure -event reset-init { x300t_init } + +# 1MB CFI capable flash +# flash bank <driver> <base> <size> <chip_width> <bus_width> +flash bank cfi 0xac000000 0x100000 2 2 0 + +proc x300t_init { } { + # Setup SDRAM config and flash mapping + # map flash to CPU address space REG_BASE_cpu_block+CPU_remap4 + mww 0x6f010 0x48000000 +} Property changes on: trunk/src/target/board/x300t.cfg ___________________________________________________________________ Name: svn:eol-style + native Modified: trunk/src/target/interface/parport_dlc5.cfg =================================================================== --- trunk/src/target/interface/parport_dlc5.cfg 2009-01-05 09:32:23 UTC (rev 1301) +++ trunk/src/target/interface/parport_dlc5.cfg 2009-01-05 13:45:16 UTC (rev 1302) @@ -1,7 +1,7 @@ -telnet_port 4444 -gdb_port 2001 - -interface parport -parport_port /dev/parport0 -parport_cable dlc5 -jtag_speed 0 +telnet_port 4444 +gdb_port 2001 + +interface parport +parport_port /dev/parport0 +parport_cable dlc5 +jtag_speed 0 Property changes on: trunk/src/target/interface/parport_dlc5.cfg ___________________________________________________________________ Name: svn:eol-style + native Modified: trunk/src/target/target/smp8634.cfg =================================================================== --- trunk/src/target/target/smp8634.cfg 2009-01-05 09:32:23 UTC (rev 1301) +++ trunk/src/target/target/smp8634.cfg 2009-01-05 13:45:16 UTC (rev 1302) @@ -1,32 +1,32 @@ -# script for Sigma Designs SMP8634 (eventually even SMP8635) - -if { [info exists CHIPNAME] } { - set _CHIPNAME $CHIPNAME -} else { - set _CHIPNAME smp8634 -} - -if { [info exists ENDIAN] } { - set _ENDIAN $ENDIAN -} else { - set _ENDIAN little -} - -if { [info exists CPUTAPID ] } { - set _CPUTAPID $CPUTAPID -} else { - # force an error till we get a good number - set _CPUTAPID 0x08630001 -} - -jtag_nsrst_delay 100 -jtag_ntrst_delay 100 - -reset_config trst_and_srst separate - -# jtag scan chain -# format L IRC IRCM IDCODE (Length, IR Capture, IR Capture Mask, IDCODE) -jtag newtap $_CHIPNAME cpu -irlen 5 -ircapture 0x1 -irmask 0x1 - -set _TARGETNAME [format "%s.cpu" $_CHIPNAME] -target create $_TARGETNAME mips_m4k -endian $_ENDIAN -variant +# script for Sigma Designs SMP8634 (eventually even SMP8635) + +if { [info exists CHIPNAME] } { + set _CHIPNAME $CHIPNAME +} else { + set _CHIPNAME smp8634 +} + +if { [info exists ENDIAN] } { + set _ENDIAN $ENDIAN +} else { + set _ENDIAN little +} + +if { [info exists CPUTAPID ] } { + set _CPUTAPID $CPUTAPID +} else { + # force an error till we get a good number + set _CPUTAPID 0x08630001 +} + +jtag_nsrst_delay 100 +jtag_ntrst_delay 100 + +reset_config trst_and_srst separate + +# jtag scan chain +# format L IRC IRCM IDCODE (Length, IR Capture, IR Capture Mask, IDCODE) +jtag newtap $_CHIPNAME cpu -irlen 5 -ircapture 0x1 -irmask 0x1 + +set _TARGETNAME [format "%s.cpu" $_CHIPNAME] +target create $_TARGETNAME mips_m4k -endian $_ENDIAN -variant Property changes on: trunk/src/target/target/smp8634.cfg ___________________________________________________________________ Name: svn:eol-style + native |
From: <oh...@ma...> - 2009-01-05 10:32:27
|
Author: oharboe Date: 2009-01-05 10:32:23 +0100 (Mon, 05 Jan 2009) New Revision: 1301 Modified: trunk/src/flash/pic32mx.c trunk/src/flash/pic32mx.h trunk/src/target/mips32_pracc.c trunk/src/target/mips32_pracc.h Log: John McCarthy <jg...@ma...> pic32mx flash fixups and speedups Modified: trunk/src/flash/pic32mx.c =================================================================== --- trunk/src/flash/pic32mx.c 2009-01-05 09:26:25 UTC (rev 1300) +++ trunk/src/flash/pic32mx.c 2009-01-05 09:32:23 UTC (rev 1301) @@ -71,6 +71,8 @@ int pic32mx_erase(struct flash_bank_s *bank, int first, int last); int pic32mx_protect(struct flash_bank_s *bank, int set, int first, int last); int pic32mx_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count); +int pic32mx_write_row(struct flash_bank_s *bank, u32 address, u32 srcaddr); +int pic32mx_write_word(struct flash_bank_s *bank, u32 address, u32 word); int pic32mx_probe(struct flash_bank_s *bank); int pic32mx_auto_probe(struct flash_bank_s *bank); int pic32mx_handle_part_id_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); @@ -189,7 +191,6 @@ int pic32mx_protect_check(struct flash_bank_s *bank) { target_t *target = bank->target; - pic32mx_flash_bank_t *pic32mx_info = bank->driver_priv; u32 devcfg0; int s; @@ -233,9 +234,9 @@ return ERROR_TARGET_NOT_HALTED; } -#if 0 if ((first == 0) && (last == (bank->num_sectors - 1)) && (bank->base == PIC32MX_KSEG0_PGM_FLASH || bank->base == PIC32MX_KSEG1_PGM_FLASH)) { + LOG_DEBUG("Erasing entire program flash"); status = pic32mx_nvm_exec(bank, NVMCON_OP_PFM_ERASE, 50); if( status & NVMCON_NVMERR ) return ERROR_FLASH_OPERATION_FAILED; @@ -243,11 +244,13 @@ return ERROR_FLASH_OPERATION_FAILED; return ERROR_OK; } -#endif for (i = first; i <= last; i++) { - target_write_u32(target, PIC32MX_NVMADDR, bank->base + bank->sectors[i].offset); + if(bank->base >= PIC32MX_KSEG1_PGM_FLASH) + target_write_u32(target, PIC32MX_NVMADDR, KS1Virt2Phys(bank->base + bank->sectors[i].offset)); + else + target_write_u32(target, PIC32MX_NVMADDR, KS0Virt2Phys(bank->base + bank->sectors[i].offset)); status = pic32mx_nvm_exec(bank, NVMCON_OP_PAGE_ERASE, 10); @@ -354,15 +357,14 @@ int pic32mx_write_block(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count) { - pic32mx_flash_bank_t *pic32mx_info = bank->driver_priv; target_t *target = bank->target; - u32 buffer_size = 8192; + u32 buffer_size = 512; working_area_t *source; u32 address = bank->base + offset; - reg_param_t reg_params[4]; + int retval = ERROR_OK; #if 0 + pic32mx_flash_bank_t *pic32mx_info = bank->driver_priv; armv7m_algorithm_t armv7m_info; - int retval = ERROR_OK; u8 pic32mx_flash_write_code[] = { /* write: */ @@ -395,40 +397,34 @@ if ((retval=target_write_buffer(target, pic32mx_info->write_algorithm->address, sizeof(pic32mx_flash_write_code), pic32mx_flash_write_code))!=ERROR_OK) return retval; +#endif /* memory buffer */ - while (target_alloc_working_area(target, buffer_size, &source) != ERROR_OK) + if (target_alloc_working_area(target, buffer_size, &source) != ERROR_OK) { - buffer_size /= 2; - if (buffer_size <= 256) - { - /* if we already allocated the writing code, but failed to get a buffer, free the algorithm */ - if (pic32mx_info->write_algorithm) - target_free_working_area(target, pic32mx_info->write_algorithm); +#if 0 + /* if we already allocated the writing code, but failed to get a buffer, free the algorithm */ + if (pic32mx_info->write_algorithm) + target_free_working_area(target, pic32mx_info->write_algorithm); +#endif - LOG_WARNING("no large enough working area available, can't do block memory writes"); - return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; - } - }; + LOG_WARNING("no large enough working area available, can't do block memory writes"); + return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; + } - armv7m_info.common_magic = ARMV7M_COMMON_MAGIC; - armv7m_info.core_mode = ARMV7M_MODE_ANY; - - init_reg_param(®_params[0], "r0", 32, PARAM_OUT); - init_reg_param(®_params[1], "r1", 32, PARAM_OUT); - init_reg_param(®_params[2], "r2", 32, PARAM_OUT); - init_reg_param(®_params[3], "r3", 32, PARAM_IN); - - while (count > 0) + while (count >= buffer_size/4) { - u32 thisrun_count = (count > (buffer_size / 2)) ? (buffer_size / 2) : count; + u32 status; - if ((retval = target_write_buffer(target, source->address, thisrun_count * 2, buffer))!=ERROR_OK) + if ((retval = target_write_buffer(target, source->address, buffer_size, buffer))!=ERROR_OK) { + LOG_ERROR("Failed to write row buffer (%d words) to RAM", buffer_size/4); break; + } +#if 0 buf_set_u32(reg_params[0].value, 0, 32, source->address); buf_set_u32(reg_params[1].value, 0, 32, address); - buf_set_u32(reg_params[2].value, 0, 32, thisrun_count); + buf_set_u32(reg_params[2].value, 0, 32, buffer_size/4); if ((retval = target->type->run_algorithm(target, 0, NULL, 4, reg_params, pic32mx_info->write_algorithm->address, \ pic32mx_info->write_algorithm->address + (sizeof(pic32mx_flash_write_code) - 10), 10000, &armv7m_info)) != ERROR_OK) @@ -443,39 +439,86 @@ retval = ERROR_FLASH_OPERATION_FAILED; break; } +#endif + status = pic32mx_write_row(bank, address, source->address); + if( status & NVMCON_NVMERR ) { + LOG_ERROR("Flash write error NVMERR (status=0x%08x)", status); + retval = ERROR_FLASH_OPERATION_FAILED; + break; + } + if( status & NVMCON_LVDERR ) { + LOG_ERROR("Flash write error LVDERR (status=0x%08x)", status); + retval = ERROR_FLASH_OPERATION_FAILED; + break; + } - buffer += thisrun_count * 2; - address += thisrun_count * 2; - count -= thisrun_count; + buffer += buffer_size; + address += buffer_size; + count -= buffer_size/4; } target_free_working_area(target, source); - target_free_working_area(target, pic32mx_info->write_algorithm); - destroy_reg_param(®_params[0]); - destroy_reg_param(®_params[1]); - destroy_reg_param(®_params[2]); - destroy_reg_param(®_params[3]); + while(count > 0) + { + u32 status; + status = pic32mx_write_word(bank, address, *(u32*)buffer); + if( status & NVMCON_NVMERR ) { + LOG_ERROR("Flash write error NVMERR (status=0x%08x)", status); + retval = ERROR_FLASH_OPERATION_FAILED; + break; + } + if( status & NVMCON_LVDERR ) { + LOG_ERROR("Flash write error LVDERR (status=0x%08x)", status); + retval = ERROR_FLASH_OPERATION_FAILED; + break; + } + + buffer += 4; + address += 4; + count--; + } + return retval; -#else - return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; -#endif } int pic32mx_write_word(struct flash_bank_s *bank, u32 address, u32 word) { target_t *target = bank->target; - target_write_u32(target, PIC32MX_NVMADDR, address); + if(bank->base >= PIC32MX_KSEG1_PGM_FLASH) + target_write_u32(target, PIC32MX_NVMADDR, KS1Virt2Phys(address)); + else + target_write_u32(target, PIC32MX_NVMADDR, KS0Virt2Phys(address)); target_write_u32(target, PIC32MX_NVMDATA, word); return pic32mx_nvm_exec(bank, NVMCON_OP_WORD_PROG, 5); } +/* + * Write a 128 word (512 byte) row to flash address from RAM srcaddr. + */ +int pic32mx_write_row(struct flash_bank_s *bank, u32 address, u32 srcaddr) +{ + target_t *target = bank->target; + + LOG_DEBUG("addr: 0x%08x srcaddr: 0x%08x", address, srcaddr); + + if(address >= PIC32MX_KSEG1_PGM_FLASH) + target_write_u32(target, PIC32MX_NVMADDR, KS1Virt2Phys(address)); + else + target_write_u32(target, PIC32MX_NVMADDR, KS0Virt2Phys(address)); + if(srcaddr >= PIC32MX_KSEG1_RAM) + target_write_u32(target, PIC32MX_NVMSRCADDR, KS1Virt2Phys(srcaddr)); + else + target_write_u32(target, PIC32MX_NVMSRCADDR, KS0Virt2Phys(srcaddr)); + + return pic32mx_nvm_exec(bank, NVMCON_OP_ROW_PROG, 100); +} + int pic32mx_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count) { - target_t *target = bank->target; u32 words_remaining = (count / 4); u32 bytes_remaining = (count & 0x00000003); u32 address = bank->base + offset; @@ -862,7 +905,6 @@ { flash_bank_t *bank; u32 address, value; - int i; int status, res; if (argc != 3) Modified: trunk/src/flash/pic32mx.h =================================================================== --- trunk/src/flash/pic32mx.h 2009-01-05 09:26:25 UTC (rev 1300) +++ trunk/src/flash/pic32mx.h 2009-01-05 09:32:23 UTC (rev 1301) @@ -42,22 +42,31 @@ /* pic32mx memory locations */ #define PIC32MX_KUSEG_PGM_FLASH 0x7D000000 -#define PIC32MX_KUSEG_RAM 0x7F000000 +#define PIC32MX_KUSEG_RAM 0x7F000000 -#define PIC32MX_KSEG0_RAM 0x80000000 +#define PIC32MX_KSEG0_RAM 0x80000000 #define PIC32MX_KSEG0_PGM_FLASH 0x9D000000 #define PIC32MX_KSEG0_BOOT_FLASH 0x9FC00000 -#define PIC32MX_KSEG1_RAM 0xA0000000 +#define PIC32MX_KSEG1_RAM 0xA0000000 #define PIC32MX_KSEG1_PGM_FLASH 0xBD000000 #define PIC32MX_KSEG1_PERIPHERAL 0xBF800000 #define PIC32MX_KSEG1_BOOT_FLASH 0xBFC00000 -#define PIC32MX_PHYS_RAM 0x00000000 +#define PIC32MX_PHYS_RAM 0x00000000 #define PIC32MX_PHYS_PGM_FLASH 0x1D000000 #define PIC32MX_PHYS_PERIPHERALS 0x1F800000 #define PIC32MX_PHYS_BOOT_FLASH 0x1FC00000 +/* + * Translate Virtual and Physical addresses. + * Note: These macros only work for KSEG0/KSEG1 addresses. + */ +#define KS1Virt2Phys(vaddr) ((vaddr)-0xA0000000) +#define Phys2KS1Virt(paddr) ((paddr)+0xA0000000) +#define KS0Virt2Phys(vaddr) ((vaddr)-0x80000000) +#define Phys2KS0Virt(paddr) ((paddr)+0x80000000) + /* pic32mx configuration register locations */ #define PIC32MX_DEVCFG0 0xBFC02FFC @@ -77,11 +86,11 @@ #define NVMCON_NVMERR (1<<13) #define NVMCON_LVDERR (1<<12) #define NVMCON_LVDSTAT (1<<11) -#define NVMCON_OP_PFM_ERASE 0x5 +#define NVMCON_OP_PFM_ERASE 0x5 #define NVMCON_OP_PAGE_ERASE 0x4 -#define NVMCON_OP_ROW_PROG 0x3 -#define NVMCON_OP_WORD_PROG 0x1 -#define NVMCON_OP_NOP 0x0 +#define NVMCON_OP_ROW_PROG 0x3 +#define NVMCON_OP_WORD_PROG 0x1 +#define NVMCON_OP_NOP 0x0 #define PIC32MX_NVMKEY 0xBF80F410 #define PIC32MX_NVMADDR 0xBF80F420 Modified: trunk/src/target/mips32_pracc.c =================================================================== --- trunk/src/target/mips32_pracc.c 2009-01-05 09:26:25 UTC (rev 1300) +++ trunk/src/target/mips32_pracc.c 2009-01-05 09:32:23 UTC (rev 1301) @@ -218,7 +218,10 @@ case 2: return mips32_pracc_read_mem16(ejtag_info, addr, count, (u16*)buf); case 4: - return mips32_pracc_read_mem32(ejtag_info, addr, count, (u32*)buf); + if(count==1) + return mips32_pracc_read_u32(ejtag_info, addr, (u32*)buf); + else + return mips32_pracc_read_mem32(ejtag_info, addr, count, (u32*)buf); } return ERROR_OK; @@ -247,8 +250,8 @@ MIPS32_BEQ(0,10,9), /* beq 0, $10, end */ MIPS32_NOP, - MIPS32_LW(12,0,9), /* lw $12,0($9), Load $12 with the word @mem[$9] */ - MIPS32_SW(12,0,11), /* sw $12,0($11) */ + MIPS32_LW(8,0,9), /* lw $8,0($9), Load $8 with the word @mem[$9] */ + MIPS32_SW(8,0,11), /* sw $8,0($11) */ MIPS32_ADDI(10,10,NEG16(1)), /* $10-- */ MIPS32_ADDI(9,9,4), /* $1+=4 */ @@ -298,6 +301,47 @@ return retval; } +int mips32_pracc_read_u32(mips_ejtag_t *ejtag_info, u32 addr, u32 *buf) +{ + u32 code[] = { + /* start: */ + MIPS32_MTC0(15,31,0), /* move $15 to COP0 DeSave */ + MIPS32_LUI(15,UPPER16(MIPS32_PRACC_STACK)), /* $15 = MIPS32_PRACC_STACK */ + MIPS32_ORI(15,15,LOWER16(MIPS32_PRACC_STACK)), + MIPS32_SW(8,0,15), /* sw $8,($15) */ + MIPS32_SW(9,0,15), /* sw $9,($15) */ + + MIPS32_LUI(8,UPPER16(MIPS32_PRACC_PARAM_IN)), /* $8 = MIPS32_PRACC_PARAM_IN */ + MIPS32_ORI(8,8,LOWER16(MIPS32_PRACC_PARAM_IN)), + MIPS32_LW(8,0,8), /* $8=mem[$8]; read addr */ + MIPS32_LUI(9,UPPER16(MIPS32_PRACC_PARAM_OUT)), /* $9=MIPS32_PRACC_PARAM_OUT */ + MIPS32_ORI(9,9,LOWER16(MIPS32_PRACC_PARAM_OUT)), + + MIPS32_LW(8,0,8), /* lw $8,0($8), Load $8 with the word @mem[$8] */ + MIPS32_SW(8,0,9), /* sw $8,0($9) */ + + MIPS32_LW(9,0,15), /* lw $9,($15) */ + MIPS32_LW(8,0,15), /* lw $8,($15) */ + MIPS32_MFC0(15,31,0), /* move COP0 DeSave to $15 */ + MIPS32_NOP, + MIPS32_B(NEG16(17)), /* b start */ + MIPS32_NOP, + }; + + int retval = ERROR_OK; + u32 param_in[1]; + + param_in[0] = addr; + + if ((retval = mips32_pracc_exec(ejtag_info, sizeof(code)/sizeof(code[0]), code, + sizeof(param_in)/sizeof(param_in[0]), param_in, sizeof(u32), buf, 1)) != ERROR_OK) + { + return retval; + } + + return retval; +} + int mips32_pracc_read_mem16(mips_ejtag_t *ejtag_info, u32 addr, int count, u16 *buf) { u32 code[] = { @@ -321,8 +365,8 @@ MIPS32_BEQ(0,10,9), /* beq 0, $10, end */ MIPS32_NOP, - MIPS32_LHU(12,0,9), /* lw $12,0($9), Load $12 with the halfword @mem[$9] */ - MIPS32_SW(12,0,11), /* sw $12,0($11) */ + MIPS32_LHU(8,0,9), /* lw $8,0($9), Load $8 with the halfword @mem[$9] */ + MIPS32_SW(8,0,11), /* sw $8,0($11) */ MIPS32_ADDI(10,10,NEG16(1)), /* $10-- */ MIPS32_ADDI(9,9,2), /* $9+=2 */ @@ -400,8 +444,8 @@ MIPS32_BEQ(0,10,9), /* beq 0, $10, end */ MIPS32_NOP, - MIPS32_LBU(12,0,9), /* lw $12,0($9), Load t4 with the byte @mem[t1] */ - MIPS32_SW(12,0,11), /* sw $12,0($11) */ + MIPS32_LBU(8,0,9), /* lw $8,0($9), Load t4 with the byte @mem[t1] */ + MIPS32_SW(8,0,11), /* sw $8,0($11) */ MIPS32_ADDI(10,10,NEG16(1)), /* $10-- */ MIPS32_ADDI(9,9,1), /* $9+=1 */ @@ -465,7 +509,10 @@ case 2: return mips32_pracc_write_mem16(ejtag_info, addr, count,(u16*)buf); case 4: - return mips32_pracc_write_mem32(ejtag_info, addr, count, (u32*)buf); + if(count==1) + return mips32_pracc_write_u32(ejtag_info, addr, (u32*)buf); + else + return mips32_pracc_write_mem32(ejtag_info, addr, count, (u32*)buf); } return ERROR_OK; @@ -526,6 +573,42 @@ return ERROR_OK; } +int mips32_pracc_write_u32(mips_ejtag_t *ejtag_info, u32 addr, u32 *buf) +{ + u32 code[] = { + /* start: */ + MIPS32_MTC0(15,31,0), /* move $15 to COP0 DeSave */ + MIPS32_LUI(15,UPPER16(MIPS32_PRACC_STACK)), /* $15 = MIPS32_PRACC_STACK */ + MIPS32_ORI(15,15,LOWER16(MIPS32_PRACC_STACK)), + MIPS32_SW(8,0,15), /* sw $8,($15) */ + MIPS32_SW(9,0,15), /* sw $9,($15) */ + + MIPS32_LUI(8,UPPER16((MIPS32_PRACC_PARAM_IN+4))), /* $8 = MIPS32_PRACC_PARAM_IN+4 */ + MIPS32_ORI(8,8,LOWER16((MIPS32_PRACC_PARAM_IN+4))), + MIPS32_LW(9,NEG16(4),8), /* Load write addr to $9 */ + + MIPS32_LW(8,0,8), /* lw $8,0($8), Load $8 with the word @mem[$8] */ + MIPS32_SW(8,0,9), /* sw $8,0($9) */ + + MIPS32_LW(9,0,15), /* lw $9,($15) */ + MIPS32_LW(8,0,15), /* lw $8,($15) */ + MIPS32_MFC0(15,31,0), /* move COP0 DeSave to $15 */ + MIPS32_NOP, + MIPS32_B(NEG16(15)), /* b start */ + MIPS32_NOP, + }; + + /* TODO remove array */ + u32 param_in[1+1]; + param_in[0] = addr; + param_in[1] = *buf; + + mips32_pracc_exec(ejtag_info, sizeof(code)/sizeof(code[0]), code, \ + sizeof(param_in)/sizeof(param_in[0]),param_in, 0, NULL, 1); + + return ERROR_OK; +} + int mips32_pracc_write_mem16(mips_ejtag_t *ejtag_info, u32 addr, int count, u16 *buf) { u32 code[] = { Modified: trunk/src/target/mips32_pracc.h =================================================================== --- trunk/src/target/mips32_pracc.h 2009-01-05 09:26:25 UTC (rev 1300) +++ trunk/src/target/mips32_pracc.h 2009-01-05 09:32:23 UTC (rev 1301) @@ -42,10 +42,12 @@ extern int mips32_pracc_read_mem8(mips_ejtag_t *ejtag_info, u32 addr, int count, u8 *buf); extern int mips32_pracc_read_mem16(mips_ejtag_t *ejtag_info, u32 addr, int count, u16 *buf); extern int mips32_pracc_read_mem32(mips_ejtag_t *ejtag_info, u32 addr, int count, u32 *buf); +extern int mips32_pracc_read_u32(mips_ejtag_t *ejtag_info, u32 addr, u32 *buf); extern int mips32_pracc_write_mem8(mips_ejtag_t *ejtag_info, u32 addr, int count, u8 *buf); extern int mips32_pracc_write_mem16(mips_ejtag_t *ejtag_info, u32 addr, int count, u16 *buf); extern int mips32_pracc_write_mem32(mips_ejtag_t *ejtag_info, u32 addr, int count, u32 *buf); +extern int mips32_pracc_write_u32(mips_ejtag_t *ejtag_info, u32 addr, u32 *buf); extern int mips32_pracc_read_regs(mips_ejtag_t *ejtag_info, u32 *regs); extern int mips32_pracc_write_regs(mips_ejtag_t *ejtag_info, u32 *regs); |
From: <oh...@ma...> - 2009-01-05 10:26:26
|
Author: oharboe Date: 2009-01-05 10:26:25 +0100 (Mon, 05 Jan 2009) New Revision: 1300 Modified: trunk/src/jtag/ft2232.c Log: John McCarthy <jg...@ma...> formatting fix of debug output Modified: trunk/src/jtag/ft2232.c =================================================================== --- trunk/src/jtag/ft2232.c 2009-01-05 09:25:23 UTC (rev 1299) +++ trunk/src/jtag/ft2232.c 2009-01-05 09:26:25 UTC (rev 1300) @@ -442,7 +442,7 @@ timeval_subtract(&d_inter2, &inter2, &start); timeval_subtract(&d_end, &end, &start); - LOG_INFO("inter: %i.%i, inter2: %i.%i end: %i.%i", d_inter.tv_sec, d_inter.tv_usec, d_inter2.tv_sec, d_inter2.tv_usec, d_end.tv_sec, d_end.tv_usec); + LOG_INFO("inter: %i.%06i, inter2: %i.%06i end: %i.%06i", d_inter.tv_sec, d_inter.tv_usec, d_inter2.tv_sec, d_inter2.tv_usec, d_end.tv_sec, d_end.tv_usec); #endif |
From: <oh...@ma...> - 2009-01-05 10:25:28
|
Author: oharboe Date: 2009-01-05 10:25:23 +0100 (Mon, 05 Jan 2009) New Revision: 1299 Added: trunk/src/target/board/x300t.cfg trunk/src/target/interface/parport_dlc5.cfg trunk/src/target/target/smp8634.cfg Log: Andi <ope...@gm...> basic support for the MIPS based SMP8634 SoC. Added: trunk/src/target/board/x300t.cfg =================================================================== --- trunk/src/target/board/x300t.cfg 2009-01-04 08:51:48 UTC (rev 1298) +++ trunk/src/target/board/x300t.cfg 2009-01-05 09:25:23 UTC (rev 1299) @@ -0,0 +1,17 @@ +# This is for the T-Home X300T / X301T IPTV box, +# which are based on IPTV reference designs from Kiss/Cisco KMM-32** +# +# It has Sigma Designs SMP8634 chip. +source [find target/smp8634.cfg] + +$_TARGETNAME configure -event reset-init { x300t_init } + +# 1MB CFI capable flash +# flash bank <driver> <base> <size> <chip_width> <bus_width> +flash bank cfi 0xac000000 0x100000 2 2 0 + +proc x300t_init { } { + # Setup SDRAM config and flash mapping + # map flash to CPU address space REG_BASE_cpu_block+CPU_remap4 + mww 0x6f010 0x48000000 +} Added: trunk/src/target/interface/parport_dlc5.cfg =================================================================== --- trunk/src/target/interface/parport_dlc5.cfg 2009-01-04 08:51:48 UTC (rev 1298) +++ trunk/src/target/interface/parport_dlc5.cfg 2009-01-05 09:25:23 UTC (rev 1299) @@ -0,0 +1,7 @@ +telnet_port 4444 +gdb_port 2001 + +interface parport +parport_port /dev/parport0 +parport_cable dlc5 +jtag_speed 0 Added: trunk/src/target/target/smp8634.cfg =================================================================== --- trunk/src/target/target/smp8634.cfg 2009-01-04 08:51:48 UTC (rev 1298) +++ trunk/src/target/target/smp8634.cfg 2009-01-05 09:25:23 UTC (rev 1299) @@ -0,0 +1,32 @@ +# script for Sigma Designs SMP8634 (eventually even SMP8635) + +if { [info exists CHIPNAME] } { + set _CHIPNAME $CHIPNAME +} else { + set _CHIPNAME smp8634 +} + +if { [info exists ENDIAN] } { + set _ENDIAN $ENDIAN +} else { + set _ENDIAN little +} + +if { [info exists CPUTAPID ] } { + set _CPUTAPID $CPUTAPID +} else { + # force an error till we get a good number + set _CPUTAPID 0x08630001 +} + +jtag_nsrst_delay 100 +jtag_ntrst_delay 100 + +reset_config trst_and_srst separate + +# jtag scan chain +# format L IRC IRCM IDCODE (Length, IR Capture, IR Capture Mask, IDCODE) +jtag newtap $_CHIPNAME cpu -irlen 5 -ircapture 0x1 -irmask 0x1 + +set _TARGETNAME [format "%s.cpu" $_CHIPNAME] +target create $_TARGETNAME mips_m4k -endian $_ENDIAN -variant |
From: <oh...@ma...> - 2009-01-04 09:51:50
|
Author: oharboe Date: 2009-01-04 09:51:48 +0100 (Sun, 04 Jan 2009) New Revision: 1298 Modified: trunk/src/target/board/pic-p32mx.cfg Log: eol-style native Modified: trunk/src/target/board/pic-p32mx.cfg =================================================================== --- trunk/src/target/board/pic-p32mx.cfg 2009-01-03 08:56:52 UTC (rev 1297) +++ trunk/src/target/board/pic-p32mx.cfg 2009-01-04 08:51:48 UTC (rev 1298) @@ -1,8 +1,8 @@ -# The Olimex PIC-P32MX has a PIC32MX - -set CPUTAPID 0x40916053 -source [find target/pic32mx.cfg] - -init -flash probe 0 -flash probe 1 +# The Olimex PIC-P32MX has a PIC32MX + +set CPUTAPID 0x40916053 +source [find target/pic32mx.cfg] + +init +flash probe 0 +flash probe 1 Property changes on: trunk/src/target/board/pic-p32mx.cfg ___________________________________________________________________ Name: svn:eol-style + native |
From: <oh...@ma...> - 2009-01-03 09:56:55
|
Author: oharboe Date: 2009-01-03 09:56:52 +0100 (Sat, 03 Jan 2009) New Revision: 1297 Modified: trunk/src/flash/pic32mx.c trunk/src/flash/pic32mx.h Log: eol-style native Modified: trunk/src/flash/pic32mx.c =================================================================== --- trunk/src/flash/pic32mx.c 2009-01-02 23:58:16 UTC (rev 1296) +++ trunk/src/flash/pic32mx.c 2009-01-03 08:56:52 UTC (rev 1297) @@ -1,902 +1,902 @@ -/*************************************************************************** - * Copyright (C) 2005 by Dominic Rath * - * Dom...@gm... * - * * - * Copyright (C) 2008 by Spencer Oliver * - * sp...@sp... * - * * - * Copyright (C) 2008 by John McCarthy * - * jg...@ma... * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You 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. * - ***************************************************************************/ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "replacements.h" - -#include "pic32mx.h" -#include "flash.h" -#include "target.h" -#include "log.h" -#include "mips32.h" -#include "algorithm.h" -#include "binarybuffer.h" - -#include <stdlib.h> -#include <string.h> - -static -struct pic32mx_devs_s { - u8 devid; - char *name; - u32 pfm_size; -} pic32mx_devs[] = { - { 0x78, "460F512L USB", 512 }, - { 0x74, "460F256L USB", 256 }, - { 0x6D, "440F128L USB", 128 }, - { 0x56, "440F512H USB", 512 }, - { 0x52, "440F256H USB", 256 }, - { 0x4D, "440F128H USB", 128 }, - { 0x42, "420F032H USB", 32 }, - { 0x38, "360F512L", 512 }, - { 0x34, "360F256L", 256 }, - { 0x2D, "340F128L", 128 }, - { 0x2A, "320F128L", 128 }, - { 0x16, "340F512H", 512 }, - { 0x12, "340F256H", 256 }, - { 0x0D, "340F128H", 128 }, - { 0x0A, "320F128H", 128 }, - { 0x06, "320F064H", 64 }, - { 0x02, "320F032H", 32 }, - { 0x00, NULL, 0 } -}; - -int pic32mx_register_commands(struct command_context_s *cmd_ctx); -int pic32mx_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank); -int pic32mx_erase(struct flash_bank_s *bank, int first, int last); -int pic32mx_protect(struct flash_bank_s *bank, int set, int first, int last); -int pic32mx_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count); -int pic32mx_probe(struct flash_bank_s *bank); -int pic32mx_auto_probe(struct flash_bank_s *bank); -int pic32mx_handle_part_id_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); -int pic32mx_protect_check(struct flash_bank_s *bank); -int pic32mx_info(struct flash_bank_s *bank, char *buf, int buf_size); - -#if 0 -int pic32mx_handle_lock_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); -int pic32mx_handle_unlock_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); -#endif -int pic32mx_handle_chip_erase_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); -int pic32mx_handle_pgm_word_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); -int pic32mx_chip_erase(struct flash_bank_s *bank); - -flash_driver_t pic32mx_flash = -{ - .name = "pic32mx", - .register_commands = pic32mx_register_commands, - .flash_bank_command = pic32mx_flash_bank_command, - .erase = pic32mx_erase, - .protect = pic32mx_protect, - .write = pic32mx_write, - .probe = pic32mx_probe, - .auto_probe = pic32mx_auto_probe, - .erase_check = default_flash_mem_blank_check, - .protect_check = pic32mx_protect_check, - .info = pic32mx_info -}; - -int pic32mx_register_commands(struct command_context_s *cmd_ctx) -{ - command_t *pic32mx_cmd = register_command(cmd_ctx, NULL, "pic32mx", NULL, COMMAND_ANY, "pic32mx flash specific commands"); - -#if 0 - register_command(cmd_ctx, pic32mx_cmd, "lock", pic32mx_handle_lock_command, COMMAND_EXEC, - "lock device"); - register_command(cmd_ctx, pic32mx_cmd, "unlock", pic32mx_handle_unlock_command, COMMAND_EXEC, - "unlock protected device"); -#endif - register_command(cmd_ctx, pic32mx_cmd, "chip_erase", pic32mx_handle_chip_erase_command, COMMAND_EXEC, - "erase device"); - register_command(cmd_ctx, pic32mx_cmd, "pgm_word", pic32mx_handle_pgm_word_command, COMMAND_EXEC, - "program a word"); - return ERROR_OK; -} - -/* flash bank pic32mx <base> <size> 0 0 <target#> - */ -int pic32mx_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank) -{ - pic32mx_flash_bank_t *pic32mx_info; - - if (argc < 6) - { - LOG_WARNING("incomplete flash_bank pic32mx configuration"); - return ERROR_FLASH_BANK_INVALID; - } - - pic32mx_info = malloc(sizeof(pic32mx_flash_bank_t)); - bank->driver_priv = pic32mx_info; - - pic32mx_info->write_algorithm = NULL; - pic32mx_info->probed = 0; - - return ERROR_OK; -} - -u32 pic32mx_get_flash_status(flash_bank_t *bank) -{ - target_t *target = bank->target; - u32 status; - - target_read_u32(target, PIC32MX_NVMCON, &status); - - return status; -} - -u32 pic32mx_wait_status_busy(flash_bank_t *bank, int timeout) -{ - u32 status; - - /* wait for busy to clear */ - while (((status = pic32mx_get_flash_status(bank)) & NVMCON_NVMWR) && (timeout-- > 0)) - { - LOG_DEBUG("status: 0x%x", status); - alive_sleep(1); - } - if(timeout <= 0) - LOG_DEBUG("timeout: status: 0x%x", status); - - return status; -} - -int pic32mx_nvm_exec(struct flash_bank_s *bank, u32 op, u32 timeout) -{ - target_t *target = bank->target; - u32 status; - - target_write_u32(target, PIC32MX_NVMCON, NVMCON_NVMWREN|op); - - /* unlock flash registers */ - target_write_u32(target, PIC32MX_NVMKEY, NVMKEY1); - target_write_u32(target, PIC32MX_NVMKEY, NVMKEY2); - - /* start operation */ - target_write_u32(target, PIC32MX_NVMCONSET, NVMCON_NVMWR); - - status = pic32mx_wait_status_busy(bank, timeout); - - /* lock flash registers */ - target_write_u32(target, PIC32MX_NVMCONCLR, NVMCON_NVMWREN); - - return status; -} - -int pic32mx_protect_check(struct flash_bank_s *bank) -{ - target_t *target = bank->target; - pic32mx_flash_bank_t *pic32mx_info = bank->driver_priv; - - u32 devcfg0; - int s; - int num_pages; - - if (target->state != TARGET_HALTED) - { - LOG_ERROR("Target not halted"); - return ERROR_TARGET_NOT_HALTED; - } - - target_read_u32(target, PIC32MX_DEVCFG0, &devcfg0); - if((devcfg0 & (1<<28)) == 0) /* code protect bit */ - num_pages = 0xffff; /* All pages protected */ - else if(bank->base == PIC32MX_KSEG1_BOOT_FLASH) - { - if(devcfg0 & (1<<24)) - num_pages = 0; /* All pages unprotected */ - else - num_pages = 0xffff; /* All pages protected */ - } - else /* pgm flash */ - num_pages = (~devcfg0 >> 12) & 0xff; - for (s = 0; s < bank->num_sectors && s < num_pages; s++) - bank->sectors[s].is_protected = 1; - for (; s < bank->num_sectors; s++) - bank->sectors[s].is_protected = 0; - - return ERROR_OK; -} - -int pic32mx_erase(struct flash_bank_s *bank, int first, int last) -{ - target_t *target = bank->target; - int i; - u32 status; - - if (bank->target->state != TARGET_HALTED) - { - LOG_ERROR("Target not halted"); - return ERROR_TARGET_NOT_HALTED; - } - -#if 0 - if ((first == 0) && (last == (bank->num_sectors - 1)) && (bank->base == PIC32MX_KSEG0_PGM_FLASH || bank->base == PIC32MX_KSEG1_PGM_FLASH)) - { - status = pic32mx_nvm_exec(bank, NVMCON_OP_PFM_ERASE, 50); - if( status & NVMCON_NVMERR ) - return ERROR_FLASH_OPERATION_FAILED; - if( status & NVMCON_LVDERR ) - return ERROR_FLASH_OPERATION_FAILED; - return ERROR_OK; - } -#endif - - for (i = first; i <= last; i++) - { - target_write_u32(target, PIC32MX_NVMADDR, bank->base + bank->sectors[i].offset); - - status = pic32mx_nvm_exec(bank, NVMCON_OP_PAGE_ERASE, 10); - - if( status & NVMCON_NVMERR ) - return ERROR_FLASH_OPERATION_FAILED; - if( status & NVMCON_LVDERR ) - return ERROR_FLASH_OPERATION_FAILED; - bank->sectors[i].is_erased = 1; - } - - return ERROR_OK; -} - -int pic32mx_protect(struct flash_bank_s *bank, int set, int first, int last) -{ - pic32mx_flash_bank_t *pic32mx_info = NULL; - target_t *target = bank->target; - u16 prot_reg[4] = {0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF}; - int i, reg, bit; - int status; - u32 protection; - - pic32mx_info = bank->driver_priv; - - if (target->state != TARGET_HALTED) - { - LOG_ERROR("Target not halted"); - return ERROR_TARGET_NOT_HALTED; - } - -#if 0 - if ((first && (first % pic32mx_info->ppage_size)) || ((last + 1) && (last + 1) % pic32mx_info->ppage_size)) - { - LOG_WARNING("sector start/end incorrect - stm32 has %dK sector protection", pic32mx_info->ppage_size); - return ERROR_FLASH_SECTOR_INVALID; - } - - /* medium density - each bit refers to a 4bank protection - * high density - each bit refers to a 2bank protection */ - target_read_u32(target, PIC32MX_FLASH_WRPR, &protection); - - prot_reg[0] = (u16)protection; - prot_reg[1] = (u16)(protection >> 8); - prot_reg[2] = (u16)(protection >> 16); - prot_reg[3] = (u16)(protection >> 24); - - if (pic32mx_info->ppage_size == 2) - { - /* high density flash */ - - /* bit 7 controls sector 62 - 255 protection */ - if (last > 61) - { - if (set) - prot_reg[3] &= ~(1 << 7); - else - prot_reg[3] |= (1 << 7); - } - - if (first > 61) - first = 62; - if (last > 61) - last = 61; - - for (i = first; i <= last; i++) - { - reg = (i / pic32mx_info->ppage_size) / 8; - bit = (i / pic32mx_info->ppage_size) - (reg * 8); - - if( set ) - prot_reg[reg] &= ~(1 << bit); - else - prot_reg[reg] |= (1 << bit); - } - } - else - { - /* medium density flash */ - for (i = first; i <= last; i++) - { - reg = (i / pic32mx_info->ppage_size) / 8; - bit = (i / pic32mx_info->ppage_size) - (reg * 8); - - if( set ) - prot_reg[reg] &= ~(1 << bit); - else - prot_reg[reg] |= (1 << bit); - } - } - - if ((status = pic32mx_erase_options(bank)) != ERROR_OK) - return status; - - pic32mx_info->option_bytes.protection[0] = prot_reg[0]; - pic32mx_info->option_bytes.protection[1] = prot_reg[1]; - pic32mx_info->option_bytes.protection[2] = prot_reg[2]; - pic32mx_info->option_bytes.protection[3] = prot_reg[3]; - - return pic32mx_write_options(bank); -#else - return ERROR_OK; -#endif -} - -int pic32mx_write_block(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count) -{ - pic32mx_flash_bank_t *pic32mx_info = bank->driver_priv; - target_t *target = bank->target; - u32 buffer_size = 8192; - working_area_t *source; - u32 address = bank->base + offset; - reg_param_t reg_params[4]; -#if 0 - armv7m_algorithm_t armv7m_info; - int retval = ERROR_OK; - - u8 pic32mx_flash_write_code[] = { - /* write: */ - 0xDF, 0xF8, 0x24, 0x40, /* ldr r4, PIC32MX_FLASH_CR */ - 0x09, 0x4D, /* ldr r5, PIC32MX_FLASH_SR */ - 0x4F, 0xF0, 0x01, 0x03, /* mov r3, #1 */ - 0x23, 0x60, /* str r3, [r4, #0] */ - 0x30, 0xF8, 0x02, 0x3B, /* ldrh r3, [r0], #2 */ - 0x21, 0xF8, 0x02, 0x3B, /* strh r3, [r1], #2 */ - /* busy: */ - 0x2B, 0x68, /* ldr r3, [r5, #0] */ - 0x13, 0xF0, 0x01, 0x0F, /* tst r3, #0x01 */ - 0xFB, 0xD0, /* beq busy */ - 0x13, 0xF0, 0x14, 0x0F, /* tst r3, #0x14 */ - 0x01, 0xD1, /* bne exit */ - 0x01, 0x3A, /* subs r2, r2, #1 */ - 0xED, 0xD1, /* bne write */ - /* exit: */ - 0xFE, 0xE7, /* b exit */ - 0x10, 0x20, 0x02, 0x40, /* PIC32MX_FLASH_CR: .word 0x40022010 */ - 0x0C, 0x20, 0x02, 0x40 /* PIC32MX_FLASH_SR: .word 0x4002200C */ - }; - - /* flash write code */ - if (target_alloc_working_area(target, sizeof(pic32mx_flash_write_code), &pic32mx_info->write_algorithm) != ERROR_OK) - { - LOG_WARNING("no working area available, can't do block memory writes"); - return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; - }; - - if ((retval=target_write_buffer(target, pic32mx_info->write_algorithm->address, sizeof(pic32mx_flash_write_code), pic32mx_flash_write_code))!=ERROR_OK) - return retval; - - /* memory buffer */ - while (target_alloc_working_area(target, buffer_size, &source) != ERROR_OK) - { - buffer_size /= 2; - if (buffer_size <= 256) - { - /* if we already allocated the writing code, but failed to get a buffer, free the algorithm */ - if (pic32mx_info->write_algorithm) - target_free_working_area(target, pic32mx_info->write_algorithm); - - LOG_WARNING("no large enough working area available, can't do block memory writes"); - return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; - } - }; - - armv7m_info.common_magic = ARMV7M_COMMON_MAGIC; - armv7m_info.core_mode = ARMV7M_MODE_ANY; - - init_reg_param(®_params[0], "r0", 32, PARAM_OUT); - init_reg_param(®_params[1], "r1", 32, PARAM_OUT); - init_reg_param(®_params[2], "r2", 32, PARAM_OUT); - init_reg_param(®_params[3], "r3", 32, PARAM_IN); - - while (count > 0) - { - u32 thisrun_count = (count > (buffer_size / 2)) ? (buffer_size / 2) : count; - - if ((retval = target_write_buffer(target, source->address, thisrun_count * 2, buffer))!=ERROR_OK) - break; - - buf_set_u32(reg_params[0].value, 0, 32, source->address); - buf_set_u32(reg_params[1].value, 0, 32, address); - buf_set_u32(reg_params[2].value, 0, 32, thisrun_count); - - if ((retval = target->type->run_algorithm(target, 0, NULL, 4, reg_params, pic32mx_info->write_algorithm->address, \ - pic32mx_info->write_algorithm->address + (sizeof(pic32mx_flash_write_code) - 10), 10000, &armv7m_info)) != ERROR_OK) - { - LOG_ERROR("error executing pic32mx flash write algorithm"); - retval = ERROR_FLASH_OPERATION_FAILED; - break; - } - - if (buf_get_u32(reg_params[3].value, 0, 32) & 0x14) - { - retval = ERROR_FLASH_OPERATION_FAILED; - break; - } - - buffer += thisrun_count * 2; - address += thisrun_count * 2; - count -= thisrun_count; - } - - target_free_working_area(target, source); - target_free_working_area(target, pic32mx_info->write_algorithm); - - destroy_reg_param(®_params[0]); - destroy_reg_param(®_params[1]); - destroy_reg_param(®_params[2]); - destroy_reg_param(®_params[3]); - - return retval; -#else - return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; -#endif -} - -int pic32mx_write_word(struct flash_bank_s *bank, u32 address, u32 word) -{ - target_t *target = bank->target; - - target_write_u32(target, PIC32MX_NVMADDR, address); - target_write_u32(target, PIC32MX_NVMDATA, word); - - return pic32mx_nvm_exec(bank, NVMCON_OP_WORD_PROG, 5); -} - -int pic32mx_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count) -{ - target_t *target = bank->target; - u32 words_remaining = (count / 4); - u32 bytes_remaining = (count & 0x00000003); - u32 address = bank->base + offset; - u32 bytes_written = 0; - u32 status; - u32 retval; - - if (bank->target->state != TARGET_HALTED) - { - LOG_ERROR("Target not halted"); - return ERROR_TARGET_NOT_HALTED; - } - - if (offset & 0x3) - { - LOG_WARNING("offset 0x%x breaks required 4-byte alignment", offset); - return ERROR_FLASH_DST_BREAKS_ALIGNMENT; - } - - /* multiple words (4-byte) to be programmed? */ - if (words_remaining > 0) - { - /* try using a block write */ - if ((retval = pic32mx_write_block(bank, buffer, offset, words_remaining)) != ERROR_OK) - { - if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) - { - /* if block write failed (no sufficient working area), - * we use normal (slow) single dword accesses */ - LOG_WARNING("couldn't use block writes, falling back to single memory accesses"); - } - else if (retval == ERROR_FLASH_OPERATION_FAILED) - { - LOG_ERROR("flash writing failed with error code: 0x%x", retval); - return ERROR_FLASH_OPERATION_FAILED; - } - } - else - { - buffer += words_remaining * 4; - address += words_remaining * 4; - words_remaining = 0; - } - } - - while (words_remaining > 0) - { - status = pic32mx_write_word(bank, address, *(u32*)(buffer + bytes_written)); - - if( status & NVMCON_NVMERR ) - return ERROR_FLASH_OPERATION_FAILED; - if( status & NVMCON_LVDERR ) - return ERROR_FLASH_OPERATION_FAILED; - - bytes_written += 4; - words_remaining--; - address += 4; - } - - if (bytes_remaining) - { - u8 last_word[4] = {0xff, 0xff, 0xff, 0xff}; - int i = 0; - - while(bytes_remaining > 0) - { - /* Assumes little endian */ - last_word[i++] = *(buffer + bytes_written); - bytes_remaining--; - bytes_written++; - } - - status = pic32mx_write_word(bank, address, *(u32*)last_word); - - if( status & NVMCON_NVMERR ) - return ERROR_FLASH_OPERATION_FAILED; - if( status & NVMCON_LVDERR ) - return ERROR_FLASH_OPERATION_FAILED; - } - - return ERROR_OK; -} - -int pic32mx_probe(struct flash_bank_s *bank) -{ - target_t *target = bank->target; - pic32mx_flash_bank_t *pic32mx_info = bank->driver_priv; - mips32_common_t *mips32 = target->arch_info; - mips_ejtag_t *ejtag_info = &mips32->ejtag_info; - int i; - u16 num_pages; - u32 device_id; - int page_size; - - pic32mx_info->probed = 0; - - device_id = ejtag_info->idcode; - LOG_INFO( "device id = 0x%08x (manuf 0x%03x dev 0x%02x, ver 0x%03x)", device_id, (device_id>>1)&0x7ff, (device_id>>12)&0xff, (device_id>>20)&0xfff ); - - if(((device_id>>1)&0x7ff) != PIC32MX_MANUF_ID) { - LOG_WARNING( "Cannot identify target as a PIC32MX family." ); - return ERROR_FLASH_OPERATION_FAILED; - } - - page_size = 4096; - if(bank->base == PIC32MX_KSEG1_BOOT_FLASH || bank->base == 1) { - /* 0xBFC00000: Boot flash size fixed at 12k */ - num_pages = 12; - } else { - /* 0xBD000000: Program flash size varies with device */ - for(i=0; pic32mx_devs[i].name != NULL; i++) - if(pic32mx_devs[i].devid == ((device_id >> 12) & 0xff)) { - num_pages = pic32mx_devs[i].pfm_size; - break; - } - if(pic32mx_devs[i].name == NULL) { - LOG_WARNING( "Cannot identify target as a PIC32MX family." ); - return ERROR_FLASH_OPERATION_FAILED; - } - } - -#if 0 - if (bank->target->state != TARGET_HALTED) - { - LOG_ERROR("Target not halted"); - return ERROR_TARGET_NOT_HALTED; - } - - /* get flash size from target */ - if (target_read_u16(target, 0x1FFFF7E0, &num_pages) != ERROR_OK) - { - /* failed reading flash size, default to max target family */ - num_pages = 0xffff; - } -#endif - - LOG_INFO( "flash size = %dkbytes", num_pages ); - - /* calculate numbers of pages */ - num_pages /= (page_size / 1024); - - if(bank->base == 0) bank->base = PIC32MX_KSEG1_PGM_FLASH; - if(bank->base == 1) bank->base = PIC32MX_KSEG1_BOOT_FLASH; - bank->size = (num_pages * page_size); - bank->num_sectors = num_pages; - bank->chip_width = 4; - bank->bus_width = 4; - bank->sectors = malloc(sizeof(flash_sector_t) * num_pages); - - for (i = 0; i < num_pages; i++) - { - bank->sectors[i].offset = i * page_size; - bank->sectors[i].size = page_size; - bank->sectors[i].is_erased = -1; - bank->sectors[i].is_protected = 1; - } - - pic32mx_info->probed = 1; - - return ERROR_OK; -} - -int pic32mx_auto_probe(struct flash_bank_s *bank) -{ - pic32mx_flash_bank_t *pic32mx_info = bank->driver_priv; - if (pic32mx_info->probed) - return ERROR_OK; - return pic32mx_probe(bank); -} - -int pic32mx_handle_part_id_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) -{ - return ERROR_OK; -} - -int pic32mx_info(struct flash_bank_s *bank, char *buf, int buf_size) -{ - target_t *target = bank->target; - mips32_common_t *mips32 = target->arch_info; - mips_ejtag_t *ejtag_info = &mips32->ejtag_info; - u32 device_id; - int printed, i; - - device_id = ejtag_info->idcode; - - if(((device_id>>1)&0x7ff) != PIC32MX_MANUF_ID) { - snprintf(buf, buf_size, "Cannot identify target as a PIC32MX family (manufacturer 0x%03d != 0x%03d)\n", (device_id>>1)&0x7ff, PIC32MX_MANUF_ID); - return ERROR_FLASH_OPERATION_FAILED; - } - for(i=0; pic32mx_devs[i].name != NULL; i++) - if(pic32mx_devs[i].devid == ((device_id >> 12) & 0xff)) { - printed = snprintf(buf, buf_size, "PIC32MX%s", pic32mx_devs[i].name); - break; - } - if(pic32mx_devs[i].name == NULL) { - snprintf(buf, buf_size, "Cannot identify target as a PIC32MX family\n"); - return ERROR_FLASH_OPERATION_FAILED; - } - buf += printed; - buf_size -= printed; - printed = snprintf(buf, buf_size, " Ver: 0x%03x", (device_id>>20)&0xfff); - - return ERROR_OK; -} - -#if 0 -int pic32mx_handle_lock_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) -{ - flash_bank_t *bank; - target_t *target = NULL; - pic32mx_flash_bank_t *pic32mx_info = NULL; - - if (argc < 1) - { - command_print(cmd_ctx, "pic32mx lock <bank>"); - return ERROR_OK; - } - - bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0)); - if (!bank) - { - command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]); - return ERROR_OK; - } - - pic32mx_info = bank->driver_priv; - - target = bank->target; - - if (target->state != TARGET_HALTED) - { - LOG_ERROR("Target not halted"); - return ERROR_TARGET_NOT_HALTED; - } - - if (pic32mx_erase_options(bank) != ERROR_OK) - { - command_print(cmd_ctx, "pic32mx failed to erase options"); - return ERROR_OK; - } - - /* set readout protection */ - pic32mx_info->option_bytes.RDP = 0; - - if (pic32mx_write_options(bank) != ERROR_OK) - { - command_print(cmd_ctx, "pic32mx failed to lock device"); - return ERROR_OK; - } - - command_print(cmd_ctx, "pic32mx locked"); - - return ERROR_OK; -} - -int pic32mx_handle_unlock_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) -{ - flash_bank_t *bank; - target_t *target = NULL; - pic32mx_flash_bank_t *pic32mx_info = NULL; - - if (argc < 1) - { - command_print(cmd_ctx, "pic32mx unlock <bank>"); - return ERROR_OK; - } - - bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0)); - if (!bank) - { - command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]); - return ERROR_OK; - } - - pic32mx_info = bank->driver_priv; - - target = bank->target; - - if (target->state != TARGET_HALTED) - { - LOG_ERROR("Target not halted"); - return ERROR_TARGET_NOT_HALTED; - } - - if (pic32mx_erase_options(bank) != ERROR_OK) - { - command_print(cmd_ctx, "pic32mx failed to unlock device"); - return ERROR_OK; - } - - if (pic32mx_write_options(bank) != ERROR_OK) - { - command_print(cmd_ctx, "pic32mx failed to lock device"); - return ERROR_OK; - } - - command_print(cmd_ctx, "pic32mx unlocked"); - - return ERROR_OK; -} -#endif - -int pic32mx_chip_erase(struct flash_bank_s *bank) -{ - target_t *target = bank->target; - u32 status; - - if (target->state != TARGET_HALTED) - { - LOG_ERROR("Target not halted"); - return ERROR_TARGET_NOT_HALTED; - } - - LOG_INFO("PIC32MX chip erase called"); - -#if 0 - /* unlock option flash registers */ - target_write_u32(target, PIC32MX_FLASH_KEYR, KEY1); - target_write_u32(target, PIC32MX_FLASH_KEYR, KEY2); - - /* chip erase flash memory */ - target_write_u32(target, PIC32MX_FLASH_CR, FLASH_MER); - target_write_u32(target, PIC32MX_FLASH_CR, FLASH_MER|FLASH_STRT); - - status = pic32mx_wait_status_busy(bank, 10); - - target_write_u32(target, PIC32MX_FLASH_CR, FLASH_LOCK); - - if( status & FLASH_WRPRTERR ) - { - LOG_ERROR("pic32mx device protected"); - return ERROR_OK; - } - - if( status & FLASH_PGERR ) - { - LOG_ERROR("pic32mx device programming failed"); - return ERROR_OK; - } -#endif - - return ERROR_OK; -} - -int pic32mx_handle_chip_erase_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) -{ - flash_bank_t *bank; - int i; - -#if 0 - if (argc != 0) - { - command_print(cmd_ctx, "pic32mx chip_erase"); - return ERROR_OK; - } - - bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0)); - if (!bank) - { - command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]); - return ERROR_OK; - } - - if (pic32mx_chip_erase(bank) == ERROR_OK) - { - /* set all sectors as erased */ - for (i = 0; i < bank->num_sectors; i++) - { - bank->sectors[i].is_erased = 1; - } - - command_print(cmd_ctx, "pic32mx chip erase complete"); - } - else - { - command_print(cmd_ctx, "pic32mx chip erase failed"); - } -#endif - - return ERROR_OK; -} - -int pic32mx_handle_pgm_word_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) -{ - flash_bank_t *bank; - u32 address, value; - int i; - int status, res; - - if (argc != 3) - { - command_print(cmd_ctx, "pic32mx pgm_word <addr> <value> <bank>"); - return ERROR_OK; - } - - address = strtoul(args[0], NULL, 0); - value = strtoul(args[1], NULL, 0); - - bank = get_flash_bank_by_num(strtoul(args[2], NULL, 0)); - if (!bank) - { - command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[2]); - return ERROR_OK; - } - if (address < bank->base || address >= (bank->base+bank->size)) - { - command_print(cmd_ctx, "flash address '%s' is out of bounds", args[0]); - return ERROR_OK; - } - - res = ERROR_OK; - status = pic32mx_write_word(bank, address, value); - if( status & NVMCON_NVMERR ) - res = ERROR_FLASH_OPERATION_FAILED; - if( status & NVMCON_LVDERR ) - res = ERROR_FLASH_OPERATION_FAILED; - - if (res == ERROR_OK) - command_print(cmd_ctx, "pic32mx pgm word complete"); - else - command_print(cmd_ctx, "pic32mx pgm word failed (status=0x%x)", status); - - return ERROR_OK; -} +/*************************************************************************** + * Copyright (C) 2005 by Dominic Rath * + * Dom...@gm... * + * * + * Copyright (C) 2008 by Spencer Oliver * + * sp...@sp... * + * * + * Copyright (C) 2008 by John McCarthy * + * jg...@ma... * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You 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. * + ***************************************************************************/ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "replacements.h" + +#include "pic32mx.h" +#include "flash.h" +#include "target.h" +#include "log.h" +#include "mips32.h" +#include "algorithm.h" +#include "binarybuffer.h" + +#include <stdlib.h> +#include <string.h> + +static +struct pic32mx_devs_s { + u8 devid; + char *name; + u32 pfm_size; +} pic32mx_devs[] = { + { 0x78, "460F512L USB", 512 }, + { 0x74, "460F256L USB", 256 }, + { 0x6D, "440F128L USB", 128 }, + { 0x56, "440F512H USB", 512 }, + { 0x52, "440F256H USB", 256 }, + { 0x4D, "440F128H USB", 128 }, + { 0x42, "420F032H USB", 32 }, + { 0x38, "360F512L", 512 }, + { 0x34, "360F256L", 256 }, + { 0x2D, "340F128L", 128 }, + { 0x2A, "320F128L", 128 }, + { 0x16, "340F512H", 512 }, + { 0x12, "340F256H", 256 }, + { 0x0D, "340F128H", 128 }, + { 0x0A, "320F128H", 128 }, + { 0x06, "320F064H", 64 }, + { 0x02, "320F032H", 32 }, + { 0x00, NULL, 0 } +}; + +int pic32mx_register_commands(struct command_context_s *cmd_ctx); +int pic32mx_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank); +int pic32mx_erase(struct flash_bank_s *bank, int first, int last); +int pic32mx_protect(struct flash_bank_s *bank, int set, int first, int last); +int pic32mx_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count); +int pic32mx_probe(struct flash_bank_s *bank); +int pic32mx_auto_probe(struct flash_bank_s *bank); +int pic32mx_handle_part_id_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); +int pic32mx_protect_check(struct flash_bank_s *bank); +int pic32mx_info(struct flash_bank_s *bank, char *buf, int buf_size); + +#if 0 +int pic32mx_handle_lock_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); +int pic32mx_handle_unlock_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); +#endif +int pic32mx_handle_chip_erase_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); +int pic32mx_handle_pgm_word_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); +int pic32mx_chip_erase(struct flash_bank_s *bank); + +flash_driver_t pic32mx_flash = +{ + .name = "pic32mx", + .register_commands = pic32mx_register_commands, + .flash_bank_command = pic32mx_flash_bank_command, + .erase = pic32mx_erase, + .protect = pic32mx_protect, + .write = pic32mx_write, + .probe = pic32mx_probe, + .auto_probe = pic32mx_auto_probe, + .erase_check = default_flash_mem_blank_check, + .protect_check = pic32mx_protect_check, + .info = pic32mx_info +}; + +int pic32mx_register_commands(struct command_context_s *cmd_ctx) +{ + command_t *pic32mx_cmd = register_command(cmd_ctx, NULL, "pic32mx", NULL, COMMAND_ANY, "pic32mx flash specific commands"); + +#if 0 + register_command(cmd_ctx, pic32mx_cmd, "lock", pic32mx_handle_lock_command, COMMAND_EXEC, + "lock device"); + register_command(cmd_ctx, pic32mx_cmd, "unlock", pic32mx_handle_unlock_command, COMMAND_EXEC, + "unlock protected device"); +#endif + register_command(cmd_ctx, pic32mx_cmd, "chip_erase", pic32mx_handle_chip_erase_command, COMMAND_EXEC, + "erase device"); + register_command(cmd_ctx, pic32mx_cmd, "pgm_word", pic32mx_handle_pgm_word_command, COMMAND_EXEC, + "program a word"); + return ERROR_OK; +} + +/* flash bank pic32mx <base> <size> 0 0 <target#> + */ +int pic32mx_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank) +{ + pic32mx_flash_bank_t *pic32mx_info; + + if (argc < 6) + { + LOG_WARNING("incomplete flash_bank pic32mx configuration"); + return ERROR_FLASH_BANK_INVALID; + } + + pic32mx_info = malloc(sizeof(pic32mx_flash_bank_t)); + bank->driver_priv = pic32mx_info; + + pic32mx_info->write_algorithm = NULL; + pic32mx_info->probed = 0; + + return ERROR_OK; +} + +u32 pic32mx_get_flash_status(flash_bank_t *bank) +{ + target_t *target = bank->target; + u32 status; + + target_read_u32(target, PIC32MX_NVMCON, &status); + + return status; +} + +u32 pic32mx_wait_status_busy(flash_bank_t *bank, int timeout) +{ + u32 status; + + /* wait for busy to clear */ + while (((status = pic32mx_get_flash_status(bank)) & NVMCON_NVMWR) && (timeout-- > 0)) + { + LOG_DEBUG("status: 0x%x", status); + alive_sleep(1); + } + if(timeout <= 0) + LOG_DEBUG("timeout: status: 0x%x", status); + + return status; +} + +int pic32mx_nvm_exec(struct flash_bank_s *bank, u32 op, u32 timeout) +{ + target_t *target = bank->target; + u32 status; + + target_write_u32(target, PIC32MX_NVMCON, NVMCON_NVMWREN|op); + + /* unlock flash registers */ + target_write_u32(target, PIC32MX_NVMKEY, NVMKEY1); + target_write_u32(target, PIC32MX_NVMKEY, NVMKEY2); + + /* start operation */ + target_write_u32(target, PIC32MX_NVMCONSET, NVMCON_NVMWR); + + status = pic32mx_wait_status_busy(bank, timeout); + + /* lock flash registers */ + target_write_u32(target, PIC32MX_NVMCONCLR, NVMCON_NVMWREN); + + return status; +} + +int pic32mx_protect_check(struct flash_bank_s *bank) +{ + target_t *target = bank->target; + pic32mx_flash_bank_t *pic32mx_info = bank->driver_priv; + + u32 devcfg0; + int s; + int num_pages; + + if (target->state != TARGET_HALTED) + { + LOG_ERROR("Target not halted"); + return ERROR_TARGET_NOT_HALTED; + } + + target_read_u32(target, PIC32MX_DEVCFG0, &devcfg0); + if((devcfg0 & (1<<28)) == 0) /* code protect bit */ + num_pages = 0xffff; /* All pages protected */ + else if(bank->base == PIC32MX_KSEG1_BOOT_FLASH) + { + if(devcfg0 & (1<<24)) + num_pages = 0; /* All pages unprotected */ + else + num_pages = 0xffff; /* All pages protected */ + } + else /* pgm flash */ + num_pages = (~devcfg0 >> 12) & 0xff; + for (s = 0; s < bank->num_sectors && s < num_pages; s++) + bank->sectors[s].is_protected = 1; + for (; s < bank->num_sectors; s++) + bank->sectors[s].is_protected = 0; + + return ERROR_OK; +} + +int pic32mx_erase(struct flash_bank_s *bank, int first, int last) +{ + target_t *target = bank->target; + int i; + u32 status; + + if (bank->target->state != TARGET_HALTED) + { + LOG_ERROR("Target not halted"); + return ERROR_TARGET_NOT_HALTED; + } + +#if 0 + if ((first == 0) && (last == (bank->num_sectors - 1)) && (bank->base == PIC32MX_KSEG0_PGM_FLASH || bank->base == PIC32MX_KSEG1_PGM_FLASH)) + { + status = pic32mx_nvm_exec(bank, NVMCON_OP_PFM_ERASE, 50); + if( status & NVMCON_NVMERR ) + return ERROR_FLASH_OPERATION_FAILED; + if( status & NVMCON_LVDERR ) + return ERROR_FLASH_OPERATION_FAILED; + return ERROR_OK; + } +#endif + + for (i = first; i <= last; i++) + { + target_write_u32(target, PIC32MX_NVMADDR, bank->base + bank->sectors[i].offset); + + status = pic32mx_nvm_exec(bank, NVMCON_OP_PAGE_ERASE, 10); + + if( status & NVMCON_NVMERR ) + return ERROR_FLASH_OPERATION_FAILED; + if( status & NVMCON_LVDERR ) + return ERROR_FLASH_OPERATION_FAILED; + bank->sectors[i].is_erased = 1; + } + + return ERROR_OK; +} + +int pic32mx_protect(struct flash_bank_s *bank, int set, int first, int last) +{ + pic32mx_flash_bank_t *pic32mx_info = NULL; + target_t *target = bank->target; + u16 prot_reg[4] = {0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF}; + int i, reg, bit; + int status; + u32 protection; + + pic32mx_info = bank->driver_priv; + + if (target->state != TARGET_HALTED) + { + LOG_ERROR("Target not halted"); + return ERROR_TARGET_NOT_HALTED; + } + +#if 0 + if ((first && (first % pic32mx_info->ppage_size)) || ((last + 1) && (last + 1) % pic32mx_info->ppage_size)) + { + LOG_WARNING("sector start/end incorrect - stm32 has %dK sector protection", pic32mx_info->ppage_size); + return ERROR_FLASH_SECTOR_INVALID; + } + + /* medium density - each bit refers to a 4bank protection + * high density - each bit refers to a 2bank protection */ + target_read_u32(target, PIC32MX_FLASH_WRPR, &protection); + + prot_reg[0] = (u16)protection; + prot_reg[1] = (u16)(protection >> 8); + prot_reg[2] = (u16)(protection >> 16); + prot_reg[3] = (u16)(protection >> 24); + + if (pic32mx_info->ppage_size == 2) + { + /* high density flash */ + + /* bit 7 controls sector 62 - 255 protection */ + if (last > 61) + { + if (set) + prot_reg[3] &= ~(1 << 7); + else + prot_reg[3] |= (1 << 7); + } + + if (first > 61) + first = 62; + if (last > 61) + last = 61; + + for (i = first; i <= last; i++) + { + reg = (i / pic32mx_info->ppage_size) / 8; + bit = (i / pic32mx_info->ppage_size) - (reg * 8); + + if( set ) + prot_reg[reg] &= ~(1 << bit); + else + prot_reg[reg] |= (1 << bit); + } + } + else + { + /* medium density flash */ + for (i = first; i <= last; i++) + { + reg = (i / pic32mx_info->ppage_size) / 8; + bit = (i / pic32mx_info->ppage_size) - (reg * 8); + + if( set ) + prot_reg[reg] &= ~(1 << bit); + else + prot_reg[reg] |= (1 << bit); + } + } + + if ((status = pic32mx_erase_options(bank)) != ERROR_OK) + return status; + + pic32mx_info->option_bytes.protection[0] = prot_reg[0]; + pic32mx_info->option_bytes.protection[1] = prot_reg[1]; + pic32mx_info->option_bytes.protection[2] = prot_reg[2]; + pic32mx_info->option_bytes.protection[3] = prot_reg[3]; + + return pic32mx_write_options(bank); +#else + return ERROR_OK; +#endif +} + +int pic32mx_write_block(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count) +{ + pic32mx_flash_bank_t *pic32mx_info = bank->driver_priv; + target_t *target = bank->target; + u32 buffer_size = 8192; + working_area_t *source; + u32 address = bank->base + offset; + reg_param_t reg_params[4]; +#if 0 + armv7m_algorithm_t armv7m_info; + int retval = ERROR_OK; + + u8 pic32mx_flash_write_code[] = { + /* write: */ + 0xDF, 0xF8, 0x24, 0x40, /* ldr r4, PIC32MX_FLASH_CR */ + 0x09, 0x4D, /* ldr r5, PIC32MX_FLASH_SR */ + 0x4F, 0xF0, 0x01, 0x03, /* mov r3, #1 */ + 0x23, 0x60, /* str r3, [r4, #0] */ + 0x30, 0xF8, 0x02, 0x3B, /* ldrh r3, [r0], #2 */ + 0x21, 0xF8, 0x02, 0x3B, /* strh r3, [r1], #2 */ + /* busy: */ + 0x2B, 0x68, /* ldr r3, [r5, #0] */ + 0x13, 0xF0, 0x01, 0x0F, /* tst r3, #0x01 */ + 0xFB, 0xD0, /* beq busy */ + 0x13, 0xF0, 0x14, 0x0F, /* tst r3, #0x14 */ + 0x01, 0xD1, /* bne exit */ + 0x01, 0x3A, /* subs r2, r2, #1 */ + 0xED, 0xD1, /* bne write */ + /* exit: */ + 0xFE, 0xE7, /* b exit */ + 0x10, 0x20, 0x02, 0x40, /* PIC32MX_FLASH_CR: .word 0x40022010 */ + 0x0C, 0x20, 0x02, 0x40 /* PIC32MX_FLASH_SR: .word 0x4002200C */ + }; + + /* flash write code */ + if (target_alloc_working_area(target, sizeof(pic32mx_flash_write_code), &pic32mx_info->write_algorithm) != ERROR_OK) + { + LOG_WARNING("no working area available, can't do block memory writes"); + return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; + }; + + if ((retval=target_write_buffer(target, pic32mx_info->write_algorithm->address, sizeof(pic32mx_flash_write_code), pic32mx_flash_write_code))!=ERROR_OK) + return retval; + + /* memory buffer */ + while (target_alloc_working_area(target, buffer_size, &source) != ERROR_OK) + { + buffer_size /= 2; + if (buffer_size <= 256) + { + /* if we already allocated the writing code, but failed to get a buffer, free the algorithm */ + if (pic32mx_info->write_algorithm) + target_free_working_area(target, pic32mx_info->write_algorithm); + + LOG_WARNING("no large enough working area available, can't do block memory writes"); + return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; + } + }; + + armv7m_info.common_magic = ARMV7M_COMMON_MAGIC; + armv7m_info.core_mode = ARMV7M_MODE_ANY; + + init_reg_param(®_params[0], "r0", 32, PARAM_OUT); + init_reg_param(®_params[1], "r1", 32, PARAM_OUT); + init_reg_param(®_params[2], "r2", 32, PARAM_OUT); + init_reg_param(®_params[3], "r3", 32, PARAM_IN); + + while (count > 0) + { + u32 thisrun_count = (count > (buffer_size / 2)) ? (buffer_size / 2) : count; + + if ((retval = target_write_buffer(target, source->address, thisrun_count * 2, buffer))!=ERROR_OK) + break; + + buf_set_u32(reg_params[0].value, 0, 32, source->address); + buf_set_u32(reg_params[1].value, 0, 32, address); + buf_set_u32(reg_params[2].value, 0, 32, thisrun_count); + + if ((retval = target->type->run_algorithm(target, 0, NULL, 4, reg_params, pic32mx_info->write_algorithm->address, \ + pic32mx_info->write_algorithm->address + (sizeof(pic32mx_flash_write_code) - 10), 10000, &armv7m_info)) != ERROR_OK) + { + LOG_ERROR("error executing pic32mx flash write algorithm"); + retval = ERROR_FLASH_OPERATION_FAILED; + break; + } + + if (buf_get_u32(reg_params[3].value, 0, 32) & 0x14) + { + retval = ERROR_FLASH_OPERATION_FAILED; + break; + } + + buffer += thisrun_count * 2; + address += thisrun_count * 2; + count -= thisrun_count; + } + + target_free_working_area(target, source); + target_free_working_area(target, pic32mx_info->write_algorithm); + + destroy_reg_param(®_params[0]); + destroy_reg_param(®_params[1]); + destroy_reg_param(®_params[2]); + destroy_reg_param(®_params[3]); + + return retval; +#else + return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; +#endif +} + +int pic32mx_write_word(struct flash_bank_s *bank, u32 address, u32 word) +{ + target_t *target = bank->target; + + target_write_u32(target, PIC32MX_NVMADDR, address); + target_write_u32(target, PIC32MX_NVMDATA, word); + + return pic32mx_nvm_exec(bank, NVMCON_OP_WORD_PROG, 5); +} + +int pic32mx_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count) +{ + target_t *target = bank->target; + u32 words_remaining = (count / 4); + u32 bytes_remaining = (count & 0x00000003); + u32 address = bank->base + offset; + u32 bytes_written = 0; + u32 status; + u32 retval; + + if (bank->target->state != TARGET_HALTED) + { + LOG_ERROR("Target not halted"); + return ERROR_TARGET_NOT_HALTED; + } + + if (offset & 0x3) + { + LOG_WARNING("offset 0x%x breaks required 4-byte alignment", offset); + return ERROR_FLASH_DST_BREAKS_ALIGNMENT; + } + + /* multiple words (4-byte) to be programmed? */ + if (words_remaining > 0) + { + /* try using a block write */ + if ((retval = pic32mx_write_block(bank, buffer, offset, words_remaining)) != ERROR_OK) + { + if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) + { + /* if block write failed (no sufficient working area), + * we use normal (slow) single dword accesses */ + LOG_WARNING("couldn't use block writes, falling back to single memory accesses"); + } + else if (retval == ERROR_FLASH_OPERATION_FAILED) + { + LOG_ERROR("flash writing failed with error code: 0x%x", retval); + return ERROR_FLASH_OPERATION_FAILED; + } + } + else + { + buffer += words_remaining * 4; + address += words_remaining * 4; + words_remaining = 0; + } + } + + while (words_remaining > 0) + { + status = pic32mx_write_word(bank, address, *(u32*)(buffer + bytes_written)); + + if( status & NVMCON_NVMERR ) + return ERROR_FLASH_OPERATION_FAILED; + if( status & NVMCON_LVDERR ) + return ERROR_FLASH_OPERATION_FAILED; + + bytes_written += 4; + words_remaining--; + address += 4; + } + + if (bytes_remaining) + { + u8 last_word[4] = {0xff, 0xff, 0xff, 0xff}; + int i = 0; + + while(bytes_remaining > 0) + { + /* Assumes little endian */ + last_word[i++] = *(buffer + bytes_written); + bytes_remaining--; + bytes_written++; + } + + status = pic32mx_write_word(bank, address, *(u32*)last_word); + + if( status & NVMCON_NVMERR ) + return ERROR_FLASH_OPERATION_FAILED; + if( status & NVMCON_LVDERR ) + return ERROR_FLASH_OPERATION_FAILED; + } + + return ERROR_OK; +} + +int pic32mx_probe(struct flash_bank_s *bank) +{ + target_t *target = bank->target; + pic32mx_flash_bank_t *pic32mx_info = bank->driver_priv; + mips32_common_t *mips32 = target->arch_info; + mips_ejtag_t *ejtag_info = &mips32->ejtag_info; + int i; + u16 num_pages; + u32 device_id; + int page_size; + + pic32mx_info->probed = 0; + + device_id = ejtag_info->idcode; + LOG_INFO( "device id = 0x%08x (manuf 0x%03x dev 0x%02x, ver 0x%03x)", device_id, (device_id>>1)&0x7ff, (device_id>>12)&0xff, (device_id>>20)&0xfff ); + + if(((device_id>>1)&0x7ff) != PIC32MX_MANUF_ID) { + LOG_WARNING( "Cannot identify target as a PIC32MX family." ); + return ERROR_FLASH_OPERATION_FAILED; + } + + page_size = 4096; + if(bank->base == PIC32MX_KSEG1_BOOT_FLASH || bank->base == 1) { + /* 0xBFC00000: Boot flash size fixed at 12k */ + num_pages = 12; + } else { + /* 0xBD000000: Program flash size varies with device */ + for(i=0; pic32mx_devs[i].name != NULL; i++) + if(pic32mx_devs[i].devid == ((device_id >> 12) & 0xff)) { + num_pages = pic32mx_devs[i].pfm_size; + break; + } + if(pic32mx_devs[i].name == NULL) { + LOG_WARNING( "Cannot identify target as a PIC32MX family." ); + return ERROR_FLASH_OPERATION_FAILED; + } + } + +#if 0 + if (bank->target->state != TARGET_HALTED) + { + LOG_ERROR("Target not halted"); + return ERROR_TARGET_NOT_HALTED; + } + + /* get flash size from target */ + if (target_read_u16(target, 0x1FFFF7E0, &num_pages) != ERROR_OK) + { + /* failed reading flash size, default to max target family */ + num_pages = 0xffff; + } +#endif + + LOG_INFO( "flash size = %dkbytes", num_pages ); + + /* calculate numbers of pages */ + num_pages /= (page_size / 1024); + + if(bank->base == 0) bank->base = PIC32MX_KSEG1_PGM_FLASH; + if(bank->base == 1) bank->base = PIC32MX_KSEG1_BOOT_FLASH; + bank->size = (num_pages * page_size); + bank->num_sectors = num_pages; + bank->chip_width = 4; + bank->bus_width = 4; + bank->sectors = malloc(sizeof(flash_sector_t) * num_pages); + + for (i = 0; i < num_pages; i++) + { + bank->sectors[i].offset = i * page_size; + bank->sectors[i].size = page_size; + bank->sectors[i].is_erased = -1; + bank->sectors[i].is_protected = 1; + } + + pic32mx_info->probed = 1; + + return ERROR_OK; +} + +int pic32mx_auto_probe(struct flash_bank_s *bank) +{ + pic32mx_flash_bank_t *pic32mx_info = bank->driver_priv; + if (pic32mx_info->probed) + return ERROR_OK; + return pic32mx_probe(bank); +} + +int pic32mx_handle_part_id_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) +{ + return ERROR_OK; +} + +int pic32mx_info(struct flash_bank_s *bank, char *buf, int buf_size) +{ + target_t *target = bank->target; + mips32_common_t *mips32 = target->arch_info; + mips_ejtag_t *ejtag_info = &mips32->ejtag_info; + u32 device_id; + int printed, i; + + device_id = ejtag_info->idcode; + + if(((device_id>>1)&0x7ff) != PIC32MX_MANUF_ID) { + snprintf(buf, buf_size, "Cannot identify target as a PIC32MX family (manufacturer 0x%03d != 0x%03d)\n", (device_id>>1)&0x7ff, PIC32MX_MANUF_ID); + return ERROR_FLASH_OPERATION_FAILED; + } + for(i=0; pic32mx_devs[i].name != NULL; i++) + if(pic32mx_devs[i].devid == ((device_id >> 12) & 0xff)) { + printed = snprintf(buf, buf_size, "PIC32MX%s", pic32mx_devs[i].name); + break; + } + if(pic32mx_devs[i].name == NULL) { + snprintf(buf, buf_size, "Cannot identify target as a PIC32MX family\n"); + return ERROR_FLASH_OPERATION_FAILED; + } + buf += printed; + buf_size -= printed; + printed = snprintf(buf, buf_size, " Ver: 0x%03x", (device_id>>20)&0xfff); + + return ERROR_OK; +} + +#if 0 +int pic32mx_handle_lock_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) +{ + flash_bank_t *bank; + target_t *target = NULL; + pic32mx_flash_bank_t *pic32mx_info = NULL; + + if (argc < 1) + { + command_print(cmd_ctx, "pic32mx lock <bank>"); + return ERROR_OK; + } + + bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0)); + if (!bank) + { + command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]); + return ERROR_OK; + } + + pic32mx_info = bank->driver_priv; + + target = bank->target; + + if (target->state != TARGET_HALTED) + { + LOG_ERROR("Target not halted"); + return ERROR_TARGET_NOT_HALTED; + } + + if (pic32mx_erase_options(bank) != ERROR_OK) + { + command_print(cmd_ctx, "pic32mx failed to erase options"); + return ERROR_OK; + } + + /* set readout protection */ + pic32mx_info->option_bytes.RDP = 0; + + if (pic32mx_write_options(bank) != ERROR_OK) + { + command_print(cmd_ctx, "pic32mx failed to lock device"); + return ERROR_OK; + } + + command_print(cmd_ctx, "pic32mx locked"); + + return ERROR_OK; +} + +int pic32mx_handle_unlock_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) +{ + flash_bank_t *bank; + target_t *target = NULL; + pic32mx_flash_bank_t *pic32mx_info = NULL; + + if (argc < 1) + { + command_print(cmd_ctx, "pic32mx unlock <bank>"); + return ERROR_OK; + } + + bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0)); + if (!bank) + { + command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]); + return ERROR_OK; + } + + pic32mx_info = bank->driver_priv; + + target = bank->target; + + if (target->state != TARGET_HALTED) + { + LOG_ERROR("Target not halted"); + return ERROR_TARGET_NOT_HALTED; + } + + if (pic32mx_erase_options(bank) != ERROR_OK) + { + command_print(cmd_ctx, "pic32mx failed to unlock device"); + return ERROR_OK; + } + + if (pic32mx_write_options(bank) != ERROR_OK) + { + command_print(cmd_ctx, "pic32mx failed to lock device"); + return ERROR_OK; + } + + command_print(cmd_ctx, "pic32mx unlocked"); + + return ERROR_OK; +} +#endif + +int pic32mx_chip_erase(struct flash_bank_s *bank) +{ + target_t *target = bank->target; + u32 status; + + if (target->state != TARGET_HALTED) + { + LOG_ERROR("Target not halted"); + return ERROR_TARGET_NOT_HALTED; + } + + LOG_INFO("PIC32MX chip erase called"); + +#if 0 + /* unlock option flash registers */ + target_write_u32(target, PIC32MX_FLASH_KEYR, KEY1); + target_write_u32(target, PIC32MX_FLASH_KEYR, KEY2); + + /* chip erase flash memory */ + target_write_u32(target, PIC32MX_FLASH_CR, FLASH_MER); + target_write_u32(target, PIC32MX_FLASH_CR, FLASH_MER|FLASH_STRT); + + status = pic32mx_wait_status_busy(bank, 10); + + target_write_u32(target, PIC32MX_FLASH_CR, FLASH_LOCK); + + if( status & FLASH_WRPRTERR ) + { + LOG_ERROR("pic32mx device protected"); + return ERROR_OK; + } + + if( status & FLASH_PGERR ) + { + LOG_ERROR("pic32mx device programming failed"); + return ERROR_OK; + } +#endif + + return ERROR_OK; +} + +int pic32mx_handle_chip_erase_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) +{ + flash_bank_t *bank; + int i; + +#if 0 + if (argc != 0) + { + command_print(cmd_ctx, "pic32mx chip_erase"); + return ERROR_OK; + } + + bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0)); + if (!bank) + { + command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]); + return ERROR_OK; + } + + if (pic32mx_chip_erase(bank) == ERROR_OK) + { + /* set all sectors as erased */ + for (i = 0; i < bank->num_sectors; i++) + { + bank->sectors[i].is_erased = 1; + } + + command_print(cmd_ctx, "pic32mx chip erase complete"); + } + else + { + command_print(cmd_ctx, "pic32mx chip erase failed"); + } +#endif + + return ERROR_OK; +} + +int pic32mx_handle_pgm_word_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) +{ + flash_bank_t *bank; + u32 address, value; + int i; + int status, res; + + if (argc != 3) + { + command_print(cmd_ctx, "pic32mx pgm_word <addr> <value> <bank>"); + return ERROR_OK; + } + + address = strtoul(args[0], NULL, 0); + value = strtoul(args[1], NULL, 0); + + bank = get_flash_bank_by_num(strtoul(args[2], NULL, 0)); + if (!bank) + { + command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[2]); + return ERROR_OK; + } + if (address < bank->base || address >= (bank->base+bank->size)) + { + command_print(cmd_ctx, "flash address '%s' is out of bounds", args[0]); + return ERROR_OK; + } + + res = ERROR_OK; + status = pic32mx_write_word(bank, address, value); + if( status & NVMCON_NVMERR ) + res = ERROR_FLASH_OPERATION_FAILED; + if( status & NVMCON_LVDERR ) + res = ERROR_FLASH_OPERATION_FAILED; + + if (res == ERROR_OK) + command_print(cmd_ctx, "pic32mx pgm word complete"); + else + command_print(cmd_ctx, "pic32mx pgm word failed (status=0x%x)", status); + + return ERROR_OK; +} Property changes on: trunk/src/flash/pic32mx.c ___________________________________________________________________ Name: svn:eol-style + native Modified: trunk/src/flash/pic32mx.h =================================================================== --- trunk/src/flash/pic32mx.h 2009-01-02 23:58:16 UTC (rev 1296) +++ trunk/src/flash/pic32mx.h 2009-01-03 08:56:52 UTC (rev 1297) @@ -1,105 +1,105 @@ -/*************************************************************************** - * Copyright (C) 2005 by Dominic Rath * - * Dom...@gm... * - * * - * Copyright (C) 2008 by Spencer Oliver * - * sp...@sp... * - * * - * Copyright (C) 2008 by John McCarthy * - * jg...@ma... * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You 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. * - ***************************************************************************/ -#ifndef PIC32MX_H -#define PIC32MX_H - -#include "flash.h" -#include "target.h" - -typedef struct pic32mx_flash_bank_s -{ - working_area_t *write_algorithm; - int devid; - int ppage_size; - int probed; -} pic32mx_flash_bank_t; - -#define PIC32MX_MANUF_ID 0x029 - -/* pic32mx memory locations */ - -#define PIC32MX_KUSEG_PGM_FLASH 0x7D000000 -#define PIC32MX_KUSEG_RAM 0x7F000000 - -#define PIC32MX_KSEG0_RAM 0x80000000 -#define PIC32MX_KSEG0_PGM_FLASH 0x9D000000 -#define PIC32MX_KSEG0_BOOT_FLASH 0x9FC00000 - -#define PIC32MX_KSEG1_RAM 0xA0000000 -#define PIC32MX_KSEG1_PGM_FLASH 0xBD000000 -#define PIC32MX_KSEG1_PERIPHERAL 0xBF800000 -#define PIC32MX_KSEG1_BOOT_FLASH 0xBFC00000 - -#define PIC32MX_PHYS_RAM 0x00000000 -#define PIC32MX_PHYS_PGM_FLASH 0x1D000000 -#define PIC32MX_PHYS_PERIPHERALS 0x1F800000 -#define PIC32MX_PHYS_BOOT_FLASH 0x1FC00000 - -/* pic32mx configuration register locations */ - -#define PIC32MX_DEVCFG0 0xBFC02FFC -#define PIC32MX_DEVCFG1 0xBFC02FF8 -#define PIC32MX_DEVCFG2 0xBFC02FF4 -#define PIC32MX_DEVCFG3 0XBFC02FF0 -#define PIC32MX_DEVID 0xBF80F220 - -/* pic32mx flash controller register locations */ - -#define PIC32MX_NVMCON 0xBF80F400 -#define PIC32MX_NVMCONCLR 0xBF80F404 -#define PIC32MX_NVMCONSET 0xBF80F408 -#define PIC32MX_NVMCONINV 0xBF80F40C -#define NVMCON_NVMWR (1<<15) -#define NVMCON_NVMWREN (1<<14) -#define NVMCON_NVMERR (1<<13) -#define NVMCON_LVDERR (1<<12) -#define NVMCON_LVDSTAT (1<<11) -#define NVMCON_OP_PFM_ERASE 0x5 -#define NVMCON_OP_PAGE_ERASE 0x4 -#define NVMCON_OP_ROW_PROG 0x3 -#define NVMCON_OP_WORD_PROG 0x1 -#define NVMCON_OP_NOP 0x0 - -#define PIC32MX_NVMKEY 0xBF80F410 -#define PIC32MX_NVMADDR 0xBF80F420 -#define PIC32MX_NVMADDRCLR 0xBF80F424 -#define PIC32MX_NVMADDRSET 0xBF80F428 -#define PIC32MX_NVMADDRINV 0xBF80F42C -#define PIC32MX_NVMDATA 0xBF80F430 -#define PIC32MX_NVMSRCADDR 0xBF80F440 - -/* flash unlock keys */ - -#define NVMKEY1 0xAA996655 -#define NVMKEY2 0x556699AA - -typedef struct pic32mx_mem_layout_s { - u32 sector_start; - u32 sector_size; -} pic32mx_mem_layout_t; - -#endif /* PIC32MX_H */ - +/*************************************************************************** + * Copyright (C) 2005 by Dominic Rath * + * Dom...@gm... * + * * + * Copyright (C) 2008 by Spencer Oliver * + * sp...@sp... * + * * + * Copyright (C) 2008 by John McCarthy * + * jg...@ma... * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You 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. * + ***************************************************************************/ +#ifndef PIC32MX_H +#define PIC32MX_H + +#include "flash.h" +#include "target.h" + +typedef struct pic32mx_flash_bank_s +{ + working_area_t *write_algorithm; + int devid; + int ppage_size; + int probed; +} pic32mx_flash_bank_t; + +#define PIC32MX_MANUF_ID 0x029 + +/* pic32mx memory locations */ + +#define PIC32MX_KUSEG_PGM_FLASH 0x7D000000 +#define PIC32MX_KUSEG_RAM 0x7F000000 + +#define PIC32MX_KSEG0_RAM 0x80000000 +#define PIC32MX_KSEG0_PGM_FLASH 0x9D000000 +#define PIC32MX_KSEG0_BOOT_FLASH 0x9FC00000 + +#define PIC32MX_KSEG1_RAM 0xA0000000 +#define PIC32MX_KSEG1_PGM_FLASH 0xBD000000 +#define PIC32MX_KSEG1_PERIPHERAL 0xBF800000 +#define PIC32MX_KSEG1_BOOT_FLASH 0xBFC00000 + +#define PIC32MX_PHYS_RAM 0x00000000 +#define PIC32MX_PHYS_PGM_FLASH 0x1D000000 +#define PIC32MX_PHYS_PERIPHERALS 0x1F800000 +#define PIC32MX_PHYS_BOOT_FLASH 0x1FC00000 + +/* pic32mx configuration register locations */ + +#define PIC32MX_DEVCFG0 0xBFC02FFC +#define PIC32MX_DEVCFG1 0xBFC02FF8 +#define PIC32MX_DEVCFG2 0xBFC02FF4 +#define PIC32MX_DEVCFG3 0XBFC02FF0 +#define PIC32MX_DEVID 0xBF80F220 + +/* pic32mx flash controller register locations */ + +#define PIC32MX_NVMCON 0xBF80F400 +#define PIC32MX_NVMCONCLR 0xBF80F404 +#define PIC32MX_NVMCONSET 0xBF80F408 +#define PIC32MX_NVMCONINV 0xBF80F40C +#define NVMCON_NVMWR (1<<15) +#define NVMCON_NVMWREN (1<<14) +#define NVMCON_NVMERR (1<<13) +#define NVMCON_LVDERR (1<<12) +#define NVMCON_LVDSTAT (1<<11) +#define NVMCON_OP_PFM_ERASE 0x5 +#define NVMCON_OP_PAGE_ERASE 0x4 +#define NVMCON_OP_ROW_PROG 0x3 +#define NVMCON_OP_WORD_PROG 0x1 +#define NVMCON_OP_NOP 0x0 + +#define PIC32MX_NVMKEY 0xBF80F410 +#define PIC32MX_NVMADDR 0xBF80F420 +#define PIC32MX_NVMADDRCLR 0xBF80F424 +#define PIC32MX_NVMADDRSET 0xBF80F428 +#define PIC32MX_NVMADDRI... [truncated message content] |
From: <oh...@ma...> - 2009-01-03 00:58:24
|
Author: oharboe Date: 2009-01-03 00:58:16 +0100 (Sat, 03 Jan 2009) New Revision: 1296 Added: trunk/src/flash/pic32mx.c trunk/src/flash/pic32mx.h trunk/src/target/board/pic-p32mx.cfg Modified: trunk/src/flash/Makefile.am trunk/src/flash/flash.c trunk/src/target/mips_ejtag.h trunk/src/target/mips_m4k.c trunk/src/target/target/pic32mx.cfg Log: John McCarthy <jg...@ma...> pic32mx flash wip Modified: trunk/src/flash/Makefile.am =================================================================== --- trunk/src/flash/Makefile.am 2009-01-02 23:52:46 UTC (rev 1295) +++ trunk/src/flash/Makefile.am 2009-01-02 23:58:16 UTC (rev 1296) @@ -4,7 +4,7 @@ noinst_LIBRARIES = libflash.a libflash_a_SOURCES = flash.c lpc2000.c cfi.c non_cfi.c at91sam7.c at91sam7_old.c str7x.c str9x.c aduc702x.c nand.c lpc3180_nand_controller.c \ stellaris.c str9xpec.c stm32x.c tms470.c ecos.c \ - s3c24xx_nand.c s3c2410_nand.c s3c2412_nand.c s3c2440_nand.c s3c2443_nand.c lpc288x.c ocl.c mflash.c + s3c24xx_nand.c s3c2410_nand.c s3c2412_nand.c s3c2440_nand.c s3c2443_nand.c lpc288x.c ocl.c mflash.c pic32mx.c noinst_HEADERS = flash.h lpc2000.h cfi.h non_cfi.h at91sam7.h at91sam7_old.h str7x.h str9x.h nand.h lpc3180_nand_controller.h \ stellaris.h str9xpec.h stm32x.h tms470.h s3c24xx_nand.h s3c24xx_regs_nand.h lpc288x.h mflash.h \ - ocl.h + ocl.h pic32mx.h Modified: trunk/src/flash/flash.c =================================================================== --- trunk/src/flash/flash.c 2009-01-02 23:52:46 UTC (rev 1295) +++ trunk/src/flash/flash.c 2009-01-02 23:58:16 UTC (rev 1296) @@ -78,6 +78,7 @@ extern flash_driver_t ecosflash_flash; extern flash_driver_t lpc288x_flash; extern flash_driver_t ocl_flash; +extern flash_driver_t pic32mx_flash; flash_driver_t *flash_drivers[] = { &lpc2000_flash, @@ -94,6 +95,7 @@ &ecosflash_flash, &lpc288x_flash, &ocl_flash, + &pic32mx_flash, NULL, }; @@ -316,14 +318,17 @@ /* put flash bank in linked list */ if (flash_banks) { + int bank_num = 0; /* find last flash bank */ - for (p = flash_banks; p && p->next; p = p->next); + for (p = flash_banks; p && p->next; p = p->next) bank_num++; if (p) p->next = c; + c->bank_number = bank_num + 1; } else { flash_banks = c; + c->bank_number = 0; } found = 1; Added: trunk/src/flash/pic32mx.c =================================================================== --- trunk/src/flash/pic32mx.c 2009-01-02 23:52:46 UTC (rev 1295) +++ trunk/src/flash/pic32mx.c 2009-01-02 23:58:16 UTC (rev 1296) @@ -0,0 +1,902 @@ +/*************************************************************************** + * Copyright (C) 2005 by Dominic Rath * + * Dom...@gm... * + * * + * Copyright (C) 2008 by Spencer Oliver * + * sp...@sp... * + * * + * Copyright (C) 2008 by John McCarthy * + * jg...@ma... * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You 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. * + ***************************************************************************/ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "replacements.h" + +#include "pic32mx.h" +#include "flash.h" +#include "target.h" +#include "log.h" +#include "mips32.h" +#include "algorithm.h" +#include "binarybuffer.h" + +#include <stdlib.h> +#include <string.h> + +static +struct pic32mx_devs_s { + u8 devid; + char *name; + u32 pfm_size; +} pic32mx_devs[] = { + { 0x78, "460F512L USB", 512 }, + { 0x74, "460F256L USB", 256 }, + { 0x6D, "440F128L USB", 128 }, + { 0x56, "440F512H USB", 512 }, + { 0x52, "440F256H USB", 256 }, + { 0x4D, "440F128H USB", 128 }, + { 0x42, "420F032H USB", 32 }, + { 0x38, "360F512L", 512 }, + { 0x34, "360F256L", 256 }, + { 0x2D, "340F128L", 128 }, + { 0x2A, "320F128L", 128 }, + { 0x16, "340F512H", 512 }, + { 0x12, "340F256H", 256 }, + { 0x0D, "340F128H", 128 }, + { 0x0A, "320F128H", 128 }, + { 0x06, "320F064H", 64 }, + { 0x02, "320F032H", 32 }, + { 0x00, NULL, 0 } +}; + +int pic32mx_register_commands(struct command_context_s *cmd_ctx); +int pic32mx_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank); +int pic32mx_erase(struct flash_bank_s *bank, int first, int last); +int pic32mx_protect(struct flash_bank_s *bank, int set, int first, int last); +int pic32mx_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count); +int pic32mx_probe(struct flash_bank_s *bank); +int pic32mx_auto_probe(struct flash_bank_s *bank); +int pic32mx_handle_part_id_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); +int pic32mx_protect_check(struct flash_bank_s *bank); +int pic32mx_info(struct flash_bank_s *bank, char *buf, int buf_size); + +#if 0 +int pic32mx_handle_lock_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); +int pic32mx_handle_unlock_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); +#endif +int pic32mx_handle_chip_erase_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); +int pic32mx_handle_pgm_word_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); +int pic32mx_chip_erase(struct flash_bank_s *bank); + +flash_driver_t pic32mx_flash = +{ + .name = "pic32mx", + .register_commands = pic32mx_register_commands, + .flash_bank_command = pic32mx_flash_bank_command, + .erase = pic32mx_erase, + .protect = pic32mx_protect, + .write = pic32mx_write, + .probe = pic32mx_probe, + .auto_probe = pic32mx_auto_probe, + .erase_check = default_flash_mem_blank_check, + .protect_check = pic32mx_protect_check, + .info = pic32mx_info +}; + +int pic32mx_register_commands(struct command_context_s *cmd_ctx) +{ + command_t *pic32mx_cmd = register_command(cmd_ctx, NULL, "pic32mx", NULL, COMMAND_ANY, "pic32mx flash specific commands"); + +#if 0 + register_command(cmd_ctx, pic32mx_cmd, "lock", pic32mx_handle_lock_command, COMMAND_EXEC, + "lock device"); + register_command(cmd_ctx, pic32mx_cmd, "unlock", pic32mx_handle_unlock_command, COMMAND_EXEC, + "unlock protected device"); +#endif + register_command(cmd_ctx, pic32mx_cmd, "chip_erase", pic32mx_handle_chip_erase_command, COMMAND_EXEC, + "erase device"); + register_command(cmd_ctx, pic32mx_cmd, "pgm_word", pic32mx_handle_pgm_word_command, COMMAND_EXEC, + "program a word"); + return ERROR_OK; +} + +/* flash bank pic32mx <base> <size> 0 0 <target#> + */ +int pic32mx_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank) +{ + pic32mx_flash_bank_t *pic32mx_info; + + if (argc < 6) + { + LOG_WARNING("incomplete flash_bank pic32mx configuration"); + return ERROR_FLASH_BANK_INVALID; + } + + pic32mx_info = malloc(sizeof(pic32mx_flash_bank_t)); + bank->driver_priv = pic32mx_info; + + pic32mx_info->write_algorithm = NULL; + pic32mx_info->probed = 0; + + return ERROR_OK; +} + +u32 pic32mx_get_flash_status(flash_bank_t *bank) +{ + target_t *target = bank->target; + u32 status; + + target_read_u32(target, PIC32MX_NVMCON, &status); + + return status; +} + +u32 pic32mx_wait_status_busy(flash_bank_t *bank, int timeout) +{ + u32 status; + + /* wait for busy to clear */ + while (((status = pic32mx_get_flash_status(bank)) & NVMCON_NVMWR) && (timeout-- > 0)) + { + LOG_DEBUG("status: 0x%x", status); + alive_sleep(1); + } + if(timeout <= 0) + LOG_DEBUG("timeout: status: 0x%x", status); + + return status; +} + +int pic32mx_nvm_exec(struct flash_bank_s *bank, u32 op, u32 timeout) +{ + target_t *target = bank->target; + u32 status; + + target_write_u32(target, PIC32MX_NVMCON, NVMCON_NVMWREN|op); + + /* unlock flash registers */ + target_write_u32(target, PIC32MX_NVMKEY, NVMKEY1); + target_write_u32(target, PIC32MX_NVMKEY, NVMKEY2); + + /* start operation */ + target_write_u32(target, PIC32MX_NVMCONSET, NVMCON_NVMWR); + + status = pic32mx_wait_status_busy(bank, timeout); + + /* lock flash registers */ + target_write_u32(target, PIC32MX_NVMCONCLR, NVMCON_NVMWREN); + + return status; +} + +int pic32mx_protect_check(struct flash_bank_s *bank) +{ + target_t *target = bank->target; + pic32mx_flash_bank_t *pic32mx_info = bank->driver_priv; + + u32 devcfg0; + int s; + int num_pages; + + if (target->state != TARGET_HALTED) + { + LOG_ERROR("Target not halted"); + return ERROR_TARGET_NOT_HALTED; + } + + target_read_u32(target, PIC32MX_DEVCFG0, &devcfg0); + if((devcfg0 & (1<<28)) == 0) /* code protect bit */ + num_pages = 0xffff; /* All pages protected */ + else if(bank->base == PIC32MX_KSEG1_BOOT_FLASH) + { + if(devcfg0 & (1<<24)) + num_pages = 0; /* All pages unprotected */ + else + num_pages = 0xffff; /* All pages protected */ + } + else /* pgm flash */ + num_pages = (~devcfg0 >> 12) & 0xff; + for (s = 0; s < bank->num_sectors && s < num_pages; s++) + bank->sectors[s].is_protected = 1; + for (; s < bank->num_sectors; s++) + bank->sectors[s].is_protected = 0; + + return ERROR_OK; +} + +int pic32mx_erase(struct flash_bank_s *bank, int first, int last) +{ + target_t *target = bank->target; + int i; + u32 status; + + if (bank->target->state != TARGET_HALTED) + { + LOG_ERROR("Target not halted"); + return ERROR_TARGET_NOT_HALTED; + } + +#if 0 + if ((first == 0) && (last == (bank->num_sectors - 1)) && (bank->base == PIC32MX_KSEG0_PGM_FLASH || bank->base == PIC32MX_KSEG1_PGM_FLASH)) + { + status = pic32mx_nvm_exec(bank, NVMCON_OP_PFM_ERASE, 50); + if( status & NVMCON_NVMERR ) + return ERROR_FLASH_OPERATION_FAILED; + if( status & NVMCON_LVDERR ) + return ERROR_FLASH_OPERATION_FAILED; + return ERROR_OK; + } +#endif + + for (i = first; i <= last; i++) + { + target_write_u32(target, PIC32MX_NVMADDR, bank->base + bank->sectors[i].offset); + + status = pic32mx_nvm_exec(bank, NVMCON_OP_PAGE_ERASE, 10); + + if( status & NVMCON_NVMERR ) + return ERROR_FLASH_OPERATION_FAILED; + if( status & NVMCON_LVDERR ) + return ERROR_FLASH_OPERATION_FAILED; + bank->sectors[i].is_erased = 1; + } + + return ERROR_OK; +} + +int pic32mx_protect(struct flash_bank_s *bank, int set, int first, int last) +{ + pic32mx_flash_bank_t *pic32mx_info = NULL; + target_t *target = bank->target; + u16 prot_reg[4] = {0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF}; + int i, reg, bit; + int status; + u32 protection; + + pic32mx_info = bank->driver_priv; + + if (target->state != TARGET_HALTED) + { + LOG_ERROR("Target not halted"); + return ERROR_TARGET_NOT_HALTED; + } + +#if 0 + if ((first && (first % pic32mx_info->ppage_size)) || ((last + 1) && (last + 1) % pic32mx_info->ppage_size)) + { + LOG_WARNING("sector start/end incorrect - stm32 has %dK sector protection", pic32mx_info->ppage_size); + return ERROR_FLASH_SECTOR_INVALID; + } + + /* medium density - each bit refers to a 4bank protection + * high density - each bit refers to a 2bank protection */ + target_read_u32(target, PIC32MX_FLASH_WRPR, &protection); + + prot_reg[0] = (u16)protection; + prot_reg[1] = (u16)(protection >> 8); + prot_reg[2] = (u16)(protection >> 16); + prot_reg[3] = (u16)(protection >> 24); + + if (pic32mx_info->ppage_size == 2) + { + /* high density flash */ + + /* bit 7 controls sector 62 - 255 protection */ + if (last > 61) + { + if (set) + prot_reg[3] &= ~(1 << 7); + else + prot_reg[3] |= (1 << 7); + } + + if (first > 61) + first = 62; + if (last > 61) + last = 61; + + for (i = first; i <= last; i++) + { + reg = (i / pic32mx_info->ppage_size) / 8; + bit = (i / pic32mx_info->ppage_size) - (reg * 8); + + if( set ) + prot_reg[reg] &= ~(1 << bit); + else + prot_reg[reg] |= (1 << bit); + } + } + else + { + /* medium density flash */ + for (i = first; i <= last; i++) + { + reg = (i / pic32mx_info->ppage_size) / 8; + bit = (i / pic32mx_info->ppage_size) - (reg * 8); + + if( set ) + prot_reg[reg] &= ~(1 << bit); + else + prot_reg[reg] |= (1 << bit); + } + } + + if ((status = pic32mx_erase_options(bank)) != ERROR_OK) + return status; + + pic32mx_info->option_bytes.protection[0] = prot_reg[0]; + pic32mx_info->option_bytes.protection[1] = prot_reg[1]; + pic32mx_info->option_bytes.protection[2] = prot_reg[2]; + pic32mx_info->option_bytes.protection[3] = prot_reg[3]; + + return pic32mx_write_options(bank); +#else + return ERROR_OK; +#endif +} + +int pic32mx_write_block(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count) +{ + pic32mx_flash_bank_t *pic32mx_info = bank->driver_priv; + target_t *target = bank->target; + u32 buffer_size = 8192; + working_area_t *source; + u32 address = bank->base + offset; + reg_param_t reg_params[4]; +#if 0 + armv7m_algorithm_t armv7m_info; + int retval = ERROR_OK; + + u8 pic32mx_flash_write_code[] = { + /* write: */ + 0xDF, 0xF8, 0x24, 0x40, /* ldr r4, PIC32MX_FLASH_CR */ + 0x09, 0x4D, /* ldr r5, PIC32MX_FLASH_SR */ + 0x4F, 0xF0, 0x01, 0x03, /* mov r3, #1 */ + 0x23, 0x60, /* str r3, [r4, #0] */ + 0x30, 0xF8, 0x02, 0x3B, /* ldrh r3, [r0], #2 */ + 0x21, 0xF8, 0x02, 0x3B, /* strh r3, [r1], #2 */ + /* busy: */ + 0x2B, 0x68, /* ldr r3, [r5, #0] */ + 0x13, 0xF0, 0x01, 0x0F, /* tst r3, #0x01 */ + 0xFB, 0xD0, /* beq busy */ + 0x13, 0xF0, 0x14, 0x0F, /* tst r3, #0x14 */ + 0x01, 0xD1, /* bne exit */ + 0x01, 0x3A, /* subs r2, r2, #1 */ + 0xED, 0xD1, /* bne write */ + /* exit: */ + 0xFE, 0xE7, /* b exit */ + 0x10, 0x20, 0x02, 0x40, /* PIC32MX_FLASH_CR: .word 0x40022010 */ + 0x0C, 0x20, 0x02, 0x40 /* PIC32MX_FLASH_SR: .word 0x4002200C */ + }; + + /* flash write code */ + if (target_alloc_working_area(target, sizeof(pic32mx_flash_write_code), &pic32mx_info->write_algorithm) != ERROR_OK) + { + LOG_WARNING("no working area available, can't do block memory writes"); + return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; + }; + + if ((retval=target_write_buffer(target, pic32mx_info->write_algorithm->address, sizeof(pic32mx_flash_write_code), pic32mx_flash_write_code))!=ERROR_OK) + return retval; + + /* memory buffer */ + while (target_alloc_working_area(target, buffer_size, &source) != ERROR_OK) + { + buffer_size /= 2; + if (buffer_size <= 256) + { + /* if we already allocated the writing code, but failed to get a buffer, free the algorithm */ + if (pic32mx_info->write_algorithm) + target_free_working_area(target, pic32mx_info->write_algorithm); + + LOG_WARNING("no large enough working area available, can't do block memory writes"); + return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; + } + }; + + armv7m_info.common_magic = ARMV7M_COMMON_MAGIC; + armv7m_info.core_mode = ARMV7M_MODE_ANY; + + init_reg_param(®_params[0], "r0", 32, PARAM_OUT); + init_reg_param(®_params[1], "r1", 32, PARAM_OUT); + init_reg_param(®_params[2], "r2", 32, PARAM_OUT); + init_reg_param(®_params[3], "r3", 32, PARAM_IN); + + while (count > 0) + { + u32 thisrun_count = (count > (buffer_size / 2)) ? (buffer_size / 2) : count; + + if ((retval = target_write_buffer(target, source->address, thisrun_count * 2, buffer))!=ERROR_OK) + break; + + buf_set_u32(reg_params[0].value, 0, 32, source->address); + buf_set_u32(reg_params[1].value, 0, 32, address); + buf_set_u32(reg_params[2].value, 0, 32, thisrun_count); + + if ((retval = target->type->run_algorithm(target, 0, NULL, 4, reg_params, pic32mx_info->write_algorithm->address, \ + pic32mx_info->write_algorithm->address + (sizeof(pic32mx_flash_write_code) - 10), 10000, &armv7m_info)) != ERROR_OK) + { + LOG_ERROR("error executing pic32mx flash write algorithm"); + retval = ERROR_FLASH_OPERATION_FAILED; + break; + } + + if (buf_get_u32(reg_params[3].value, 0, 32) & 0x14) + { + retval = ERROR_FLASH_OPERATION_FAILED; + break; + } + + buffer += thisrun_count * 2; + address += thisrun_count * 2; + count -= thisrun_count; + } + + target_free_working_area(target, source); + target_free_working_area(target, pic32mx_info->write_algorithm); + + destroy_reg_param(®_params[0]); + destroy_reg_param(®_params[1]); + destroy_reg_param(®_params[2]); + destroy_reg_param(®_params[3]); + + return retval; +#else + return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; +#endif +} + +int pic32mx_write_word(struct flash_bank_s *bank, u32 address, u32 word) +{ + target_t *target = bank->target; + + target_write_u32(target, PIC32MX_NVMADDR, address); + target_write_u32(target, PIC32MX_NVMDATA, word); + + return pic32mx_nvm_exec(bank, NVMCON_OP_WORD_PROG, 5); +} + +int pic32mx_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count) +{ + target_t *target = bank->target; + u32 words_remaining = (count / 4); + u32 bytes_remaining = (count & 0x00000003); + u32 address = bank->base + offset; + u32 bytes_written = 0; + u32 status; + u32 retval; + + if (bank->target->state != TARGET_HALTED) + { + LOG_ERROR("Target not halted"); + return ERROR_TARGET_NOT_HALTED; + } + + if (offset & 0x3) + { + LOG_WARNING("offset 0x%x breaks required 4-byte alignment", offset); + return ERROR_FLASH_DST_BREAKS_ALIGNMENT; + } + + /* multiple words (4-byte) to be programmed? */ + if (words_remaining > 0) + { + /* try using a block write */ + if ((retval = pic32mx_write_block(bank, buffer, offset, words_remaining)) != ERROR_OK) + { + if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) + { + /* if block write failed (no sufficient working area), + * we use normal (slow) single dword accesses */ + LOG_WARNING("couldn't use block writes, falling back to single memory accesses"); + } + else if (retval == ERROR_FLASH_OPERATION_FAILED) + { + LOG_ERROR("flash writing failed with error code: 0x%x", retval); + return ERROR_FLASH_OPERATION_FAILED; + } + } + else + { + buffer += words_remaining * 4; + address += words_remaining * 4; + words_remaining = 0; + } + } + + while (words_remaining > 0) + { + status = pic32mx_write_word(bank, address, *(u32*)(buffer + bytes_written)); + + if( status & NVMCON_NVMERR ) + return ERROR_FLASH_OPERATION_FAILED; + if( status & NVMCON_LVDERR ) + return ERROR_FLASH_OPERATION_FAILED; + + bytes_written += 4; + words_remaining--; + address += 4; + } + + if (bytes_remaining) + { + u8 last_word[4] = {0xff, 0xff, 0xff, 0xff}; + int i = 0; + + while(bytes_remaining > 0) + { + /* Assumes little endian */ + last_word[i++] = *(buffer + bytes_written); + bytes_remaining--; + bytes_written++; + } + + status = pic32mx_write_word(bank, address, *(u32*)last_word); + + if( status & NVMCON_NVMERR ) + return ERROR_FLASH_OPERATION_FAILED; + if( status & NVMCON_LVDERR ) + return ERROR_FLASH_OPERATION_FAILED; + } + + return ERROR_OK; +} + +int pic32mx_probe(struct flash_bank_s *bank) +{ + target_t *target = bank->target; + pic32mx_flash_bank_t *pic32mx_info = bank->driver_priv; + mips32_common_t *mips32 = target->arch_info; + mips_ejtag_t *ejtag_info = &mips32->ejtag_info; + int i; + u16 num_pages; + u32 device_id; + int page_size; + + pic32mx_info->probed = 0; + + device_id = ejtag_info->idcode; + LOG_INFO( "device id = 0x%08x (manuf 0x%03x dev 0x%02x, ver 0x%03x)", device_id, (device_id>>1)&0x7ff, (device_id>>12)&0xff, (device_id>>20)&0xfff ); + + if(((device_id>>1)&0x7ff) != PIC32MX_MANUF_ID) { + LOG_WARNING( "Cannot identify target as a PIC32MX family." ); + return ERROR_FLASH_OPERATION_FAILED; + } + + page_size = 4096; + if(bank->base == PIC32MX_KSEG1_BOOT_FLASH || bank->base == 1) { + /* 0xBFC00000: Boot flash size fixed at 12k */ + num_pages = 12; + } else { + /* 0xBD000000: Program flash size varies with device */ + for(i=0; pic32mx_devs[i].name != NULL; i++) + if(pic32mx_devs[i].devid == ((device_id >> 12) & 0xff)) { + num_pages = pic32mx_devs[i].pfm_size; + break; + } + if(pic32mx_devs[i].name == NULL) { + LOG_WARNING( "Cannot identify target as a PIC32MX family." ); + return ERROR_FLASH_OPERATION_FAILED; + } + } + +#if 0 + if (bank->target->state != TARGET_HALTED) + { + LOG_ERROR("Target not halted"); + return ERROR_TARGET_NOT_HALTED; + } + + /* get flash size from target */ + if (target_read_u16(target, 0x1FFFF7E0, &num_pages) != ERROR_OK) + { + /* failed reading flash size, default to max target family */ + num_pages = 0xffff; + } +#endif + + LOG_INFO( "flash size = %dkbytes", num_pages ); + + /* calculate numbers of pages */ + num_pages /= (page_size / 1024); + + if(bank->base == 0) bank->base = PIC32MX_KSEG1_PGM_FLASH; + if(bank->base == 1) bank->base = PIC32MX_KSEG1_BOOT_FLASH; + bank->size = (num_pages * page_size); + bank->num_sectors = num_pages; + bank->chip_width = 4; + bank->bus_width = 4; + bank->sectors = malloc(sizeof(flash_sector_t) * num_pages); + + for (i = 0; i < num_pages; i++) + { + bank->sectors[i].offset = i * page_size; + bank->sectors[i].size = page_size; + bank->sectors[i].is_erased = -1; + bank->sectors[i].is_protected = 1; + } + + pic32mx_info->probed = 1; + + return ERROR_OK; +} + +int pic32mx_auto_probe(struct flash_bank_s *bank) +{ + pic32mx_flash_bank_t *pic32mx_info = bank->driver_priv; + if (pic32mx_info->probed) + return ERROR_OK; + return pic32mx_probe(bank); +} + +int pic32mx_handle_part_id_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) +{ + return ERROR_OK; +} + +int pic32mx_info(struct flash_bank_s *bank, char *buf, int buf_size) +{ + target_t *target = bank->target; + mips32_common_t *mips32 = target->arch_info; + mips_ejtag_t *ejtag_info = &mips32->ejtag_info; + u32 device_id; + int printed, i; + + device_id = ejtag_info->idcode; + + if(((device_id>>1)&0x7ff) != PIC32MX_MANUF_ID) { + snprintf(buf, buf_size, "Cannot identify target as a PIC32MX family (manufacturer 0x%03d != 0x%03d)\n", (device_id>>1)&0x7ff, PIC32MX_MANUF_ID); + return ERROR_FLASH_OPERATION_FAILED; + } + for(i=0; pic32mx_devs[i].name != NULL; i++) + if(pic32mx_devs[i].devid == ((device_id >> 12) & 0xff)) { + printed = snprintf(buf, buf_size, "PIC32MX%s", pic32mx_devs[i].name); + break; + } + if(pic32mx_devs[i].name == NULL) { + snprintf(buf, buf_size, "Cannot identify target as a PIC32MX family\n"); + return ERROR_FLASH_OPERATION_FAILED; + } + buf += printed; + buf_size -= printed; + printed = snprintf(buf, buf_size, " Ver: 0x%03x", (device_id>>20)&0xfff); + + return ERROR_OK; +} + +#if 0 +int pic32mx_handle_lock_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) +{ + flash_bank_t *bank; + target_t *target = NULL; + pic32mx_flash_bank_t *pic32mx_info = NULL; + + if (argc < 1) + { + command_print(cmd_ctx, "pic32mx lock <bank>"); + return ERROR_OK; + } + + bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0)); + if (!bank) + { + command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]); + return ERROR_OK; + } + + pic32mx_info = bank->driver_priv; + + target = bank->target; + + if (target->state != TARGET_HALTED) + { + LOG_ERROR("Target not halted"); + return ERROR_TARGET_NOT_HALTED; + } + + if (pic32mx_erase_options(bank) != ERROR_OK) + { + command_print(cmd_ctx, "pic32mx failed to erase options"); + return ERROR_OK; + } + + /* set readout protection */ + pic32mx_info->option_bytes.RDP = 0; + + if (pic32mx_write_options(bank) != ERROR_OK) + { + command_print(cmd_ctx, "pic32mx failed to lock device"); + return ERROR_OK; + } + + command_print(cmd_ctx, "pic32mx locked"); + + return ERROR_OK; +} + +int pic32mx_handle_unlock_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) +{ + flash_bank_t *bank; + target_t *target = NULL; + pic32mx_flash_bank_t *pic32mx_info = NULL; + + if (argc < 1) + { + command_print(cmd_ctx, "pic32mx unlock <bank>"); + return ERROR_OK; + } + + bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0)); + if (!bank) + { + command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]); + return ERROR_OK; + } + + pic32mx_info = bank->driver_priv; + + target = bank->target; + + if (target->state != TARGET_HALTED) + { + LOG_ERROR("Target not halted"); + return ERROR_TARGET_NOT_HALTED; + } + + if (pic32mx_erase_options(bank) != ERROR_OK) + { + command_print(cmd_ctx, "pic32mx failed to unlock device"); + return ERROR_OK; + } + + if (pic32mx_write_options(bank) != ERROR_OK) + { + command_print(cmd_ctx, "pic32mx failed to lock device"); + return ERROR_OK; + } + + command_print(cmd_ctx, "pic32mx unlocked"); + + return ERROR_OK; +} +#endif + +int pic32mx_chip_erase(struct flash_bank_s *bank) +{ + target_t *target = bank->target; + u32 status; + + if (target->state != TARGET_HALTED) + { + LOG_ERROR("Target not halted"); + return ERROR_TARGET_NOT_HALTED; + } + + LOG_INFO("PIC32MX chip erase called"); + +#if 0 + /* unlock option flash registers */ + target_write_u32(target, PIC32MX_FLASH_KEYR, KEY1); + target_write_u32(target, PIC32MX_FLASH_KEYR, KEY2); + + /* chip erase flash memory */ + target_write_u32(target, PIC32MX_FLASH_CR, FLASH_MER); + target_write_u32(target, PIC32MX_FLASH_CR, FLASH_MER|FLASH_STRT); + + status = pic32mx_wait_status_busy(bank, 10); + + target_write_u32(target, PIC32MX_FLASH_CR, FLASH_LOCK); + + if( status & FLASH_WRPRTERR ) + { + LOG_ERROR("pic32mx device protected"); + return ERROR_OK; + } + + if( status & FLASH_PGERR ) + { + LOG_ERROR("pic32mx device programming failed"); + return ERROR_OK; + } +#endif + + return ERROR_OK; +} + +int pic32mx_handle_chip_erase_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) +{ + flash_bank_t *bank; + int i; + +#if 0 + if (argc != 0) + { + command_print(cmd_ctx, "pic32mx chip_erase"); + return ERROR_OK; + } + + bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0)); + if (!bank) + { + command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]); + return ERROR_OK; + } + + if (pic32mx_chip_erase(bank) == ERROR_OK) + { + /* set all sectors as erased */ + for (i = 0; i < bank->num_sectors; i++) + { + bank->sectors[i].is_erased = 1; + } + + command_print(cmd_ctx, "pic32mx chip erase complete"); + } + else + { + command_print(cmd_ctx, "pic32mx chip erase failed"); + } +#endif + + return ERROR_OK; +} + +int pic32mx_handle_pgm_word_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) +{ + flash_bank_t *bank; + u32 address, value; + int i; + int status, res; + + if (argc != 3) + { + command_print(cmd_ctx, "pic32mx pgm_word <addr> <value> <bank>"); + return ERROR_OK; + } + + address = strtoul(args[0], NULL, 0); + value = strtoul(args[1], NULL, 0); + + bank = get_flash_bank_by_num(strtoul(args[2], NULL, 0)); + if (!bank) + { + command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[2]); + return ERROR_OK; + } + if (address < bank->base || address >= (bank->base+bank->size)) + { + command_print(cmd_ctx, "flash address '%s' is out of bounds", args[0]); + return ERROR_OK; + } + + res = ERROR_OK; + status = pic32mx_write_word(bank, address, value); + if( status & NVMCON_NVMERR ) + res = ERROR_FLASH_OPERATION_FAILED; + if( status & NVMCON_LVDERR ) + res = ERROR_FLASH_OPERATION_FAILED; + + if (res == ERROR_OK) + command_print(cmd_ctx, "pic32mx pgm word complete"); + else + command_print(cmd_ctx, "pic32mx pgm word failed (status=0x%x)", status); + + return ERROR_OK; +} Added: trunk/src/flash/pic32mx.h =================================================================== --- trunk/src/flash/pic32mx.h 2009-01-02 23:52:46 UTC (rev 1295) +++ trunk/src/flash/pic32mx.h 2009-01-02 23:58:16 UTC (rev 1296) @@ -0,0 +1,105 @@ +/*************************************************************************** + * Copyright (C) 2005 by Dominic Rath * + * Dom...@gm... * + * * + * Copyright (C) 2008 by Spencer Oliver * + * sp...@sp... * + * * + * Copyright (C) 2008 by John McCarthy * + * jg...@ma... * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You 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. * + ***************************************************************************/ +#ifndef PIC32MX_H +#define PIC32MX_H + +#include "flash.h" +#include "target.h" + +typedef struct pic32mx_flash_bank_s +{ + working_area_t *write_algorithm; + int devid; + int ppage_size; + int probed; +} pic32mx_flash_bank_t; + +#define PIC32MX_MANUF_ID 0x029 + +/* pic32mx memory locations */ + +#define PIC32MX_KUSEG_PGM_FLASH 0x7D000000 +#define PIC32MX_KUSEG_RAM 0x7F000000 + +#define PIC32MX_KSEG0_RAM 0x80000000 +#define PIC32MX_KSEG0_PGM_FLASH 0x9D000000 +#define PIC32MX_KSEG0_BOOT_FLASH 0x9FC00000 + +#define PIC32MX_KSEG1_RAM 0xA0000000 +#define PIC32MX_KSEG1_PGM_FLASH 0xBD000000 +#define PIC32MX_KSEG1_PERIPHERAL 0xBF800000 +#define PIC32MX_KSEG1_BOOT_FLASH 0xBFC00000 + +#define PIC32MX_PHYS_RAM 0x00000000 +#define PIC32MX_PHYS_PGM_FLASH 0x1D000000 +#define PIC32MX_PHYS_PERIPHERALS 0x1F800000 +#define PIC32MX_PHYS_BOOT_FLASH 0x1FC00000 + +/* pic32mx configuration register locations */ + +#define PIC32MX_DEVCFG0 0xBFC02FFC +#define PIC32MX_DEVCFG1 0xBFC02FF8 +#define PIC32MX_DEVCFG2 0xBFC02FF4 +#define PIC32MX_DEVCFG3 0XBFC02FF0 +#define PIC32MX_DEVID 0xBF80F220 + +/* pic32mx flash controller register locations */ + +#define PIC32MX_NVMCON 0xBF80F400 +#define PIC32MX_NVMCONCLR 0xBF80F404 +#define PIC32MX_NVMCONSET 0xBF80F408 +#define PIC32MX_NVMCONINV 0xBF80F40C +#define NVMCON_NVMWR (1<<15) +#define NVMCON_NVMWREN (1<<14) +#define NVMCON_NVMERR (1<<13) +#define NVMCON_LVDERR (1<<12) +#define NVMCON_LVDSTAT (1<<11) +#define NVMCON_OP_PFM_ERASE 0x5 +#define NVMCON_OP_PAGE_ERASE 0x4 +#define NVMCON_OP_ROW_PROG 0x3 +#define NVMCON_OP_WORD_PROG 0x1 +#define NVMCON_OP_NOP 0x0 + +#define PIC32MX_NVMKEY 0xBF80F410 +#define PIC32MX_NVMADDR 0xBF80F420 +#define PIC32MX_NVMADDRCLR 0xBF80F424 +#define PIC32MX_NVMADDRSET 0xBF80F428 +#define PIC32MX_NVMADDRINV 0xBF80F42C +#define PIC32MX_NVMDATA 0xBF80F430 +#define PIC32MX_NVMSRCADDR 0xBF80F440 + +/* flash unlock keys */ + +#define NVMKEY1 0xAA996655 +#define NVMKEY2 0x556699AA + +typedef struct pic32mx_mem_layout_s { + u32 sector_start; + u32 sector_size; +} pic32mx_mem_layout_t; + +#endif /* PIC32MX_H */ + Added: trunk/src/target/board/pic-p32mx.cfg =================================================================== --- trunk/src/target/board/pic-p32mx.cfg 2009-01-02 23:52:46 UTC (rev 1295) +++ trunk/src/target/board/pic-p32mx.cfg 2009-01-02 23:58:16 UTC (rev 1296) @@ -0,0 +1,8 @@ +# The Olimex PIC-P32MX has a PIC32MX + +set CPUTAPID 0x40916053 +source [find target/pic32mx.cfg] + +init +flash probe 0 +flash probe 1 Modified: trunk/src/target/mips_ejtag.h =================================================================== --- trunk/src/target/mips_ejtag.h 2009-01-02 23:52:46 UTC (rev 1295) +++ trunk/src/target/mips_ejtag.h 2009-01-02 23:58:16 UTC (rev 1296) @@ -102,6 +102,7 @@ { jtag_tap_t *tap; u32 impcode; + u32 idcode; /*int use_dma;*/ u32 ejtag_ctrl; } mips_ejtag_t; Modified: trunk/src/target/mips_m4k.c =================================================================== --- trunk/src/target/mips_m4k.c 2009-01-02 23:52:46 UTC (rev 1295) +++ trunk/src/target/mips_m4k.c 2009-01-02 23:58:16 UTC (rev 1296) @@ -50,6 +50,7 @@ int mips_m4k_examine(struct target_s *target); int mips_m4k_assert_reset(target_t *target); int mips_m4k_deassert_reset(target_t *target); +int mips_m4k_checksum_memory(target_t *target, u32 address, u32 size, u32 *checksum); target_type_t mips_m4k_target = { @@ -73,7 +74,7 @@ .read_memory = mips_m4k_read_memory, .write_memory = mips_m4k_write_memory, .bulk_write_memory = mips_m4k_bulk_write_memory, - .checksum_memory = NULL, + .checksum_memory = mips_m4k_checksum_memory, .blank_check_memory = NULL, .run_algorithm = mips32_run_algorithm, @@ -766,7 +767,8 @@ if (!target->type->examined) { mips_ejtag_get_idcode(ejtag_info, &idcode, NULL); - + ejtag_info->idcode = idcode; + if (((idcode >> 1) & 0x7FF) == 0x29) { /* we are using a pic32mx so select ejtag port @@ -790,3 +792,8 @@ { return mips_m4k_write_memory(target, address, 4, count, buffer); } + +int mips_m4k_checksum_memory(target_t *target, u32 address, u32 size, u32 *checksum) +{ + return ERROR_FAIL; /* use bulk read method */ +} Modified: trunk/src/target/target/pic32mx.cfg =================================================================== --- trunk/src/target/target/pic32mx.cfg 2009-01-02 23:52:46 UTC (rev 1295) +++ trunk/src/target/target/pic32mx.cfg 2009-01-02 23:58:16 UTC (rev 1296) @@ -26,13 +26,15 @@ #jtag scan chain #format L IRC IRCM IDCODE (Length, IR Capture, IR Capture Mask, IDCODE) -jtag newtap $_CPUNAME cpu -irlen 5 -ircapture 0x1 -irmask 0x1 -expected-id $_CPUTAPID +jtag newtap $_CHIPNAME cpu -irlen 5 -ircapture 0x1 -irmask 0x1f -expected-id $_CPUTAPID set _TARGETNAME [format "%s.cpu" $_CHIPNAME] target create $_TARGETNAME mips_m4k -endian $_ENDIAN -chain-position $_TARGETNAME $_TARGETNAME configure -work-area-virt 0 -work-area-phys 0xa0000000 -work-area-size 16384 -work-area-backup 0 +flash bank pic32mx 0xbd000000 0 0 0 0 +flash bank pic32mx 0xbfc00000 0 0 0 0 # For more information about the configuration files, take a look at: # openocd.texi |
From: <oh...@ma...> - 2009-01-03 00:52:59
|
Author: oharboe Date: 2009-01-03 00:52:46 +0100 (Sat, 03 Jan 2009) New Revision: 1295 Modified: trunk/src/target/mips_ejtag.c Log: John McCarthy <jg...@ma...> keep_alive() fix Modified: trunk/src/target/mips_ejtag.c =================================================================== --- trunk/src/target/mips_ejtag.c 2009-01-01 16:06:46 UTC (rev 1294) +++ trunk/src/target/mips_ejtag.c 2009-01-02 23:52:46 UTC (rev 1295) @@ -144,6 +144,8 @@ return retval; } + keep_alive(); + return ERROR_OK; } |
From: ntfreak at B. <nt...@ma...> - 2009-01-01 17:06:47
|
Author: ntfreak Date: 2009-01-01 17:06:46 +0100 (Thu, 01 Jan 2009) New Revision: 1294 Modified: trunk/doc/openocd.texi trunk/src/helper/options.c trunk/src/helper/replacements.c trunk/src/helper/replacements.h trunk/src/server/gdb_server.c trunk/src/server/server.c Log: - add gdb pipe support to native win32 (--pipe option) Modified: trunk/doc/openocd.texi =================================================================== --- trunk/doc/openocd.texi 2008-12-28 21:40:39 UTC (rev 1293) +++ trunk/doc/openocd.texi 2009-01-01 16:06:46 UTC (rev 1294) @@ -557,7 +557,6 @@ target library is in the search path by default. For details on the @option{-p} option. @xref{Connecting to GDB}. -Option @option{-p} is not currently supported under native win32. Note! OpenOCD will launch the GDB & telnet server even if it can not establish a connection with the target. In general, it is possible for Modified: trunk/src/helper/options.c =================================================================== --- trunk/src/helper/options.c 2008-12-28 21:40:39 UTC (rev 1293) +++ trunk/src/helper/options.c 2009-01-01 16:06:46 UTC (rev 1294) @@ -149,14 +149,8 @@ /* pipes unsupported on hosted platforms */ LOG_WARNING("pipes not supported on this platform"); #else -#ifdef IS_MINGW - /* pipes currently unsupported on win32 */ - LOG_WARNING("pipes currently unsupported on win32"); - exit(1); -#else server_use_pipes = 1; #endif -#endif break; } } Modified: trunk/src/helper/replacements.c =================================================================== --- trunk/src/helper/replacements.c 2008-12-28 21:40:39 UTC (rev 1293) +++ trunk/src/helper/replacements.c 2009-01-01 16:06:46 UTC (rev 1294) @@ -68,6 +68,10 @@ #include <stdio.h> +#ifdef _WIN32 +#include <io.h> +#endif + /* replacements for gettimeofday */ #ifndef HAVE_GETTIMEOFDAY @@ -137,3 +141,151 @@ return (char *) memcpy (new, s, len); } #endif + +#ifdef _WIN32 +int win_select(int max_fd, fd_set *rfds, fd_set *wfds, fd_set *efds, struct timeval *tv) +{ + DWORD ms_total, limit; + HANDLE handles[MAXIMUM_WAIT_OBJECTS]; + int handle_slot_to_fd[MAXIMUM_WAIT_OBJECTS]; + int n_handles = 0, i; + fd_set sock_read, sock_write, sock_except; + fd_set aread, awrite, aexcept; + int sock_max_fd = -1; + struct timeval tvslice; + int retcode; + +#define SAFE_FD_ISSET(fd, set) (set != NULL && FD_ISSET(fd, set)) + + /* calculate how long we need to wait in milliseconds */ + if (tv == NULL) { + ms_total = INFINITE; + } else { + ms_total = tv->tv_sec * 1000; + ms_total += tv->tv_usec / 1000; + } + + FD_ZERO(&sock_read); + FD_ZERO(&sock_write); + FD_ZERO(&sock_except); + + /* build an array of handles for non-sockets */ + for (i = 0; i < max_fd; i++) { + if (SAFE_FD_ISSET(i, rfds) || SAFE_FD_ISSET(i, wfds) || SAFE_FD_ISSET(i, efds)) { + handles[n_handles] = (HANDLE)_get_osfhandle(i); + if (handles[n_handles] == INVALID_HANDLE_VALUE) { + /* socket */ + if (SAFE_FD_ISSET(i, rfds)) { + FD_SET(i, &sock_read); + } + if (SAFE_FD_ISSET(i, wfds)) { + FD_SET(i, &sock_write); + } + if (SAFE_FD_ISSET(i, efds)) { + FD_SET(i, &sock_except); + } + if (i > sock_max_fd) { + sock_max_fd = i; + } + } else { + handle_slot_to_fd[n_handles] = i; + n_handles++; + } + } + } + + if (n_handles == 0) { + /* plain sockets only - let winsock handle the whole thing */ + return select(max_fd, rfds, wfds, efds, tv); + } + + /* mixture of handles and sockets; lets multiplex between + * winsock and waiting on the handles */ + + FD_ZERO(&aread); + FD_ZERO(&awrite); + FD_ZERO(&aexcept); + + limit = GetTickCount() + ms_total; + do { + retcode = 0; + + if (sock_max_fd >= 0) { + /* overwrite the zero'd sets here; the select call + * will clear those that are not active */ + aread = sock_read; + awrite = sock_write; + aexcept = sock_except; + + tvslice.tv_sec = 0; + tvslice.tv_usec = 100000; + + retcode = select(sock_max_fd+1, &aread, &awrite, &aexcept, &tvslice); + } + if (n_handles > 0) { + /* check handles */ + DWORD wret; + + wret = MsgWaitForMultipleObjects(n_handles, handles, FALSE, retcode > 0 ? 0 : 100, QS_ALLEVENTS); + + if (wret == WAIT_TIMEOUT) { + /* set retcode to 0; this is the default. + * select() may have set it to something else, + * in which case we leave it alone, so this branch + * does nothing */ + ; + } else if (wret == WAIT_FAILED) { + if (retcode == 0) { + retcode = -1; + } + } else { + if (retcode < 0) { + retcode = 0; + } + for (i = 0; i < n_handles; i++) { + if (WAIT_OBJECT_0 == WaitForSingleObject(handles[i], 0)) { + if (SAFE_FD_ISSET(handle_slot_to_fd[i], rfds)) { + DWORD dwBytes; + + if (PeekNamedPipe((HANDLE)_get_osfhandle(handle_slot_to_fd[i]), NULL, 0, NULL, &dwBytes, NULL)) + { + /* check to see if gdb pipe has data available */ + if (dwBytes) + { + FD_SET(handle_slot_to_fd[i], &aread); + retcode++; + } + } + else + { + FD_SET(handle_slot_to_fd[i], &aread); + retcode++; + } + } + if (SAFE_FD_ISSET(handle_slot_to_fd[i], wfds)) { + FD_SET(handle_slot_to_fd[i], &awrite); + retcode++; + } + if (SAFE_FD_ISSET(handle_slot_to_fd[i], efds)) { + FD_SET(handle_slot_to_fd[i], &aexcept); + retcode++; + } + } + } + } + } + } while (retcode == 0 && (ms_total == INFINITE || GetTickCount() < limit)); + + if (rfds) { + *rfds = aread; + } + if (wfds) { + *wfds = awrite; + } + if (efds) { + *efds = aexcept; + } + + return retcode; +} +#endif Modified: trunk/src/helper/replacements.h =================================================================== --- trunk/src/helper/replacements.h 2008-12-28 21:40:39 UTC (rev 1293) +++ trunk/src/helper/replacements.h 2009-01-01 16:06:46 UTC (rev 1294) @@ -180,6 +180,9 @@ } #endif /* IS_MINGW */ + +int win_select(int max_fd, fd_set *rfds, fd_set *wfds, fd_set *efds, struct timeval *tv); + #endif /* _WIN32 */ /* generic socket functions for Windows and Posix */ @@ -221,6 +224,15 @@ #endif } +static __inline int socket_select(int max_fd, fd_set *rfds, fd_set *wfds, fd_set *efds, struct timeval *tv) +{ +#ifdef _WIN32 + return win_select(max_fd, rfds, wfds, efds, tv); +#else + return select(max_fd, rfds, wfds, efds, tv); +#endif +} + #ifndef HAVE_ELF_H typedef struct Modified: trunk/src/server/gdb_server.c =================================================================== --- trunk/src/server/gdb_server.c 2008-12-28 21:40:39 UTC (rev 1293) +++ trunk/src/server/gdb_server.c 2009-01-01 16:06:46 UTC (rev 1294) @@ -126,7 +126,7 @@ tv.tv_sec = timeout_s; tv.tv_usec = 0; - if (select(connection->fd + 1, &read_fds, NULL, NULL, &tv) == 0) + if (socket_select(connection->fd + 1, &read_fds, NULL, NULL, &tv) == 0) { /* This can typically be because a "monitor" command took too long * before printing any progress messages Modified: trunk/src/server/server.c =================================================================== --- trunk/src/server/server.c 2008-12-28 21:40:39 UTC (rev 1293) +++ trunk/src/server/server.c 2009-01-01 16:06:46 UTC (rev 1294) @@ -97,12 +97,11 @@ } else if (service->type == CONNECTION_PIPE) { -#ifndef _WIN32 c->fd = service->fd; /* do not check for new connections again on stdin */ service->fd = -1; -#endif + LOG_INFO("accepting '%s' connection from pipe", service->name); if ((retval = service->new_connection(c)) != ERROR_OK) { @@ -223,6 +222,8 @@ LOG_WARNING("cannot change stdout mode to binary"); if (_setmode(_fileno(stdin), _O_BINARY) < 0) LOG_WARNING("cannot change stdin mode to binary"); + if (_setmode(_fileno(stderr), _O_BINARY) < 0) + LOG_WARNING("cannot change stderr mode to binary"); #else socket_nonblock(c->fd); #endif @@ -365,7 +366,7 @@ kept_alive(); /* Only while we're sleeping we'll let others run */ - retval = select(fd_max + 1, &read_fds, NULL, NULL, &tv); + retval = socket_select(fd_max + 1, &read_fds, NULL, NULL, &tv); openocd_sleep_postlude(); if (retval == -1) @@ -503,7 +504,7 @@ WORD wVersionRequested; WSADATA wsaData; - wVersionRequested = MAKEWORD( 2, 2 ); + wVersionRequested = MAKEWORD(2, 2); if (WSAStartup(wVersionRequested, &wsaData) != 0) { @@ -511,7 +512,16 @@ exit(-1); } - SetConsoleCtrlHandler( ControlHandler, TRUE ); + if (server_use_pipes == 0) + { + /* register ctrl-c handler */ + SetConsoleCtrlHandler(ControlHandler, TRUE); + } + else + { + /* we are using pipes so ignore ctrl-c */ + SetConsoleCtrlHandler(NULL, TRUE); + } signal(SIGINT, sig_handler); signal(SIGTERM, sig_handler); |