Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add JTAG support to avrftdi #1324

Merged
merged 9 commits into from
Aug 4, 2023
Merged

add JTAG support to avrftdi #1324

merged 9 commits into from
Aug 4, 2023

Conversation

jkent
Copy link
Contributor

@jkent jkent commented Mar 19, 2023

Added tumpa-b and tumpa-jtag to config

JTAG tested at 8MHz, example of reading 128KiB flash:

$ avrdude -p atmega128rfa1 -c tumpa-jtag -B 8MHz -U flash:r:dump

avrdude: AVR device initialized and ready to accept instructions
avrdude: device signature = 0x1ea701 (probably m128rfa1)
avrdude: reading flash memory ...

Reading | ################################################## | 100% 0.40 s 

avrdude: writing output file dump

avrdude done.  Thank you.

@stefanrueger
Copy link
Collaborator

@jkent Thanks for your cotribution! Two quick comments

  • You'll have seen the compilation failure for msvc (arm64, ARM64) above
  • I had a quick look at the diff and notice a lot of format changes; we tend to leave the style of previous contributors alone (so we see what's changed; so we can figure more easily out what the history of a certain code section is); that doesn't mean you have to use that style for your own code, but please leave format and style of existing code be

Other than that, once both above are addressed someone on the team can do a review (may take some time...)

@MCUdude
Copy link
Collaborator

MCUdude commented Mar 19, 2023

Thanks for your contribution! Sadly, I don't have any hardware I can test with, but this will in fact be the first non-official hardware that supports AVR JTAG programming!

I had a quick look at the diff and notice a lot of format changes; we tend to leave the style of previous contributors alone (so we see what's changed; so we can figure more easily out what the history of a certain code section is); that doesn't mean you have to use that style for your own code, but please leave format and style of existing code be

@stefanrueger I do agree that leaving old code (formatting) like it already is is a good idea, but I'd argue that "new" code should follow a loose standard to match the look and feel of existing code.

Most of the code base already uses two white spaces as indents. We should continue to do this.

@jkent jkent force-pushed the avrftdi branch 3 times, most recently from f58cad4 to d9f4586 Compare March 19, 2023 18:39
@jkent
Copy link
Contributor Author

jkent commented Mar 19, 2023

Sorry for the noise. Should be good now. I'm not a Windows programmer. :)

Thanks for the feedback. I left the formatting in the style of the original.

@jkent
Copy link
Contributor Author

jkent commented Mar 19, 2023

Wooops, regression fixed from checking out my main branch during reformat.

I have another JTAG programmer that works, but it uses code on an ATmega16u2. I still need to publish that code. If interested, I've added support to AVRDUDE for it too. It is dual role where it by default acts as a USB serial adapter, serial break signal switches to programming mode where it does JTAG operations. Its not nearly as fast as the FTDI MPSSE, but it could be useful to somebody.

@stefanrueger
Copy link
Collaborator

Thanks @jkent Out of curiosity:What's the significance of tdi, tdo, tck and could they be overlaid to sdi, sdo and sck? Not suggesting they shoud, but if they are essentially the same functionality a simpler overlay in lexer.l could be sth like

(tdo|sdo)            { yylval=NULL; ccap(); return K_SDO; }

Externally you could use tdo, tdo, tck but within the program it would be SDI, ...

@jkent
Copy link
Contributor Author

jkent commented Mar 19, 2023

They are the JTAG signals. In terms of the MPSSE, they use the same pins, but on other bitbanging hardware they could have different functionality. I added them for completeness. They also keep you from being confused about the data direction, as the ISP signals are in terms of the host, where the JTAG signals are in terms of the device.

@stefanrueger
Copy link
Collaborator

Thanks for explanation (so sdo corresponds to tdi?). All good.

@jkent
Copy link
Contributor Author

jkent commented Mar 19, 2023

That is correct! In terms of the programmer SDO is an output, and TDO is an input.

@mcuee mcuee added the enhancement New feature or request label Mar 19, 2023
@mcuee
Copy link
Collaborator

mcuee commented Mar 20, 2023

I have another JTAG programmer that works, but it uses code on an ATmega16u2. I still need to publish that code. If interested, I've added support to AVRDUDE for it too. It is dual role where it by default acts as a USB serial adapter, serial break signal switches to programming mode where it does JTAG operations. Its not nearly as fast as the FTDI MPSSE, but it could be useful to somebody.

@jkent

That would be nice to have as well -- probably in a separate PR. I assume the FW can be ported to ATmega32U4 (and therefore Arduino Pro Micro or Leonardo).

@mcuee
Copy link
Collaborator

mcuee commented Mar 20, 2023

@jkent

It is nice to have FTDI MPSSE to work with AVR JTAG. It will open up quite some JTAG adapters to use with AVR JTAG as there are many adapters which are based on FT2232H (mainly for ARM chips using OpenOCD).
I have the original Amontec Jtag Key2, I will try to carry out the test soon.

Comment on lines 1092 to 1195
#------------------------------------------------------------
# tumpa-jtag
#------------------------------------------------------------

programmer parent "tumpa"
id = "tumpa-jtag";
desc = "TIAO USB Multi-Protocol Adapter (JTAG)";
type = "avrftdi_jtag";
sck = ;
sdo = ;
sdi = ;
tck = 0; # TCK 9
tdi = 1; # TDI 5
tdo = 2; # TDO 13
tms = 3; # TMS 7
reset = ; #4; # RST 15
buff = ~11;
prog_modes = PM_JTAG;
;

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use the output of avrdude -ctumpa-jtag/s (the canonical form as understood by avrdude) for the avrdude.conf.in entry. Also, it would help us and improve avrdude.conf if if you could replace the pre-existing (meaningless) comment submitted as bug #46020 with a suitable URL for TUMPA.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the output of avrdude -ctumpa-jtag/s. Is it sutable? or would you prefer a complete new device entry (with usb vid/pid) without the disabled reset/sck/sdo/sdi signals?

#------------------------------------------------------------
# tumpa-jtag
#------------------------------------------------------------

programmer parent "tumpa"
    id                     = "tumpa-jtag";
    desc                   = "TIAO USB Multi-Protocol Adapter (JTAG)";
    type                   = "avrftdi_jtag";
    prog_modes             = PM_JTAG;
    buff                   = ~11;
    reset                  = ; #4; # RST 15
    sck                    = ;
    sdo                    = ;
    sdi                    = ;
    tck                    = 0; # TCK 9
    tdi                    = 1; # TDI 5
    tdo                    = 2; # TDO 13
    tms                    = 3; # TMS 7
;

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ignore this, as per @mariusgreuel , I will parent this off of ft2232h_jtag.

stefanrueger
stefanrueger previously approved these changes Mar 20, 2023
Copy link
Collaborator

@stefanrueger stefanrueger left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had a quick look through the code; it's well written and I did not spot any obvious problems. Once we have an independent functional test (@mcuee?) I think we can merge your contribution. Thanks again

@mcuee mcuee added this to the AVRDUDE 7.2 milestone Mar 20, 2023
@mcuee
Copy link
Collaborator

mcuee commented Mar 20, 2023

I need to figure out the connection first. The following connection does not seem to work.

#------------------------------------------------------------
# jtagkey-jtag
#------------------------------------------------------------

programmer parent "jtagkey"
    id                     = "jtagkey-jtag";
    desc                   = "Amontec JTAGKey, JTAGKey-Tiny and JTAGKey2 (JTAG)";
    type                   = "avrftdi_jtag";
    sck                    = ;
    sdo                    = ;
    sdi                    = ;
    tck                    = 0; # TCK 9
    tdi                    = 1; # TDI 5
    tdo                    = 2; # TDO 13
    tms                    = 3; # TMS 7
    reset                  = ; # 
    buff                   = ~4;
    prog_modes             = PM_JTAG;
;

PS C:\work\avr\avrdude_test\avrdude_bin> .\avrdude_pr1324 -C avrdude_pr1324.conf -c jtagkey-jtag -p m32a -v -B6

avrdude_pr1324: Version 7.1-20230319 (4d0296e)
                Copyright the AVRDUDE authors;
                see https://github.com/avrdudes/avrdude/blob/main/AUTHORS

                System wide configuration file is C:\work\avr\avrdude_test\avrdude_bin\avrdude_pr1324.conf

                Using Port                    : usb
                Using Programmer              : jtagkey-jtag
                Setting bit clk period        : 6.0
                AVR Part                      : ATmega32A
                Chip Erase delay              : 9000 us
                PAGEL                         : PD7
                BS2                           : PA0
                RESET disposition             : possible i/o
                RETRY pulse                   : SCK
                Serial program mode           : yes
                Parallel program mode         : yes
                Timeout                       : 200
                StabDelay                     : 100
                CmdexeDelay                   : 25
                SyncLoops                     : 32
                PollIndex                     : 3
                PollValue                     : 0x53
                Memory Detail                 :

                                                  Block Poll               Page                       Polled
                  Memory Type Alias    Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
                  ----------- -------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
                  eeprom                  4    20    64    0 no       1024    4      0  9000  9000 0xff 0xff
                  flash                  33    10    64    0 yes     32768  128    256  4500  4500 0xff 0x00
                  lfuse                   0     0     0    0 no          1    1      0  2000  2000 0x00 0x00
                  hfuse                   0     0     0    0 no          1    1      0  2000  2000 0x00 0x00
                  lock                    0     0     0    0 no          1    1      0  2000  2000 0x00 0x00
                  signature               0     0     0    0 no          3    1      0     0     0 0x00 0x00
                  calibration             0     0     0    0 no          4    1      0     0     0 0x00 0x00

                Programmer Type : avrftdi_jtag
                Description     : Amontec JTAGKey, JTAGKey-Tiny and JTAGKey2 (JTAG)
                Pin assignment  : 0..7 = DBUS0..7, 8..15 = CBUS0..7
                  VCC     =  (not used)
                  BUFF    = ~4
                  RESET   =  (not used)
                  SCK     =  (not used)
                  SDO     =  (not used)
                  SDI     =  (not used)
                  TCK     =  0
                  TDI     =  1
                  TDO     =  2
                  TMS     =  3
                  ERR LED =  (not used)
                  RDY LED =  (not used)
                  PGM LED =  (not used)
                  VFY LED =  (not used)

avrdude_pr1324: AVR device initialized and ready to accept instructions
avrdude_pr1324: device signature = 0xffffff (probably .xmega) (retrying)
avrdude_pr1324: device signature = 0xffffff (probably .xmega) (retrying)
avrdude_pr1324: device signature = 0xffffff (probably .xmega)
avrdude_pr1324 main() error: Yikes!  Invalid device signature.
avrdude_pr1324 main() error: expected signature for ATmega32A is 1E 95 02
               Double check connections and try again, or use -F to override
               this check.


avrdude_pr1324 done.  Thank you.

JTAGKey2 to FT2232H map:
https://startingelectronics.org/articles/embedded-tools/amontec-info/amontec_jtagkey_flyer_ft2232_map.pdf

Screenshot 2023-03-20 212317

JTAGKey 2 Diagram (JTAGkey 2 using FT2232H, JTAGKey using FT2232L).
https://startingelectronics.org/articles/embedded-tools/amontec-info/amontec_jtagkey_flyer_diagram.pdf
Screenshot 2023-03-20 213027

@mcuee
Copy link
Collaborator

mcuee commented Mar 20, 2023

Debug log.

Click for the detailed debug log with -vvvv
PS C:\work\avr\avrdude_test\avrdude_bin> .\avrdude_pr1324 -C avrdude_pr1324.conf -c jtagkey-jtag -p m32a -vvvv

avrdude_pr1324: Version 7.1-20230319 (4d0296e)
                Copyright the AVRDUDE authors;
                see https://github.com/avrdudes/avrdude/blob/main/AUTHORS

                System wide configuration file is C:\work\avr\avrdude_test\avrdude_bin\avrdude_pr1324.conf

                Using Port                    : usb
                Using Programmer              : jtagkey-jtag
I avrftdi_open(788): Using device VID:PID 0403:cff8 and SN '(null)' on interface A.
D write_flush(513): Setting pin direction (0x0000) and value (0x0000)
T write_flush(525): Set pins command: 80 00 00 82 00 00
I set_frequency(248): Using frequency: 150000
I set_frequency(249): Clock divisor: 0x0027
D avrftdi_check_pins_mpsse(611): Using valid mask mpsse: 0x0000fff0
avrdude_pr1324: <unknown>: pin is OK
avrdude_pr1324: VCC: pin is OK
avrdude_pr1324: BUFF: pin is OK
avrdude_pr1324: RESET: pin is OK
avrdude_pr1324: SCK: pin is OK
avrdude_pr1324: SDO: pin is OK
avrdude_pr1324: SDI: pin is OK
avrdude_pr1324: TCK: pin is OK
avrdude_pr1324: TDI: pin is OK
avrdude_pr1324: TDO: pin is OK
avrdude_pr1324: TMS: pin is OK
avrdude_pr1324: ERRLED: pin is OK
avrdude_pr1324: RDYLED: pin is OK
avrdude_pr1324: PGMLED: pin is OK
avrdude_pr1324: VFYLED: pin is OK
D avrftdi_check_pins_bb(569): Using valid mask bitbanging: 0x0000ffff
avrdude_pr1324: <unknown>: pin is OK
avrdude_pr1324: VCC: pin is OK
avrdude_pr1324: BUFF: pin is OK
avrdude_pr1324: RESET: pin is OK
avrdude_pr1324: SCK: pin is OK
avrdude_pr1324: SDO: pin is OK
avrdude_pr1324: SDI: pin is OK
avrdude_pr1324: TCK: pin is OK
avrdude_pr1324: TDI: pin is OK
avrdude_pr1324: TDO: pin is OK
avrdude_pr1324: TMS: pin is OK
avrdude_pr1324: ERRLED: pin is OK
avrdude_pr1324: RDYLED: pin is OK
avrdude_pr1324: PGMLED: pin is OK
avrdude_pr1324: VFYLED: pin is OK
I avrftdi_pin_setup(722): Pin direction mask: 021b
I avrftdi_pin_setup(723): Pin value mask: 0210
                AVR Part                      : ATmega32A
                Chip Erase delay              : 9000 us
                PAGEL                         : PD7
                BS2                           : PA0
                RESET disposition             : possible i/o
                RETRY pulse                   : SCK
                Serial program mode           : yes
                Parallel program mode         : yes
                Timeout                       : 200
                StabDelay                     : 100
                CmdexeDelay                   : 25
                SyncLoops                     : 32
                PollIndex                     : 3
                PollValue                     : 0x53
                Memory Detail                 :

                                                  Block Poll               Page                       Polled
                  Memory Type Alias    Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
                  ----------- -------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
                  eeprom                  4    20    64    0 no       1024    4      0  9000  9000 0xff 0xff
                                                  Block Poll               Page                       Polled
                  Memory Type Alias    Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
                  ----------- -------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
                  flash                  33    10    64    0 yes     32768  128    256  4500  4500 0xff 0x00
                                                  Block Poll               Page                       Polled
                  Memory Type Alias    Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
                  ----------- -------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
                  lfuse                   0     0     0    0 no          1    1      0  2000  2000 0x00 0x00
                                                  Block Poll               Page                       Polled
                  Memory Type Alias    Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
                  ----------- -------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
                  hfuse                   0     0     0    0 no          1    1      0  2000  2000 0x00 0x00
                                                  Block Poll               Page                       Polled
                  Memory Type Alias    Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
                  ----------- -------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
                  lock                    0     0     0    0 no          1    1      0  2000  2000 0x00 0x00
                                                  Block Poll               Page                       Polled
                  Memory Type Alias    Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
                  ----------- -------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
                  signature               0     0     0    0 no          3    1      0     0     0 0x00 0x00
                                                  Block Poll               Page                       Polled
                  Memory Type Alias    Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
                  ----------- -------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
                  calibration             0     0     0    0 no          4    1      0     0     0 0x00 0x00

                Programmer Type : avrftdi_jtag
                Description     : Amontec JTAGKey, JTAGKey-Tiny and JTAGKey2 (JTAG)
                Pin assignment  : 0..7 = DBUS0..7, 8..15 = CBUS0..7
                  VCC     =  (not used)
                  BUFF    = ~4
                  RESET   = ~9
                  SCK     =  (not used)
                  SDO     =  (not used)
                  SDI     =  (not used)
                  TCK     =  0
                  TDI     =  1
                  TDO     =  2
                  TMS     =  3
                  ERR LED =  (not used)
                  RDY LED =  (not used)
                  PGM LED =  (not used)
                  VFY LED =  (not used)

D set_pin(280): Setting pin 4 (ADBUS4) as BUFF: high (low active)
D write_flush(513): Setting pin direction (0x021b) and value (0x0200)
T write_flush(525): Set pins command: 80 00 1b 82 02 02
D set_pin(280): Setting pin 9 (ACBUS9) as RESET: low (low active)
D write_flush(513): Setting pin direction (0x021b) and value (0x0200)
T write_flush(525): Set pins command: 80 00 1b 82 02 02
D set_pin(280): Setting pin 0 (ADBUS0) as TCK: low (high active)
D write_flush(513): Setting pin direction (0x021b) and value (0x0200)
T write_flush(525): Set pins command: 80 00 1b 82 02 02
D set_pin(280): Setting pin 9 (ACBUS9) as RESET: high (low active)
D write_flush(513): Setting pin direction (0x021b) and value (0x0000)
T write_flush(525): Set pins command: 80 00 1b 82 00 02
avrdude_pr1324: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.01 s

avrdude_pr1324: device signature = 0xffffff (probably .xmega) (retrying)

Reading | ################################################## | 100% 0.01 s

avrdude_pr1324: device signature = 0xffffff (probably .xmega) (retrying)

Reading | ################################################## | 100% 0.01 s

avrdude_pr1324: device signature = 0xffffff (probably .xmega)
avrdude_pr1324 main() [main.c:1349] error: Yikes!  Invalid device signature.
avrdude_pr1324 main() [main.c:1351] error: expected signature for ATmega32A is 1E 95 02
               Double check connections and try again, or use -F to override
               this check.

D write_flush(513): Setting pin direction (0x021b) and value (0x0000)
T write_flush(525): Set pins command: 80 00 1b 82 00 02
D set_pin(280): Setting pin 4 (ADBUS4) as BUFF: low (low active)
D write_flush(513): Setting pin direction (0x021b) and value (0x0010)
T write_flush(525): Set pins command: 80 10 1b 82 00 02
D set_pin(280): Setting pin 9 (ACBUS9) as RESET: high (low active)
D write_flush(513): Setting pin direction (0x021b) and value (0x0010)
T write_flush(525): Set pins command: 80 10 1b 82 00 02
I avrftdi_close(881): LED Mask=0x0000 value =0x0010 &=0x0000
D write_flush(513): Setting pin direction (0x0000) and value (0x0000)
T write_flush(525): Set pins command: 80 00 00 82 00 00

avrdude_pr1324 done.  Thank you.

@mcuee
Copy link
Collaborator

mcuee commented Mar 20, 2023

@mariusgreuel
Just wondering if you have some time to review this PR and see if you can check with your target. Thanks.

@mariusgreuel
Copy link
Contributor

Hi @jkent, thanks for the PR! Have not tried using the programmer yet, but your code looks good!

One note: A lot of people (like myself) have generic FTDI breakout boards, such as the Adafruit FT232H, FT mini modules, etc. I think we can make your FTDI JTAG programmer available to a bigger audience (plus ease testing for myself) if we include configs for generic FT232H and FT2232H boards.

My suggestion would be to add two new configs such as ft232h_jtag and ft2232h_jtag (no parent) using the default USB PIDs 0x6014 and 0x6010, and then derive tumpa-jtag from ft2232h_jtag while changing the USB PID. For an example, see the generic ft232h programmer as a base and the derived boards, such as um232h. Also, the breakout boards often only have the generic pin names (such as AD0 for TCK) on the silkscreen. If you could add these pin names to the signal comments, this would save me from consulting the data sheet.

@jkent
Copy link
Contributor Author

jkent commented Mar 21, 2023

@mcuee I'll take a look at the ATmega32A manual in a bit to see if there are any differences with the programming protocol. I did not implement byte by byte read/write because of its speed, but maybe some chips need it?

@mcuee
Copy link
Collaborator

mcuee commented Mar 21, 2023

@mcuee I'll take a look at the ATmega32A manual in a bit to see if there are any differences with the programming protocol. I did not implement byte by byte read/write because of its speed, but maybe some chips need it?

I tend to think my issue is more related to connection as it failed to read the device signature. I will try again later with ATmega128A to see if that makes any difference. Let's see if @mariusgreuel can have a positive result.

@mcuee
Copy link
Collaborator

mcuee commented Mar 21, 2023

@jkent

I think your current code will not work with my JTAGKey 2 as there are two pins to control the reset signals.

Openocd uses the following convention.
https://github.com/openocd-org/openocd/blob/master/tcl/interface/ftdi/c232hm.cfg

# ---A*BUS-------CCCCCCCC|DDDDDDDD
# --------\______76543210|76543210

Relevant codes to deal with different configuration of FT232H/FT2232H/FT4232H or similar.
https://github.com/openocd-org/openocd/blob/master/src/jtag/drivers/ftdi.c#L742-L793

For tumpa.
https://github.com/openocd-org/openocd/blob/master/tcl/interface/ftdi/tumpa.cfg

ftdi layout_init 0x0038 0x087b
ftdi layout_signal nTRST -data 0x0020 (pin AD5)
ftdi layout_signal nSRST -data 0x0010 (pin AD4)

For JTAGkey2
https://github.com/openocd-org/openocd/blob/master/tcl/interface/ftdi/jtagkey2.cfg

ftdi layout_init 0x0c08 0x0f1b
ftdi layout_signal nTRST -data 0x0100 -noe 0x0400 (pin AC0, enable pin is /AC2)
ftdi layout_signal nSRST -data 0x0200 -noe 0x0800 (pin AC1, enable pin is /AC3)

Other files of reference to avrdude from OpenOCD
https://github.com/openocd-org/openocd/tree/master/tcl/interface/ftdi
https://github.com/openocd-org/openocd/blob/master/tcl/interface/ftdi/minimodule.cfg
https://github.com/openocd-org/openocd/blob/master/tcl/interface/ftdi/kt-link.cfg

@mcuee
Copy link
Collaborator

mcuee commented Mar 21, 2023

@jkent @mariusgreuel @stefanrueger

Still I am okay if we just get the current code merged without modifications. At least many adapters will be supported with the current pull request.

Only things like JTAGkey and KT-Link will not be supported.

KT-Link
https://github.com/openocd-org/openocd/blob/master/tcl/interface/ftdi/kt-link.cfg

ftdi layout_init 0x8c28 0xff3b
ftdi layout_signal nTRST -data 0x0100 -noe 0x0400
ftdi layout_signal nSRST -data 0x0200 -noe 0x0800
ftdi layout_signal LED -data 0x8000
ftdi layout_signal SWD_EN -ndata 0x0020 -oe 0x2000
ftdi layout_signal SWDIO_OE -ndata 0x1000

ktlink

@stefanrueger
Copy link
Collaborator

will not work with my JTAGKey 2 as there are two pins to control the reset signals

Can AVRDUDE's model of pins and external devices cope with the need to control two pins to set the reset signal? What I am trying to get at is there a way the current code base can do this at all with only small changes? Would a hardware mod (cutting wires, some pullup/pulldown for one of the signals) be an alternative?

I am okay if we just get the current code merged without modifications

OK, will merge on the next mergefest, may actually be today's (European ) evening, unless I hear from you to the contrary @jkent @mariusgreuel @MCUdude @mcuee.

@mariusgreuel
Copy link
Contributor

I just tried a few things, today not much seems to work, not my day. Quitting now and saving a serious look at this for another day.

I do not have a m128rf, so I took a m32u4 (the JTAG commands look identical at first glance).

Some sanity checks:

SUCCESS: MSVC with custom libftdi/FTDI driver, FT232H via ISP:

D:\Work\avrdudes\avrdude>out\build\x64-Debug\src\avrdude.exe -c ft232h -p m32u4

avrdude: AVR device initialized and ready to accept instructions
avrdude: device signature = 0x1e9587 (probably m32u4)

avrdude done.  Thank you.

FAILED: MinGW64 with stock libftdi/libusb0 driver, FT232H via ISP:

$ ./build_mingw64/src/avrdude.exe -c ft232h -p m32u4
E avrftdi_open(782): Error -4 occurred: usb_open() failed
avrdude error: unable to open programmer ft232h on port usb

avrdude done.  Thank you.

FAILED: Linux/Ubuntu 22.04 with usbipd-win, FT232H via ISP:

marius@Zeus:/mnt/d/Work/avrdudes/avrdude$ ./build_linux/src/avrdude -c ft232h -p m32u4
E avrftdi_open(782): Error -4 occurred: usb_open() failed
avrdude error: unable to open programmer ft232h on port usb

avrdude done.  Thank you.

SUCCESS: MSVC, Atmel ICE via JTAG:

D:\Work\avrdudes\avrdude>out\build\x64-Debug\src\avrdude.exe -c atmelice -p m32u4

         Vtarget         : 5.01 V
         JTAG clk prog.  : 1000 kHz
         JTAG clk debug  : 1000 kHz

avrdude: AVR device initialized and ready to accept instructions
avrdude: device signature = 0x1e9587 (probably m32u4)

avrdude done.  Thank you.

As only the MSVC build works with the FT232H, I just tried the ft232h_jtag programmer with this configuration. It seems like the
programmer detect a different device signature every time:

D:\Work\avrdudes\avrdude>out\build\x64-Debug\src\avrdude.exe -c ft232h_jtag -p m32u4

avrdude: AVR device initialized and ready to accept instructions
avrdude: device signature = 0x800021
avrdude error: expected signature for ATmega32U4 is 1E 95 87
        double check chip or use -F to override this check

avrdude done.  Thank you.

D:\Work\avrdudes\avrdude>out\build\x64-Debug\src\avrdude.exe -c ft232h_jtag -p m32u4

avrdude: AVR device initialized and ready to accept instructions
avrdude: device signature = 0x21e100
avrdude error: expected signature for ATmega32U4 is 1E 95 87
        double check chip or use -F to override this check

avrdude done.  Thank you.

D:\Work\avrdudes\avrdude>out\build\x64-Debug\src\avrdude.exe -c ft232h_jtag -p m32u4

avrdude: AVR device initialized and ready to accept instructions
avrdude: device signature = 0xe19080
avrdude error: expected signature for ATmega32U4 is 1E 95 87
        double check chip or use -F to override this check

avrdude done.  Thank you.

Note sure what is going on. I used a direct connection, no pull-ups/downs. I have no experience with the JTAG/AVR protocol, but I am wondering:

  • Do the FTDIs need pull-ups/downs to work with JTAG?
  • Is a m32u4 supposed to work with this programmer? Generally speaking, which devices would work?

@mcuee I can't remember whether I tried the FT232H programmers with MinGW/libftdi/libusb0, do they still work for you?

@stefanrueger
Copy link
Collaborator

Decided to leave this PR hanging around until the next time as there might be a few insights that come from more testing...

@mcuee
Copy link
Collaborator

mcuee commented Mar 22, 2023

@mcuee I can't remember whether I tried the FT232H programmers with MinGW/libftdi/libusb0, do they still work for you?

@mariusgreuel

I was using MinGW/libftdi-1.0/libusb-1.0 with my FT2232H based JTAGkey 2 and it worked fine last time.

I will check again the ISP mode with latest git and this PR to see if there are any regressions.

As for MinGW/libftdi-0.1/libusb-win32 or MinGW/libftdi-0.1/libusb-compat-0.1 combination, I have not tried it since libftdi-0.1 has not been updated for a long time (last commit was on 2014-12-23, last release was on 2012-03-19).
http://developer.intra2net.com/git/?p=libftdi;a=shortlog;h=refs/heads/libftdi-0.x

@stefanrueger
Copy link
Collaborator

I reviewed all usleep() in avrftdi.c. They look good with exception of Line 958, where I would have expected usleep(20 * 1000) instead of usleep(20). I am not sure I can draw much info from this comment, which I would have deleted (I am petty sure this comment pre-existed your code @jkent but still I'd delete it while we are at it).

@stefanrueger
Copy link
Collaborator

Then there is Issue #379 (treating the usersig memory for some special parts in JTAG). Would be great if this PR was to extend to usersig. The relevant pages are in this datasheet, pages 525-39 and, in particular, pages 538-9:

Screenshot from 2023-06-20 16-47-08

@MCUdude
Copy link
Collaborator

MCUdude commented Jun 20, 2023

So, maybe sleep a bit (say 10 ms or sth like usleep(m->max_write_delay); at the start of every avrftdi_jtag_paged_read() or after the read page command is issued?

I tried adding usleep(m->max_write_delay); and usleep(20); several places in avrftdi_jtag_paged_read(), but I'm still having the same read issue.

I reviewed all usleep() in avrftdi.c. They look good with exception of Line 958, where I would have expected usleep(20 * 1000) instead of usleep(20). I am not sure I can draw much info from this comment, which I would have deleted (I am petty sure this comment pre-existed your code @jkent but still I'd delete it while we are at it).

This didn't work very well:

$./avrdude -cft2232h_jtag -patmega16 -t
avrdude: AVR device initialized and ready to accept instructions
avrdude: device signature = 0x1e9403 (probably m16)
avrdude> read flash 0 0x200
Reading | -------------------------------------------------- | 0% 0.00 s 
avrftdi.c:1352 avrftdi_jtag_ir_out() ftdi_write_data(pdata->ftdic, buf, ptr - buf) != ptr - buf: Undefined error: 0 (0)
	usb bulk write failed
avrftdi.c:1393 avrftdi_jtag_dr_out() ftdi_write_data(pdata->ftdic, buf, ptr - buf) != ptr - buf: Undefined error: 0 (0)
	usb bulk write failed
avrftdi.c:1393 avrftdi_jtag_dr_out() ftdi_write_data(pdata->ftdic, buf, ptr - buf) != ptr - buf: Undefined error: 0 (0)
	usb bulk write failed
avrftdi.c:1393 avrftdi_jtag_dr_out() ftdi_write_data(pdata->ftdic, buf, ptr - buf) != ptr - buf: Undefined error: 0 (0)
	usb bulk write failed
avrftdi.c:1393 avrftdi_jtag_dr_out() ftdi_write_data(pdata->ftdic, buf, ptr - buf) != ptr - buf: Undefined error: 0 (0)
	usb bulk write failed
avrftdi.c:1352 avrftdi_jtag_ir_out() ftdi_write_data(pdata->ftdic, buf, ptr - buf) != ptr - buf: Undefined error: 0 (0)
	usb bulk write failed
avrftdi.c:1776 avrftdi_jtag_paged_read() ftdi_write_data(pdata->ftdic, buf, ptr - buf) != ptr - buf: Undefined error: 0 (0)
	usb bulk write failed
avrdude error: unable to read flash page at addr 0x0000
avrdude error: (read) error reading flash address 0x00000 of part ATmega16
               read operation not supported on memory type flash
avrdude> quit
avrftdi.c:1352 avrftdi_jtag_ir_out() ftdi_write_data(pdata->ftdic, buf, ptr - buf) != ptr - buf: Operation timed out (60)
	usb bulk write failed
avrftdi.c:1393 avrftdi_jtag_dr_out() ftdi_write_data(pdata->ftdic, buf, ptr - buf) != ptr - buf: Operation timed out (60)
	usb bulk write failed
avrftdi.c:1393 avrftdi_jtag_dr_out() ftdi_write_data(pdata->ftdic, buf, ptr - buf) != ptr - buf: Operation timed out (60)
	usb bulk write failed
avrftdi.c:1352 avrftdi_jtag_ir_out() ftdi_write_data(pdata->ftdic, buf, ptr - buf) != ptr - buf: Operation timed out (60)
	usb bulk write failed
avrftdi.c:1393 avrftdi_jtag_dr_out() ftdi_write_data(pdata->ftdic, buf, ptr - buf) != ptr - buf: Operation timed out (60)
	usb bulk write failed
avrftdi.c:1352 avrftdi_jtag_ir_out() ftdi_write_data(pdata->ftdic, buf, ptr - buf) != ptr - buf: Operation timed out (60)
	usb bulk write failed
avrftdi.c:1393 avrftdi_jtag_dr_out() ftdi_write_data(pdata->ftdic, buf, ptr - buf) != ptr - buf: Operation timed out (60)
	usb bulk write failed
avrftdi.c:523 write_flush() ftdi_write_data(pdata->ftdic, buf, 6) != 6: Operation timed out (60)
	usb bulk write failed
avrftdi.c:523 write_flush() ftdi_write_data(pdata->ftdic, buf, 6) != 6: Operation timed out (60)
	usb bulk write failed

avrdude done.  Thank you.

@stefanrueger
Copy link
Collaborator

@MCUdude Thanks for testing. Admittedly, my ideas were a tad bit naïve (as was the allowfullbitstream shout b/c this parameter isn't used at all here).

@jkent
Copy link
Contributor Author

jkent commented Jun 20, 2023

Something worth trying is adding some JTAG clocks in the Run-Test/Idle state. I need to port over my overhauled Python code that does FTDI JTAG, it would make this much better/easier. (I've written some nifty debug code that uses the undocumented OCDR register)

@mcuee
Copy link
Collaborator

mcuee commented Jun 20, 2023

Something worth trying is adding some JTAG clocks in the Run-Test/Idle state. I need to port over my overhauled Python code that does FTDI JTAG, it would make this much better/easier. (I've written some nifty debug code that uses the undocumented OCDR register)

@jkent

Just wondering if you can add some debug message to this PR (for the JTAG functions) to help debugging this issue. Thanks.

@stefanrueger
Copy link
Collaborator

Another option would be to document that this programmer does not work for older JTAG parts and make sure the code does not try to, for example by

diff --git a/src/avrftdi.c b/src/avrftdi.c
index 22acf97..6b5708d 100644
--- a/src/avrftdi.c
+++ b/src/avrftdi.c
@@ -1464,6 +1464,11 @@ static int avrftdi_jtag_dr_inout(const PROGRAMMER *pgm, unsigned int dr,
 
 static void avrftdi_jtag_enable(PROGRAMMER *pgm, const AVRPART *p)
 {
+	if(p->flags & AVRPART_ALLOWFULLPAGEBITSTREAM) { // Proxy test for ATmega(16|32|64|128)(A|)
+		pmsg_error("programmer type %s does not work for %s\n", pgm->type, p->desc);
+		exit(0);
+	}
+
 	pgm->powerup(pgm);
 
 	set_pin(pgm, PIN_AVR_RESET, OFF);

@mcuee
Copy link
Collaborator

mcuee commented Jun 24, 2023

Another option would be to document that this programmer does not work for older JTAG parts and make sure the code does not try to, for example by

I think this is the way to go for now. This PR is a significant improvement for avrdude so it is worth to merge even with the known issue.

@cederom
Copy link
Contributor

cederom commented Jun 25, 2023

Agreed! What is here is here, more can be added when ready, just a clear message / warning what is working already and what needs work would be nice :-)

I am following the thread but am too overworked right now to test / help at the moment please forgive me!

@stefanrueger
Copy link
Collaborator

just a clear message / warning what is working already

We actually don't know. We only hypothesise that this PR works for classic JTAG parts other than ATmega(16|32|64|128)(A|). We also know that this PR won't be able to read/write the usersig memory of ATmega*RF(A1|R2) parts, see PR #1406

@stefanrueger
Copy link
Collaborator

stefanrueger commented Jun 29, 2023

@jkent Here another idea what the problem might be: the JTAG sequences for the ATmega32U

atmega32u4-jtag-flash-read

and the ATmega16

atmega16-jtag-flash-read

are actually different! Similarly, flash write seems to want the extended address byte, too, for the ATmega32U. Your PR implements the protocol variant with the extended address bytes.

If that hypothesis is correct then it's this line in avrftdi_jtag_paged_write() and this line in avrftdi_jtag_paged_load() that would need to be only executed for the JTAG protocol using the extended address.

Should this get us further then it's a bit of work to go through the data sheets of the 80 parts that support JTAG to see which is which. This command gives the list of JTAG parts:

$ avrdude -p*/d | grep PM_JTAG | cut -f2 -d"'"

The good news is that many of these parts are covered by a single data sheet, so there are a lot fewer than 80 data sheets to consult. Once that is figured out there might be a simple proxy, eg,

  if((p->prog_modes & (PM_JTAG | PM_JTAGmkI)) == PM_JTAG)
    avrftdi_jtag_dr_out(pgm, 0x0b00 | ((addr >> 17) & 0xff), 15);

or we might have to invent a new bit for the p->flags parameter, eg,

#define AVRPART_JTAG_LEA      64 // Part wants JTAG flash access to load extended addresses

to distinguish these two different protocols and a corresponding jtag_lea = yes/no; in avrdude.conf. But let's cross this bridge when we come to it.

@stefanrueger stefanrueger dismissed their stale review June 29, 2023 17:42

Approval withdrawn b/c it turns out there are (at least) 2 different JTAG protocols that need to be catered for.

@stefanrueger
Copy link
Collaborator

stefanrueger commented Jun 29, 2023

Another idea is to check whether the JTAG LEA sequence is needed for parts that don't actually have a 22-bit PC. If so,

  if(m->size > 0x20000)
    avrftdi_jtag_dr_out(pgm, 0x0b00 | ((addr >> 17) & 0xff), 15);

might work as well. Depends on implementation of the JTAG protocol in the chip. I would feel slightly more happy if the data sheets supported that approach somehow, eg, if it mentioned that the LEA sequence is optional for small parts.

@MCUdude
Copy link
Collaborator

MCUdude commented Jun 29, 2023

Another idea is to check whether the JTAG LEA sequence is needed for parts that don't actually have a 22-bit PC

  if(m->size > 0x20000)
    avrftdi_jtag_dr_out(pgm, 0x0b00 | ((addr >> 17) & 0xff), 15);
  if((p->prog_modes & (PM_JTAG | PM_JTAGmkI)) == PM_JTAG)
    avrftdi_jtag_dr_out(pgm, 0x0b00 | ((addr >> 17) & 0xff), 15);

I tried both of these in avrftdi_jtag_paged_write() and in avrftdi_jtag_paged_load(). However, the result is the same when reading the ATmega16 flash memory.

The flash is empty, but Avrdude still reports that there is content:

$./avrdude -cft2232h_jtag -patmega16 -T 'read flash 0 0x110'
avrdude: AVR device initialized and ready to accept instructions
avrdude: device signature = 0x1e9403 (probably m16)

avrdude: processing -T read flash 0 0x110
Reading | ################################################## | 100% 0.04 s 
0000  00 ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
0010  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
0020  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
0030  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
0040  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
0050  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
0060  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
0070  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
0080  40 ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |@...............|
0090  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
00a0  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
00b0  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
00c0  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
00d0  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
00e0  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
00f0  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
0100  80 ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|

avrdude done.  Thank you.

@stefanrueger
Copy link
Collaborator

Oh well, so there is only one protocol after all, and I guess it's optional to send the JTAG LEA sequence with the address (if the size of flash doesn't require it). So we are back to square one.

@stefanrueger stefanrueger mentioned this pull request Jul 1, 2023
@MCUdude
Copy link
Collaborator

MCUdude commented Jul 1, 2023

I've just tested this PR with the following hardware, and I'm able to read and write to flash without any issues on all of them:

  • ATmega2561
  • ATmega1284P
  • ATmega1281
  • ATmega645
  • AT90CAN128
  • ATmega169PA
  • ATmega165P

I wasn't able to get the ATmega162 working, but I suspect it is a hardware issue of some sort:

$./avrdude -cft2232h_jtag -patmega162
avrdude: AVR device initialized and ready to accept instructions
avrdude: device signature = 0xffffff (probably .xmega) (retrying)
avrdude: device signature = 0xffffff (probably .xmega) (retrying)
avrdude: device signature = 0xffffff (probably .xmega)
avrdude error: Yikes!  Invalid device signature.
avrdude error: expected signature for ATmega162 is 1E 94 04
        Double check connections and try again, or use -F to override
        this check.


avrdude done.  Thank you.

@stefanrueger
Copy link
Collaborator

@MCUdude

Thanks, that's great. What about the ATmega2560 and AT90CAN64?

@jkent @MCUdude @mcuee BTW, how is the TCK frequency controlled for the communication? The data sheets say "During programming the clock frequency of the TCK Input must be less than the maximum frequency of the chip." How does the code ensure the TCK frequency is not too fast?

@MCUdude
Copy link
Collaborator

MCUdude commented Jul 1, 2023

What about the ATmega2560 and AT90CAN64?

@mcuee had already tested the ATmega2560 with success, and it turned out that I didn't actually own a CAN64, only a CAN128. However, I see no reason why these should behave differently.

BTW, how is the TCK frequency controlled for the communication?

By using the -B flag. It does in fact slow down the programmer but doesn't resolve the ATmega16/32/64/128 flash read issue, sadly. I'm not sure how we could get to the bottom of this. But other than these four chips, I think the PR is good to go

@stefanrueger
Copy link
Collaborator

stefanrueger commented Jul 4, 2023

Here a summary of what works and what does not and what is not tested. Parts that appear on the same datasheet are put on one line; it's assumed if one of these works then the others do too:

OK? Tested Datasheet
✔️ AT90CAN128 AT90CAN128 AT90CAN32 AT90CAN64
AT90USB1286 AT90USB1287 AT90USB646 AT90USB647
x ATmega128
ATmega128A ATmega128A
✔️ ATmega2560 ATmega2561 ATmega1281 ATmega1280 ATmega1281 ATmega2560 ATmega2561 ATmega640
✔️ ATmega1284P ATmega1284 ATmega1284P ATmega164A ATmega164PA ATmega324A ATmega324PA ATmega644A ATmega644PA
✔️ ATmega128RFA1 ATmega128RFA1
ATmega1284RFR2 ATmega2564RFR2 ATmega644RFR2
ATmega128RFR2 ATmega256RFR2 ATmega64RFR2
ATmega16 ATmega16
ATmega16A ATmega16A
ATmega162
ATmega164P ATmega324P ATmega644P
ATmega165
ATmega165A ATmega165PA ATmega3250A ATmega3250PA ATmega325A ATmega325PA ATmega6450A ATmega6450P ATmega645A ATmega645P
✔️ ATmega165P ATmega165P
ATmega169
ATmega169P
✔️ ATmega169PA ATmega169A ATmega169PA ATmega3290A ATmega3290PA ATmega329A ATmega329PA ATmega6490A ATmega6490P ATmega649A ATmega649P
✔️ ATmega32U4 ATmega16U4 ATmega32U4
x ATmega32
ATmega32A ATmega32A
ATmega324PB
ATmega3250P ATmega325P
✔️ ATmega645 ATmega325 ATmega3250 ATmega645 ATmega6450
ATmega329 ATmega3290 ATmega649 ATmega6490
ATmega3290P ATmega329P
ATmega406
x ATmega64
ATmega64A ATmega64A
ATmega644

What do people make of this?

  • Do not merge yet?
  • Merge but only program parts that have been tested OK?
  • Merge but only program parts that have been tested OK plus those on the same datasheet?
  • Merge but refuse to program when we know a "similar" part won't program flash, ie, exclude m(16|32|64|128)(|a)?
  • Merge but refuse to run this programmer when we know the part won't program flash?

As it's the flash read routine that might go wrong, it's easy to imagine things can silently go wrong (not good).

@mcuee
Copy link
Collaborator

mcuee commented Jul 5, 2023

I have updated the above table after testing ATmega64A. It failed as expected.

To me we can merge this PR and not to program known-bad parts ATmega8/16/32/64/128(|A).

@MCUdude
Copy link
Collaborator

MCUdude commented Jul 5, 2023

I'm comfortable with this option:

Merge but refuse to program when we know a "similar" part won't program flash, ie, exclude m(16|32|64|128)(|a)?

I'm pretty confident that only the "older" parts don't work. And as long as this PR doesn't affect other programmers/parts in any way, I'm fine with merging this. However, we should try our best to make it work for the old parts as well.

The use of exit() is brought about by the fact that, unlike all other
programming functions, pgm->enable() is of type void, ie, cannot easily
tell the caller something went wrong.
@stefanrueger
Copy link
Collaborator

This PR should now be ready for merging. @mcuee @jkent @mariusgreuel @MCUdude: final tests/comments, please.

I've resolved the merge conflict and added code that rejects programming parts that are known to be incompatible with avrftdi_jtag. I opted for exit(1) in the pgm->enable() function for the simple reason that this function has return type void, ie, cannot easily tell the caller it wasn't able to progress. pgm->enable() is the first opportunity during programming where the programmer learns of the part that it is dealing with.

This PR won't be able to read/write the usersig memory of ATmega*RF(A1|R2) parts, see PR #1406. That would require someone with such a part to code this.

@stefanrueger stefanrueger merged commit 0c2f2e6 into avrdudes:main Aug 4, 2023
10 checks passed
@mcuee mcuee added this to the AVRDUDE 7.3 milestone Oct 12, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants