Author Topic: Debug DUE/DigiX via JTAG  (Read 28629 times)

gogol

  • Sr. Member
  • ****
  • Posts: 398
Debug DUE/DigiX via JTAG
« on: January 16, 2014, 01:35:10 am »
As the DigiX has an JTAG,  I started evaluating how I can do On-Chip-Debugging over the JTAG.

So I took my FT232H cable (see: http://digistump.com/board/index.php/topic,1127.0.html) and connected the JTAG-relevant Pins to the DigiX.
Code: [Select]
ADBUS0 D0 TCK/SK
ADBUS1 D1 TDI/DO
ADBUS2 D2 TDO/DI
ADBUS3 D3 TMS/CS
GND  to GND

Second I installed OpenOCD (http://openocd.sourceforge.net/)
I created a new interface-script in /usr/local/share/openocd/scripts/interface/FT232H.cfg

Code: [Select]
interface ftdi
#ftdi_device_desc "FT232H"
ftdi_vid_pid 0x0403 0x6014

ftdi_layout_init 0x0018 0x05fb

I had to add a udev-rule in /etc/udev/rules.d:
Code: [Select]
# FTDI FT232H
ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6014", MODE="664", GROUP="plugdev"

Than I started the ARDUINO-IDE and compiled the Blink-Example.  I checked, where the /tmp-Directory for the build was created and moved the whole content of that directory in a new generated testdirectory.  For later debugging I need to copy the Blink.ino file from the Examples as well to that directory, otherwise the debugger will not find it.

I created in that new test-directory a file called openocd.cfg
Code: [Select]
source [find interface/FT232H.cfg]
source [find target/at91sam3ax_8x.cfg]
gdb_memory_map disable

than I changed into that directory and started openocd, which identified the Atmel on the DigiX-board.

Code: [Select]
Info : only one transport option; autoselect 'jtag'
adapter speed: 500 kHz
adapter_nsrst_delay: 100
jtag_ntrst_delay: 100
cortex_m reset_config sysresetreq
Info : clock speed 500 kHz
Info : JTAG tap: sam3.cpu tap/device found: 0x4ba00477 (mfg: 0x23b, part: 0xba00, ver: 0x4)
Info : sam3.cpu: hardware has 6 breakpoints, 4 watchpoints

The DigiX was running at that time the Blink-Example.

I connected via telnet to openocd: telnet localhost:4444

with the command reset halt I was able to stop the running program, with reset run it continued. So far, so good.

next I stopped the mcu with reset halt and tried:
at91sam3 info which delivered the following output:
Code: [Select]
    CKGR_MOR: [0x400e0420] -> 0x00000000
    MOSCXTEN:     0 [0x0000] (main xtal enabled: NO)
    MOSCXTBY:     0 [0x0000] (main osc bypass: NO)
    MOSCRCEN:     0 [0x0000] (onchip RC-OSC enabled: NO)
     MOSCRCF:     0 [0x0000] (onchip RC-OSC freq: 4 MHz)
    MOSCXTST:     0 [0x0000] (startup clks, time= 0.000000 uSecs)
     MOSCSEL:     0 [0x0000] (mainosc source: internal RC)
       CFDEN:     0 [0x0000] (clock failure enabled: NO)
   CKGR_MCFR: [0x400e0424] -> 0x00000000
    MAINFRDY:     0 [0x0000] (main ready: NO)
       MAINF:     0 [0x0000] (0.000 Mhz (32.768khz slowclk)
  CKGR_PLLAR: [0x400e0428] -> 0x00000000
        DIVA:     0 [0x0000]
        MULA:     0 [0x0000]
PLLA Freq: (Disabled,mula = 0)
   CKGR_UCKR: [0x400e041c] -> 0x00000000
    PMC_FSMR: [0x400e0470] -> 0x00000000
    PMC_FSPR: [0x400e0474] -> 0x00000000
     PMC_IMR: [0x400e046c] -> 0x00000000
    PMC_MCKR: [0x400e0430] -> 0x00000000
         CSS:     0 [0x0000] slowclk (0.033 Mhz)
        PRES:     0 [0x0000] (selected clock)
Result CPU Freq: 0.033
    PMC_PCK0: [0x400e0440] -> 0x000001ff
    PMC_PCK1: [0x400e0444] -> 0x000001ff
    PMC_PCK2: [0x400e0448] -> 0x000001ff
    PMC_PCSR: [0x400e0418] -> 0x00000000
    PMC_SCSR: [0x400e0408] -> 0x00000000
      PMC_SR: [0x400e0468] -> 0x00000000
 CHIPID_CIDR: [0x400e0740] -> 0x285e0a60
     Version:     0 [0x0000]
       EPROC:     3 [0x0003] cortex-m3
     NVPSIZE:    10 [0x000a] 512K bytes
    NVPSIZE2:     0 [0x0000] none
    SRAMSIZE:    14 [0x000e] 96K Bytes
        ARCH:   133 [0x0085] ATSAM3XxE Series (144-pin version)
      NVPTYP:     2 [0x0002] embedded flash memory
       EXTID:     0 [0x0000] (exists: NO)
CHIPID_CIDR2: [0x400e0940] -> 0x285e0a60
     Version:     0 [0x0000]
       EPROC:     3 [0x0003] cortex-m3
     NVPSIZE:    10 [0x000a] 512K bytes
    NVPSIZE2:     0 [0x0000] none
    SRAMSIZE:    14 [0x000e] 96K Bytes
        ARCH:   133 [0x0085] ATSAM3XxE Series (144-pin version)
      NVPTYP:     2 [0x0002] embedded flash memory
       EXTID:     0 [0x0000] (exists: NO)
 CHIPID_EXID: [0x400e0744] -> 0x00000000
CHIPID_EXID2: [0x400e0944] -> 0x00000000
   rc-osc: 0.000 MHz
  mainosc: 0.000 MHz
     plla: 0.000 MHz
 cpu-freq: 0.033 MHz
mclk-freq: 0.033 MHz
 UniqueId: 0x53323120 0x35373136 0x31303220 0x38303079

Now I checked  the gpnvw bits with:  at91sam3 gpnvm
Code: [Select]
sam3-gpnvm0: 0
sam3-gpnvm1: 1
sam3-gpnvm2: 0
which showed, that the DigiX was currently booting to the firmware in the flash.

With at91sam3 gpnvm clr 1 I cleared the bit 1, and pressed reset on the digix.

The DigiX booted now -as expected- in the SAM-BA mode, and the program was not running!

lsusb showed:
Code: [Select]
Bus 001 Device 033: ID 03eb:6124 Atmel Corp. at91sam SAMBA bootloader
Next I entered at91sam3 gpnvm set 1 followed by reset init and reset run

The DigiX restarted, the Blink-Example was running, and lsusb showed:
Code: [Select]
Bus 001 Device 004: ID 2341:003e

So far, so good. Now I wished to upload code through JTAG. I erased the FLASH of the DigiX by pressing flash and resetted the device.

Now I entered: program Blink.cpp.elf verify reset, which brought unfortunately the following result:

Code: [Select]
JTAG tap: sam3.cpu tap/device found: 0x4ba00477 (mfg: 0x23b, part: 0xba00, ver: 0x4)
target state: halted
target halted due to debug-request, current mode: Thread
xPSR: 0x01000000 pc: 0x00080160 msp: 0x20088000
** Programming Started **
auto erase enabled
sam3 auto-erases while programming (request ignored)
wrote 16384 bytes from file Blink.cpp.elf in 2.188816s (7.310 KiB/s)
** Programming Finished **
** Verify Started **
checksum mismatch - attempting binary compare
diff 0 address 0x0008044c. Was 0x01 instead of 0x4f
diff 1 address 0x0008044d. Was 0xf0 instead of 0xf4
diff 2 address 0x0008044e. Was 0xa2 instead of 0x40
diff 3 address 0x0008044f. Was 0xf8 instead of 0x12
....
diff 126 address 0x000804e1. Was 0x48 instead of 0x01
diff 127 address 0x000804e2. Was 0x00 instead of 0x07
More than 128 errors, the rest are not printed.
** Verify Failed **
** Resetting Target **
JTAG tap: sam3.cpu tap/device found: 0x4ba00477 (mfg: 0x23b, part: 0xba00, ver: 0x4)
shutdown command invoked
> Connection closed by foreign host.

I tried several other ways to write the program to the digiX, direct to the flash-bank, as binary-file instead of elf, however I got all the time verification errors.
After some research I found in the Atmel reference (datasheet) the following information:

49.2.1.1 Flash: Flash Programming
When writing data into the Flash memory plane (either through the EEFC, using the IAP function
or FFPI), the data may not be correctly written (i.e the data written is not the one expected).
Problem Fix/Workaround
Set the number of Wait States (WS) at 6 (FWS = 6) during the programming


Now I am currently stuck. Is that the problem, I am running in?  How can I overcome it?
Has anyone else tried already, to program a DigiX or Due via JTAG?

It should be also possible to debug a program, which was loaded through SAM-BA, which makes it necessary to connect the DigiX with two connections and some more workaround in handling.

If others are interested in debugging the DUE, please add information to this thread.


« Last Edit: January 17, 2014, 01:35:40 am by gogol »

gogol

  • Sr. Member
  • ****
  • Posts: 398
Re: Debug DUE/DigiX via JTAG
« Reply #1 on: January 17, 2014, 01:32:51 am »
Further research shows, that I went down the wrong way.  The silicon bug, which needs 6 waitstates is covered in the NOR-flash part of openocd.
Finally I realized, that my problem was caused from virtualbox USB-driver.  As soon as I went to a bare metal machine, everything worked as expected.

Entering the line : program Blink.cpp.elf verify in the openOCD telnet session, I received the following result:

Code: [Select]
JTAG tap: sam3.cpu tap/device found: 0x4ba00477 (mfg: 0x23b, part: 0xba00, ver: 0x4)
target state: halted
target halted due to debug-request, current mode: Thread
xPSR: 0x01000000 pc: 0x00080180 msp: 0x20088000
** Programming Started **
auto erase enabled
sam3 auto-erases while programming (request ignored)
wrote 16384 bytes from file Blink.cpp.elf in 2.036943s (7.855 KiB/s)
** Programming Finished **
** Verify Started **
verified 10344 bytes in 0.261456s (38.636 KiB/s)
** Verified OK **
shutdown command invoked
> Connection closed by foreign host.

Instead of starting openocd and talking via telnet to it, uploading the file can also be done on the openocd command line:
openocd -f interface/FT232H.cfg -f target/at91sam3ax_8x.cfg  -c "program Blink.cpp.elf verify"


Next, you need to install the arm-toolchain, if not already available on your system. For Ubuntu do it like:
https://launchpad.net/~terry.guo/+archive/gcc-arm-embedded

Make sure, that it is the gcc-arm-none-eabi and not the gcc-arm-linux-eabi . The last toolchain is meant to create programs for ARM based linux servers. We need that one, where the created program runs on bare metal without an supporting os under it.

In addition install ddd, to have a graphical frontend for debugging.

Make sure, that the gpnvm bit 1 is set, so that the first program will run, instead the SAM-BA bootloader.

Go into the testdirectory, make sure, that openocd is running and the DigiX is connected.

Enter: ddd --eval-command="target remote localhost:3333" --debugger arm-none-eabi-gdb Blink.cpp.elf

In the debugger enter the following three lines:
Code: [Select]
mon reset init
set remote hardware-breakpoint-limit 6
set remote hardware-watchpoint-limit 4

start debugging!



ToDos: 
  • Figure out, how to enable adaptive clocking, to speed up the connection.  One of the GPIOs of the FT232H needs to be connected for that.
  • Figure out, how to enable an master-reset with another GPIO-line
  • Create config files for gdb
  • ...





gogol

  • Sr. Member
  • ****
  • Posts: 398
No Adaptive Clocking
« Reply #2 on: January 19, 2014, 06:36:24 am »
Ok, what I learned now is, that the Cortex-M does not support adaptive Clocking.

So the JTAG-Adapter starts up with 5 kHz, as that is 1/6 of the 32kHz the SAM3x has during startup.  JTAG-speed needs to be less than 1/6 of the Core-Clock.

Reading the OpenOCD documentation, there needs to be a board-configuration written, which contains the same steps initializing the higher clock of the controller during init. After that JTAG-clock can go up  to 14MHz (which is 1/6 of the 84 MHz the Digix/Due is running initialized).

That means, instead just using the target -f target/at91sam3ax_8x.cfg a configuration file boards/arduino-due--digix.cfg needs to be created, which will include the target and extend it with an additional configuration.

Taking the example from the openocd documentation, i think, that this needs to look like:

Code: [Select]
### board_file.cfg ###
# source target file that does most of the config in init_targets
source [find target/at91sam3ax_8x.cfg]

proc enable_fast_clock {} {
# enables fast on-board clock source
# configures the chip to use it
#
}
# initialize only board specifics - reset, clock, adapter frequency
proc init_board {} {
reset_config trst_and_srst trst_pulls_srst
$_TARGETNAME configure -event reset-init {
adapter_khz 5
enable_fast_clock
adapter_khz 14000
}
}

When checking the Arduino-Startup-Code the Initialization is done in the procedure void SystemInit(void), which is found in hardware/arduino/sam/system/CMSIS/Device/ATMEL/sam3xa/source/system_sam3xa.c

Code: [Select]
void SystemInit(void)
{
/* Set FWS according to SYS_BOARD_MCKR configuration */
EFC0->EEFC_FMR = EEFC_FMR_FWS(4);
EFC1->EEFC_FMR = EEFC_FMR_FWS(4);

/* Initialize main oscillator */
if (!(PMC->CKGR_MOR & CKGR_MOR_MOSCSEL)) {
PMC->CKGR_MOR = SYS_CKGR_MOR_KEY_VALUE | SYS_BOARD_OSCOUNT |
                     CKGR_MOR_MOSCRCEN | CKGR_MOR_MOSCXTEN;
while (!(PMC->PMC_SR & PMC_SR_MOSCXTS)) {
}
}

/* Switch to 3-20MHz Xtal oscillator */
PMC->CKGR_MOR = SYS_CKGR_MOR_KEY_VALUE | SYS_BOARD_OSCOUNT |
                           CKGR_MOR_MOSCRCEN | CKGR_MOR_MOSCXTEN | CKGR_MOR_MOSCSEL;

while (!(PMC->PMC_SR & PMC_SR_MOSCSELS)) {
}
  PMC->PMC_MCKR = (PMC->PMC_MCKR & ~(uint32_t)PMC_MCKR_CSS_Msk) |
                     PMC_MCKR_CSS_MAIN_CLK;
while (!(PMC->PMC_SR & PMC_SR_MCKRDY)) {
}

/* Initialize PLLA */
PMC->CKGR_PLLAR = SYS_BOARD_PLLAR;
while (!(PMC->PMC_SR & PMC_SR_LOCKA)) {
}

/* Switch to main clock */
PMC->PMC_MCKR = (SYS_BOARD_MCKR & ~PMC_MCKR_CSS_Msk) | PMC_MCKR_CSS_MAIN_CLK;
while (!(PMC->PMC_SR & PMC_SR_MCKRDY)) {
}

/* Switch to PLLA */
PMC->PMC_MCKR = SYS_BOARD_MCKR;
while (!(PMC->PMC_SR & PMC_SR_MCKRDY)) {
}

SystemCoreClock = CHIP_FREQ_CPU_MAX;
}

That code needs to be rewritten to TCL, so that OOCD can use it, to initialize the sam3x8e during start.

Any TCL-expert here?

« Last Edit: January 19, 2014, 10:58:02 am by gogol »

dfarrell

  • Newbie
  • *
  • Posts: 30
Re: Debug DUE/DigiX via JTAG
« Reply #3 on: January 21, 2014, 08:39:45 am »
Can't the script be sent via gdb?

As I recall this is what I did with the Due using a AT91SAM-ICE and Sourcery codebench.  The AT91SAME-ICE is reasonably priced, not quite as inexpensive as your approach but works well for me.  Customizing SAM-BA needs some tcl too, so probably tcl in either case.

Nice collection of instructions!

gogol

  • Sr. Member
  • ****
  • Posts: 398
Re: Debug DUE/DigiX via JTAG
« Reply #4 on: January 21, 2014, 09:08:52 am »
Right now everything works, you can debug and upload scripts.
The only problem is, that it is somewhat slow, as you need to start with an JTAG speed, which is 1/6 of the initial clock.
Once you stepped with the debugger over the initialization, you can enter "adapter_khz 14000" in the telnet session, and things go really fast!

With the initialization script, the CPU would go fast from the first debug statement, as it would be part of initialization.

I have no experience yet, sending script through gdb. How you manage in that case, that this is executed before your firmware and than the debugger jumps to your firmware and stops?

The advantage from the OOCD initialization-script is, that this happens, while the CPU is stopped.  The only things, which happen, is that some memory mapped registers are written and read, which influence the behaviour of the Power Management Controller.  GDB-scripts by my current understanding need to run on the target-cpu.


dfarrell

  • Newbie
  • *
  • Posts: 30
Re: Debug DUE/DigiX via JTAG
« Reply #5 on: January 21, 2014, 09:58:44 am »
I have done it via the .gdbinit file but more recently I do it through code sourcery initialization features.  Yes the instructions get pushed through JTAG to configure the processor/registers prior to loading the program image via jtag.  In other projects I use this to initialize a DDR ram controller prior to loading for debug.  You may need to include a watchdog timer disable, since debug start up is slow.  In these scripts I also like to write a "key" value to a memory location, then in my code I look for this key and the code can tell if it is running in a debug session.

gogol

  • Sr. Member
  • ****
  • Posts: 398
Re: Debug DUE/DigiX via JTAG
« Reply #6 on: April 28, 2014, 12:49:19 am »
Just as a follow-up my current configuration with the TCL-coded initialization:

openocd.cfg: with includes the JTAG interface and the BOARD
Code: [Select]
source [find interface/FT232H.cfg]
source [find board/DUE-DigiX.cfg]

FT232H.cfg:  which defines the settings for the UM232H-B, can be any other JTAG interface as well
Code: [Select]
interface ftdi
ftdi_device_desc "UM232H-B"
ftdi_device_desc "C232HM-EDHSL-0"
ftdi_vid_pid 0x0403 0x6014
ftdi_layout_init 0x0018 0x05fb

DUE-DigiX.cfg: defines the settings for the Arduino DUE or the DigiX and other clones
Code: [Select]
##########################################################################
##   DigiX  and Arduino DUE compatible boards                           ##
##   Tested with DigiX, which has the JTAG pins broken out              ##
##   Discussion: http://digistump.com/board/index.php/topic,1275.0.html ##
##########################################################################

source [find target/at91sam3ax_8x.cfg]
source [find mem_helper.tcl]

proc enable_fast_clock {} {

      # Initialization taken from system_sam3xa.c: void SystemInit(void)
      #/* Set FWS according to SYS_BOARD_MCKR configuration */
      mww 0x400E0A00 0x400
      mww 0x400E0C00 0x400

      #/* Initialize main oscillator */
      if { [mrw 0x400E0620] & 0x1000000 == 0} {
        mww 0x400E0620 0x370809
        while {!{[mrw phys 0x400E0668] & 0x1}} {}
      }

      #/* Switch to 3-20MHz Xtal oscillator */
      mww 0x400E0620 0x370809
      while { [mrw 0x400E0668] & 0x10000 == 0} { }
      mww 0x400E0630 [expr [mrw 0x400E0630] & 0xFFFFFFFC | 0x1]
      while { [mrw 0x400E0668] & 0x8 == 0} { }

      #/* Initialize PLLA */
      mww 0x400E0628 0x200D3F01
      while { [mrw 0x400E0668] & 0x2 == 0} { }

      #/* Switch to main clock */
      mww 0x400E0630 0x11
      while { [mrw 0x400E0668] & 0x8 == 0} { }

      #/* Switch to PLLA */
      mww 0x400E0630 0x12
      while { [mrw 0x400E0668] & 0x8 == 0} { }

}


proc init_board {} {
    global _TARGETNAME

    $_TARGETNAME configure -event reset-start {
        # Back to the slow JTAG clock
        adapter_khz 5
    }

   $_TARGETNAME configure -event reset-init {
      adapter_khz 5
      enable_fast_clock
      adapter_khz 14000
   }
    $_TARGETNAME configure -event gdb-attach {
        reset init
    }
}

helge

  • Newbie
  • *
  • Posts: 1
Re: Debug DUE/DigiX via JTAG
« Reply #7 on: August 24, 2014, 07:51:21 am »
Thank you for Due-DigiX.cfg. I've now spent an entire day trying to talk to a SAM3X8E via jtag, so allow me to ask this question:
is it possible to use the ti-icdi interface on TI launchpads to write to flash memory?

Code: [Select]
telnet_port 4444

#interface 17: hla
source [find interface/ti-icdi.cfg]
hla_device_desc "TI Launchpad ICDI Interface"
transport select hla_jtag

set CHIPNAME at91sam3X8E
hla newtap $CHIPNAME cpu -expected-id 0

reset_config srst_only

source [find target/at91sam3ax_8x.cfg]

all it does is throw error 0x4 and sometimes error 0x7, possibly because there is another problem with the way I try to use hla. Now I get the feeling that there's something seriously fishy here:

Quote
adapter speed: 500 kHz
Info : This adapter doesn't support configurable speed

Does this mean that adapter_khz 5 is not possible and thus I'm out of luck with the current capabilities of ti-icdi?
Thanks in advance for any comments.
« Last Edit: August 24, 2014, 08:08:45 am by helge »

gogol

  • Sr. Member
  • ****
  • Posts: 398
Re: Debug DUE/DigiX via JTAG
« Reply #8 on: August 25, 2014, 04:49:55 am »
Unfortunately I don't know the TI device.  That sounds like a question to the openOCD forum.