JTAG debugging on Arduino Due board


Dmitriy Korovkin
 

Colleagues, while trying to use JTAG on Arduino Due board, I face the
problem of the CPU clock stop while the CPU executes wfe or wfi
instruction, which, if not makes JTAG debug impossible, but requires
setting JTAG speed to a value of 2 kHz instead of 1400 kHz, which in turn
makes debugging extremely slow.
The patch below seems to solve the problem, though in a bit strange way.
Looks like putting at91 sam3 CPU into the wait mode does not stop external
clock.

8X--------------------------------------------------------------------X8

From de7fcd02aa2a36f414328685b6f1c628dc7c1d44 Mon Sep 17 00:00:00 2001
From: Dmitriy Korovkin <dmitriy.korovkin(a)windriver.com>
Date: Mon, 06 June 2016 21:50:31 +0000
Subject: [PATCH] atmel_sam3: Do not switch off CPU clock if debugging is
planned

at91sam3 supposed to go to Sleep mode and stop the CPU clock
(HCLK). It leads to JTAG problems. In order to be able to use
JTAG, we need to keep CPU clock on. This is achieved by
switching to Wait mode and keeping external main clock.
Since Wait mode switches off automatically Fast RC Oscillator,
but keeps external clock untouched.

Change-Id: Ife37a7691c3cbdf434e560725a71d419adafe054
Signed-off-by: Dmitriy Korovkin <dmitriy.korovkin(a)windriver.com>
---
arch/arm/soc/atmel_sam3/Kconfig | 9 +++++++++
arch/arm/soc/atmel_sam3/soc.c | 8 ++++++++
arch/arm/soc/atmel_sam3/soc.h | 2 ++
3 files changed, 19 insertions(+)

diff --git a/arch/arm/soc/atmel_sam3/Kconfig b/arch/arm/soc/atmel_sam3/Kconfig
index bf4ec1e..2563cc5 100644
--- a/arch/arm/soc/atmel_sam3/Kconfig
+++ b/arch/arm/soc/atmel_sam3/Kconfig
@@ -80,4 +80,13 @@ config SOC_ATMEL_SAM3_PLLA_DIVA
With default of MULA == 6, and DIVA == 1,
PLL is running at 7 times of main clock.

+config SOC_ATMEL_SAM3_WAIT_MODE
+ bool "Atmel SAM3 goes to Wait mode instead of Sleep mode"
+ depends on SOC_ATMEL_SAM3_EXT_MAINCK
+ default y if DEBUG
+ help
+ For JTAG debugging CPU clock (HCLK) should not stop. In order
+ to achieve this, make CPU go to Wait mode instead of Sleep
+ mode while using external crystal oscillator for main clock.
+
endif # SOC_ATMEL_SAM3
diff --git a/arch/arm/soc/atmel_sam3/soc.c b/arch/arm/soc/atmel_sam3/soc.c
index e9eb494..16edb71 100644
--- a/arch/arm/soc/atmel_sam3/soc.c
+++ b/arch/arm/soc/atmel_sam3/soc.c
@@ -81,6 +81,14 @@ static ALWAYS_INLINE void clock_init(void)
/* Wait for main oscillator to be selected */
while (!(__PMC->sr & PMC_INT_MOSCSELS))
;
+#ifdef CONFIG_SOC_ATMEL_SAM3_WAIT_MODE
+ /*
+ * Instruct CPU enter Wait mode instead of Sleep mode to
+ * keep Processor Clock (HCLK) and thus be able to debug
+ * CPU using JTAG
+ */
+ __PMC->fsmr |= PMC_FSMR_LPM;
+#endif
#else
/* Set main fast RC oscillator to 12 MHz */
__PMC->ckgr_mor = PMC_CKGR_MOR_KEY | PMC_CKGR_MOR_MOSCRCF_12MHZ
diff --git a/arch/arm/soc/atmel_sam3/soc.h b/arch/arm/soc/atmel_sam3/soc.h
index 4f1ace0..ebc282c 100644
--- a/arch/arm/soc/atmel_sam3/soc.h
+++ b/arch/arm/soc/atmel_sam3/soc.h
@@ -162,6 +162,8 @@
#define PMC_MCKR_PLLADIV2 (1 << 12)
#define PMC_MCKR_UPLLDIV2 (1 << 13)

+#define PMC_FSMR_LPM (1 << 20)
+
#define PMC_INT_MOSCXTS (1 << 0)
#define PMC_INT_LOCKA (1 << 1)
#define PMC_INT_MCKRDY (1 << 3)
--
1.9.1

8X-------------------------------------------------------------------------X8

Then we can use comething like this configuration for OpenOCD for
debugging:

8X-------------------------------------------------------------------------X8
# JTAG probe configuration
source [find interface/ftdi/olimex-arm-usb-ocd-h.cfg]
#source [find interface/ftdi/flyswatter2.cfg]

source [find target/at91sam3ax_8x.cfg]

source [find mem_helper.tcl]

proc enable_fast_clock {} {
# Initialization taken from soc.c: atmel_sam3_init()
# and clock_init()
mww 0x400E0A00 0x400
mww 0x400E0C00 0x400

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

# Switch to 3-20MHz Xtal oscillator
mww 0x400E0620 0x370809
while { [mrw 0x400E0668] & 0x10000 == 0} { }

# Switch to main clock first so we can setup PLL
mww 0x400E0630 [expr [mrw 0x400E0630] & 0xFFFFFFFC | 0x1]
while { [mrw 0x400E0668] & 0x8 == 0} { }

# Setup 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} { }
}

# initialize only board specifics - reset, clock, adapter frequency
proc init_board {} {
global _TARGETNAME
adapter_khz 10

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

$_TARGETNAME configure -event reset-init {
# Back to the slow JTAG clock
adapter_khz 10
enable_fast_clock
adapter_khz 14000
}

$_TARGETNAME configure -event gdb-attach {
reset init
gdb_breakpoint_override hard
}

$_TARGETNAME configure -event gdb-flash-write-end {
echo "Flash writing complete"
at91sam3 gpnvm set 1
}
}

8X------------------------------------------------------------------X8

Comments?

Dmitriy Korovkin

Join devel@lists.zephyrproject.org to automatically receive all group messages.