How to load binary to DRAM with JLink JTAG to debug? - arm

I am doing a ARM+RTOS project, and I want to download the binary to target board with JLink JTAG.
But every time 'loadbin a.bin 0x40000000' will report error -1, and says 'failed to read memory', 0x40000000 is the starting address of DRAM.
I have to use 'r' command to reset JTAG port to read memory back.
The JLINK driver is 6.72 installed in Ubuntu-20.04.5, the ARM is an allwinner chip (cortex-a7).
I am wondering how to download the binary image into DRAM thru JLink JTAG to debug.
Updated with more details.
The board is based on sun8i, with 2 ARMv7 cores.
The JLink can identify the JTAG adapter as follows,
Connecting to target via JTAG
ConfigTargetSettings() start
Setting up: AW Cortex-A7
ConfigTargetSettings() end
TotalIRLen = 4, IRPrint = 0x01
JTAG chain detection found 1 devices:
#0 Id: 0x5BA00477, IRLen: 04, CoreSight JTAG-DP
AP map detection skipped. Manually configured AP map found.
AP[0]: AHB-AP (IDR: Not set)
AP[1]: APB-AP (IDR: Not set)
Using preconfigured AP[1] as APB-AP
AP[1]: APB-AP found
ROMTbl[0][0]: CompAddr: 80050000 CID: B105900D, PID:04-004BB906 CTI
ROMTbl[0][1]: CompAddr: 81000000 CID: B105100D, PID:08-00A9CC32 ROM Table
ROMTbl[1][0]: CompAddr: 81010000 CID: 00000000, PID:00-00000000 ???
ROMTbl[1][1]: CompAddr: 81020000 CID: 00000000, PID:00-00000000 ???
ROMTbl[1][2]: CompAddr: 81400000 CID: B105100D, PID:04-000BB4A7 ROM Table
ROMTbl[2][0]: CompAddr: 81410000 CID: B105900D, PID:04-005BBC07 Cortex-A7
Found Cortex-A7 r0p5
6 code breakpoints, 4 data breakpoints
Debug architecture ARMv7.1
Data endian: little
Main ID register: 0x410FC075
I-Cache L1: 32 KB, 512 Sets, 32 Bytes/Line, 2-Way
D-Cache L1: 32 KB, 128 Sets, 64 Bytes/Line, 4-Way
Unified-Cache L2: 256 KB, 512 Sets, 64 Bytes/Line, 8-Way
System control register:
Instruction endian: little
Level-1 instruction cache enabled
Level-1 data cache enabled
MMU enabled
Branch prediction enabled
Memory zones:
[0]: Default (Default access mode)
[1]: AHB-AP (AP0) (DMA like acc. in AP0 addr. space)
[2]: APB-AP (AP1) (DMA like acc. in AP1 addr. space)
Cortex-A7 identified.
The JLinkGDBServer and gdb can attach and debug the code running (burned with a tool in Windows) in RAM, such as reading memory, modify memory etc.
But the gdb command of load a.elf will fail with error in memory writing.
And the loadbin a.bin 0x40000000 in JLinkExe also failed with memory writing.
with steps of loading add.c from Frant in my system
The JLinkGDBServer is running in another xterm, and run gdb-multiarch
(gdb) monitor reset
Resetting target
(gdb) x/8x 0x40000000
0x40000000: 0xea00001e 0x736f7472 0x00000000 0xa143480d
0x40000010: 0x0008b630 0x0008b630 0x0008b630 0x2e302e30
(gdb) load add.elf
`/home/t/develop/ctest/add.elf' has changed; re-reading symbols.
(no debugging symbols found)
Loading section .note.gnu.build-id, size 0x24 lma 0x100b4
Loading section .text, size 0x64 lma 0x40000000
Start address 0x40000000, load size 136
Transfer rate: 5 KB/sec, 68 bytes/write.
(gdb) x/8x 0x40000000
0x40000000 <main>: Cannot access memory at address 0x40000000
Before loading elf to DRAM, memory at 0x40000000 (start of DRAM) can be read from GDB. But after loading elf, that memory cannot be read from GDB.
The JLinkGDBServer also reported...
Downloading 36 bytes # address 0x000100B4
Downloading 100 bytes # address 0x40000000
Writing register (PC = 0x40000000)
Reading all registers
WARNING: Failed to read memory # address 0x40000000
Then, I changed to use JLinkExe to load a binary file of 4KB (all 0s) as follows,
J-Link>r
Reset delay: 0 ms
Reset type NORMAL: Toggle reset pin and halt CPU core.
J-Link>mem32 0x40000000 16
40000000 = EA00001E 736F7472 00000000 A143480D
40000010 = 0008B630 0008B630 0008B630 2E302E30
40000020 = 00000030 2E302E30 00000030 40000000
40000030 = 00000000 00000000 00000000 00000000
40000040 = 00000000 00000000 00000000 00000000
40000050 = 00000040 00000000
J-Link>loadbin zero.bin 0x40000000
Downloading file [zero.bin]...
Unspecified error -1
J-Link>
Tried with sunxi-fel tool
(base):~/tools/sunxi-tools-master$ sudo ./sunxi-fel -v --list
USB device 001:035 Allwinner R528 93406400:0c004814:0146880a:044713cd
(base):~/tools/sunxi-tools-master$ sudo ./sunxi-fel -p write 0x40000000 ~/u-boot.bin
usb_bulk_send() ERROR -7: Operation timed out
(base):~/tools/sunxi-tools-master$ sudo ./sunxi-fel -v --list
usb_bulk_send() ERROR -7: Operation timed out
Firstly, sunxi-fel can detect and list the attached device.
Then to load u-boot.bin to DRAM hit an error (Maybe from DRAM not initialized).
Last, the sunxi-fel cannot detect and list the attached device, I have to power cycle the board to bring it back.

This is not clear from your original question what the state of your device is prior to your attempt, nor what exact model of SBC you are using.
However, here are two different approaches you could probably use for achieving your goal. Ubuntu 22.04, Jlink software V7.84c, a JLink EDU and a FriendlyElec nanopi-2 neo with an Allwinner H3 were used for the purpose of this answer.
They could probably be adapted to a different 32 bit Alwinner SoC having JTAG support, and an SBC having the JTAG signals properly wired.
It worked for me using a nanopi2-m1 and an orangepi-zero.
You have two issues to solve here prior to be able to upload your binary usin g the JLink probe:
Making sure the SDRAM controller is configured so that the SDRAM will be readable/writable,
Enable the JTAG on some PIO port supporting the JTAG functionality: for example, the reset value for the H3 PA Configure Register is 0x77777777, that is the JAG functionality is not enable at reset. As a side-effect, if you are resetting the SoC using the JLink probe, you will lose the JTAG connectivity.
Approach #1 - using u-boot
In this case, the u-boot SPL will obviously already have configured the SDRAM controller, and its content will be usable, and you will just have to enable the JTAG functionality on PIO port A.
You will need to write the value 0x77223333 into the PA Configure Register at address 0x01c20800 in order to enable the JTAG functionality on PIO port A- please refer to 4.22.1. Port Controller Register List and 4.22.2. Port Controller Register Description of the Allwinner H3 Datasheet.
U-Boot SPL 2023.01 (Jan 24 2023 - 15:18:15 -0500)
DRAM: 512 MiB
Trying to boot from MMC1
U-Boot 2023.01 (Jan 24 2023 - 15:18:15 -0500) Allwinner Technology
CPU: Allwinner H3 (SUN8I 1680)
Model: FriendlyARM NanoPi NEO
DRAM: 512 MiB
Core: 60 devices, 17 uclasses, devicetree: separate
WDT: Not starting watchdog#1c20ca0
MMC: mmc#1c0f000: 0
Loading Environment from FAT... OK
In: serial
Out: serial
Err: serial
Net: eth0: ethernet#1c30000
starting USB...
Bus usb#1c1a000: probe failed, error -2
Bus usb#1c1a400: probe failed, error -2
Bus usb#1c1d000: USB EHCI 1.00
Bus usb#1c1d400: USB OHCI 1.0
scanning bus usb#1c1d000 for devices... 1 USB Device(s) found
scanning bus usb#1c1d400 for devices... 1 USB Device(s) found
scanning usb for storage devices... 0 Storage Device(s) found
=>
Enabling JTAG on PA:
mw.l 0x01c20800 0x77223333 1
=>
Starting the JLink GDD server - Ubuntu system:
<!-- language-all: lang-text -->
/opt/jlink$/opt/JLink_Linux_V784c_x86_64/JLinkGDBServerCLExe -select USB -device Cortex-A7 -endian little -if JTAG -speed 4000 -noir -noLocalhostOnly -nologtofile -port 2331 -SWOPort 2332 -TelnetPort 2333
SEGGER J-Link GDB Server V7.84c Command Line Version
JLinkARM.dll V7.84c (DLL compiled Jan 20 2023 12:25:58)
Command line: -select USB -device Cortex-A7 -endian little -if JTAG -speed 4000 -noir -noLocalhostOnly -nologtofile -port 2331 -SWOPort 2332 -TelnetPort 2333
-----GDB Server start settings-----
GDBInit file: none
GDB Server Listening port: 2331
SWO raw output listening port: 2332
Terminal I/O port: 2333
Accept remote connection: yes
Generate logfile: off
Verify download: off
Init regs on start: off
Silent mode: off
Single run mode: off
Target connection timeout: 0 ms
------J-Link related settings------
J-Link Host interface: USB
J-Link script: none
J-Link settings file: none
------Target related settings------
Target device: Cortex-A7
Target device parameters: none
Target interface: JTAG
Target interface speed: 4000kHz
Target endian: little
Connecting to J-Link...
J-Link is connected.
Firmware: J-Link ARM V8 compiled Nov 28 2014 13:44:46
Hardware: V8.00
S/N: ********
OEM: SEGGER-EDU
Feature(s): FlashBP, GDB
Checking target voltage...
Target voltage: 3.31 V
Listening on TCP/IP port 2331
Connecting to target...
J-Link found 1 JTAG device, Total IRLen = 4
JTAG ID: 0x5BA00477 (Cortex-A7)
Connected to target
Waiting for GDB connection...
At this stage, the JLink GDB server successfully connected the H3 using the JTAG interface.
We now need a small example program - add.c
int main(int argc, char** argv) {
const int count = 5;
int result = 0;
for (int i = 1; i < count; i++) {
result = result + i;
}
done:
// We should rather use 'WFI' here.
goto done;
}
Compiling add.elf:
/opt/arm/10/gcc-arm-10.3-2021.07-x86_64-arm-none-eabi/bin/arm-none-eabi-gcc -O0 -nostdlib -nostartfiles -e main -Wl,-Ttext=0x0000000042000000 -o add.elf add.c
/opt/arm/10/gcc-arm-10.3-2021.07-x86_64-arm-none-eabi/bin/arm-none-eabi-objdump -D -j .text add.elf > add.lst
cat add.lst
add.elf: file format elf32-littlearm
Disassembly of section .text:
42000000 <main>:
42000000: e52db004 push {fp} ; (str fp, [sp, #-4]!)
42000004: e28db000 add fp, sp, #0
42000008: e24dd01c sub sp, sp, #28
4200000c: e50b0018 str r0, [fp, #-24] ; 0xffffffe8
42000010: e50b101c str r1, [fp, #-28] ; 0xffffffe4
42000014: e3a03005 mov r3, #5
42000018: e50b3010 str r3, [fp, #-16]
4200001c: e3a03000 mov r3, #0
42000020: e50b3008 str r3, [fp, #-8]
42000024: e3a03001 mov r3, #1
42000028: e50b300c str r3, [fp, #-12]
4200002c: ea000006 b 4200004c <main+0x4c>
42000030: e51b2008 ldr r2, [fp, #-8]
42000034: e51b300c ldr r3, [fp, #-12]
42000038: e0823003 add r3, r2, r3
4200003c: e50b3008 str r3, [fp, #-8]
42000040: e51b300c ldr r3, [fp, #-12]
42000044: e2833001 add r3, r3, #1
42000048: e50b300c str r3, [fp, #-12]
4200004c: e51b200c ldr r2, [fp, #-12]
42000050: e51b3010 ldr r3, [fp, #-16]
42000054: e1520003 cmp r2, r3
42000058: bafffff4 blt 42000030 <main+0x30>
4200005c: e1a00000 nop ; (mov r0, r0)
42000060: eafffffe b 42000060 <main+0x60>
Starting a GDB session and loading add.elf:
/opt/gdb/gdb-12.1-arm-none-eabi-x86_64-linux-gnu/bin/arm-none-eabi-gdb
GNU gdb (GDB) 12.1
Copyright (C) 2022 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "--host=x86_64-linux-gnu --target=arm-none-eabi".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<https://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word".
(gdb) target remote localhost:2331
Remote debugging using localhost:2331
warning: No executable has been specified and target does not support
determining executable automatically. Try using the "file" command.
0x42000004 in ?? ()
(gdb) load add.elf
Loading section .text, size 0x64 lma 0x42000000
Start address 0x42000000, load size 100
Transfer rate: 32 KB/sec, 100 bytes/write.
(gdb) b *0x42000000
Breakpoint 1 at 0x42000000
At this stage, the program was load into the nanipo2-neo,and a break-point
was set at 0x42000000.
By switching to the TUI mode, we can step trough the program using the stepi command:
Approach #2 - using FEL mode and sunxi-fel
With this approach, you would boot your SBC in FEL mode, configure the SDRAM controller using the following command: sunxi-fel spl u-boot-sunxi-with-spl.bin, as explained on the FEL/USBBoot page of the linux-sunxi WEB site.
Enabling the JTAG functionality could than be done using the following command: sunxi-fel writel 0x01c20800 0x77223333.
Starting the JLink GDB server and launching a GDB debug session could then be done as described above.

After upgraded to JLink ver.7.0.0,the image downloading and debugging in DRAM are working well as expected.

Related

Emulate ARM Cortex-M7 with qemu-system-arm.exe

I'm using Eclipse based CubeIDE and QEMU debugging plugin.
I'm working in assembler and can debug simple project (adding two numbers in registers) on STM32 Cortex M7 board (STM32H750DK). Now I'd like to do the same using QEMU and have problems, because I can't find suitable generic Cortex M7 machine. I've tried mps2-an500, but it doesn't work.
I've done similar already under qemu-system-gnuarmeclipse.exe on STM32F407 board and it's supported even visually (board picture), and I can see LED diodes blinking.
I'd be enough just plain emulation (not visual) for cortex M7 board.
Has anyone done something similar or any other advice how to do this properly ?
Thanks.
I think you are supposed to show some code for the attempts you made when asking a question on Stackoverflow.
In your case, this could have been a minimal, reproducible example of your attempts to use the mps2-an500 QEMU virtual machine.
This being said, a procedure for building and debugging a program using QEMU and targeting the mps2-an500 virtual machine could be:
Download QEMU 7.10 for Windows, and install it into the \opt\qemu-7.1.0 directory - you will have to create it,
Download the arm-gnu-toolchain-11.3.rel1-mingw-w64-i686-arm-none-eabi toolchain,and install into the \opt\arm\11 directory - you will have to create it,
In a directory of your choice, create the following files:
build.cmd:
#set CROSS_COMPILE=\opt\arm\11\arm-gnu-toolchain-11.3.rel1-mingw-w64-i686-arm-none-eabi\bin\arm-none-eabi-
#set CC=%CROSS_COMPILE%gcc
#set OBJDUMP=%CROSS_COMPILE%objdump
#set GDB=%CROSS_COMPILE%gdb
#set QEMU_SYSTEM_ARM=\opt\qemu-7.1.0\qemu-system-arm
#%CC% -g -mthumb -mtune=cortex-m7 -nostdlib -nostartfiles -ffreestanding -Wl,-Ttext,0x00000000 -o mps2-an500.elf startup.s
#%OBJDUMP% -d mps2-an500.elf > mps2-an500.objdump
#echo QEMU/GDB commands:
#echo %QEMU_SYSTEM_ARM% -m 16M -nographic -machine mps2-an500 -S -cpu cortex-m7 -gdb tcp::2345,ipv4 -kernel mps2-an500.elf
#echo %GDB%
startup.s:
.file "startup.s"
.arch armv7-a
.fpu vfpv3-d16
.thumb
.syntax unified
.equ __StackTop, 0x21000000
.global _start
.align 2
.long __StackTop
.long _start
_start:
mov r0,#3
mov r1,#5
add r2, r0, r1
wait: b wait
.size _start, .-_start
.end
Execute the build.cmd batch procedure, it will create mps2-an500.elf and mps2-an500.lst, and display the QEMU and GDB commands you will use for debugging the (very) basic example:
build.cmd
QEMU/GDB commands:
\opt\qemu-7.1.0\qemu-system-arm -m 16M -nographic -machine mps2-an500 -S -cpu cortex-m7 -gdb tcp::2345,ipv4 -kernel mps2-an500.elf
\opt\arm\11\arm-gnu-toolchain-11.3.rel1-mingw-w64-i686-arm-none-eabi\bin\arm-none-eabi-gdb
In one console mode session, execute:
\opt\qemu-7.1.0\qemu-system-arm -m 16M -nographic -machine mps2-an500 -S -cpu cortex-m7 -gdb tcp::2345,ipv4 -kernel mps2-an500.elf
in another, execute the GDB command:
\opt\arm\11\arm-gnu-toolchain-11.3.rel1-mingw-w64-i686-arm-none-eabi\bin\arm-none-eabi-gdb --command=mps2-an500.gdb
In the GDB session, execute the following commands in sequence:
target remote localhost:2345
file mps2-an500.elf
break _start
break wait
set $sp = 0x21000000
set $pc = _start
stepi
stepi
stepi
info registers
The transcript for the GDB session should look like:
\opt\arm\11\arm-gnu-toolchain-11.3.rel1-mingw-w64-i686-arm-none-eabi\bin\arm-none-eabi-gdb
GNU gdb (Arm GNU Toolchain 11.3.Rel1) 12.1.90.20220802-git
Copyright (C) 2022 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "--host=i686-w64-mingw32 --target=arm-none-eabi".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<https://bugs.linaro.org/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word".
(gdb) target remote localhost:2345
Remote debugging using localhost:2345
warning: No executable has been specified and target does not support
determining executable automatically. Try using the "file" command.
0x00000014 in ?? ()
(gdb) file mps2-an500.elf
A program is being debugged already.
Are you sure you want to change the file? (y or n) y
Reading symbols from mps2-an500.elf...
(gdb) break _start
Breakpoint 1 at 0x8: file startup.s, line 12.
(gdb) break wait
Breakpoint 2 at 0x14: file startup.s, line 15.
(gdb) set $sp = 0x21000000
(gdb) set $pc = _start
(gdb) stepi
13 mov r1,#5
(gdb) stepi
14 add r2, r0, r1
(gdb) stepi
Breakpoint 2, _start () at startup.s:15
15 wait: b wait
(gdb) info registers
r0 0x3 3
r1 0x5 5
r2 0x8 8
r3 0x0 0
r4 0x0 0
r5 0x0 0
r6 0x0 0
r7 0x0 0
r8 0x0 0
r9 0x0 0
r10 0x0 0
r11 0x0 0
r12 0x0 0
sp 0x21000000 0x21000000
lr 0xfffffff9 -7
pc 0x14 0x14 <_start+12>
xpsr 0x41000003 1090519043
fpscr 0x0 0
(gdb)

Aarch64 baremetal Hello World program on QEMU

I have compiled and ran a simple hello world program on ARM Foundation Platform. The code is given below.
#include <stdio.h>
int main(int argc, char *argv[])
{
printf("Hello world!\n");
return 0;
}
This program is compiled and linked using ARM GNU tool chain as given below.
$aarch64-none-elf-gcc -c -march=armv8-a -g hello.c hello.o
aarch64-none-elf-gcc: warning: hello.o: linker input file unused because linking not done
$aarch64-none-elf-gcc -specs=aem-ve.specs -Wl,-Map=linkmap.txt hello.o -o hello.axf
I could successfully execute this program on ARM Foundation Platform (I think, foundation platform is similar to ARM Fixed Virtual Platform) and it prints "Hello world!"
The contents of 'aem-ve.specs' file is given below:
cat ./aarch64-none-elf/lib/aem-ve.specs
# aem-ve.specs
#
# Spec file for AArch64 baremetal newlib, libgloss on VE platform with version 2
# of AngelAPI semi-hosting.
#
# This Spec file is also appropriate for the foundation model.
%rename link old_link
*link:
-Ttext-segment 0x80000000 %(old_link)
%rename lib libc
*libgloss:
-lrdimon
*lib:
cpu-init/rdimon-aem-el3.o%s --start-group %(libc) %(libgloss) --end-group
*startfile:
crti%O%s crtbegin%O%s %{!pg:rdimon-crt0%O%s} %{pg:rdimon-crt0%O%s}
Is it possible to execute the same binary on QEMU? If so could you please share the sample command. If not, could you please share the right and best way to execute it on QEMU?
I have traced instruction execution of Foundation platform using the "trace" option and analysed using 'tarmac-profile' tool and 'Tarmac-calltree' tool. The outputs are given below:
$ ./tarmac-profile hello.trace --image hello.axf
Address Count Time Function name
0x80000000 1 120001
0x80001030 1 30001 register_fini
0x80001050 1 60001 deregister_tm_clones
0x800010c0 1 210001 __do_global_dtors_aux
0x80001148 1 23500001 frame_dummy
0x800012c0 1 10480001 main
0x80002000 1 40001 main
0x80003784 1 360001 main
0x80003818 1 460001 _cpu_init_hook
0x80003870 1 590001 _write_r
0x800038d0 1 1090001 __call_exitprocs
...
...
./tarmac-calltree hello.trace --image hello.axf
o t:10000 l:2288 pc:0x80001148 - t:23510000 l:7819 pc:0x80008060 : frame_dummy
- t:240000 l:2338 pc:0x800011a8 - t:720000 l:2443 pc:0x800011ac
o t:250000 l:2340 pc:0x80003818 - t:710000 l:2442 pc:0x80003828 : _cpu_init_hook
- t:260000 l:2343 pc:0x8000381c - t:320000 l:2354 pc:0x80003820
o t:270000 l:2345 pc:0x80002000 - t:310000 l:2353 pc:0x80002010 : main
- t:320000 l:2354 pc:0x80003820 - t:700000 l:2436 pc:0x80003824
o t:330000 l:2356 pc:0x80003784 - t:690000 l:2435 pc:0x80003814 : main
- t:760000 l:2453 pc:0x800011bc - t:2010000 l:2970 pc:0x800011c0
o t:770000 l:2455 pc:0x80004200 - t:2000000 l:2969 pc:0x800042c0 : memset
- t:2010000 l:2970 pc:0x800011c0 - t:4870000 l:3587 pc:0x800011c4
o t:2020000 l:2972 pc:0x80007970 - t:4860000 l:3586 pc:0x80007b04 : initialise_monitor_handles
- t:2960000 l:3165 pc:0x80007b24 - t:4340000 l:3465 pc:0x80007b28
I have tried the following method to execute on QEMU, without any success.
I have started the QEMU with gdb based debugging through TCP Port
$ qemu-system-aarch64 -semihosting -m 128M -nographic -monitor none -serial stdio -machine virt,gic-version=2,secure=on,virtualization=on -cpu cortex-a53 -kernel hello.axf -S -gdb tcp::9000
The result of debug session is given below:
gdb) target remote localhost:9000
Remote debugging using localhost:9000
_start () at /data/jenkins/workspace/GNU-toolchain/arm-11/src/newlib-cygwin/libgloss/aarch64/crt0.S:90
90 /data/jenkins/workspace/GNU-toolchain/arm-11/src/newlib-cygwin/libgloss/aarch64/crt0.S: No such file or directory.
(gdb) si
<The system hangs here>
I have tried to disassemble the code using gdb and its output is given below. It looks like the code is not loaded correctly
(gdb) disas frame_dummy
Dump of assembler code for function frame_dummy:
0x0000000080001110 <+0>: udf #0
0x0000000080001114 <+4>: udf #0
0x0000000080001118 <+8>: udf #0
0x000000008000111c <+12>: udf #0
0x0000000080001120 <+16>: udf #0
0x0000000080001124 <+20>: udf #0
0x0000000080001128 <+24>: udf #0
0x000000008000112c <+28>: udf #0
0x0000000080001130 <+32>: udf #0
0x0000000080001134 <+36>: udf #0
0x0000000080001138 <+40>: udf #0
0x000000008000113c <+44>: udf #0
0x0000000080001140 <+48>: udf #0
0x0000000080001144 <+52>: udf #0
End of assembler dump.
Could you please shed some light on this. Any hint given is appreciated very much.
The Foundation Model and the QEMU 'virt' board are not the same machine type. They have different devices at different physical addresses, and in particular they do not have RAM at the same address. To run bare metal code on the 'virt' machine type you will need to adjust your code. This is normal for bare metal -- the whole point is that you are running directly on some piece of (emulated) hardware and need to match the details of it.
Specifically, the minimum change you need to make here is that the RAM on the 'virt' board starts at 0x4000_0000, not the 0x8000_0000 that the Foundation Model uses. There may be others as well, but that is the immediate cause of what you're seeing.

How do i run assembly (.s) files on VSCode in Linux subsystem

I have just got into ARM programming. Learned a few basics but am having issues with running code. I use VSCode on Linux Subsystem as my IDE.
I have nothing installed on my computer and i would like to run ARM code. I have read online something about "qemu" and "kernel" and stuff, but am not sure what they mean. It would be great if someone provides a detailed walkthrough for such a problem. I do not have a raspberry pi.
For example, how do i run the following division.s file on VSCode?
.global _start
_start:
MOV R1, #X
MOV R2, #Y
MOV R3, #Z
CMP R1, R2 # is x>y ?
BGT _tryx
CMP R2, R3 # is y>z ?
BGT _isy
MOV R4, R3
B _exit
_isy:
MOV R4, R2
B _exit
_tryx:
CMP R1, R3 # is x>z ?
BGT _isx
MOV R4, R3
B _exit
_isx:
MOV R4, R1
_exit:
MOV R0, R4
MOV R7, #1
SWI 0
.data
.equ X, 3
.equ Y, 5
.equ Z, 4
Are there any extensions i need to install? Is there anything i need to download? I have used gcc to compile C code. Can it be used here too?
Thx in advance! :D
Your question is rather a broad one. This being said, a slightly modified version of your program can be executed in WSL using the following procedure:
sudo apt-get install qemu-user
sudo mkdir -p /opt/arm/10
wget 'https://developer.arm.com/-/media/Files/downloads/gnu-a/10.2-2020.11/binrel/gcc-arm-10.2-2020.11-x86_64-arm-none-linux-gnueabihf.tar.xz?revision=d0b90559-3960-4e4b-9297-7ddbc3e52783&la=en&hash=985078B758BC782BC338DB947347107FBCF8EF6B' -O gcc-arm-10.2-2020.11-x86_64-arm-none-linux-gnueabihf.tar.xz
sudo tar Jxf gcc-arm-10.2-2020.11-x86_64-arm-none-linux-gnueabihf.tar.xz -C /opt/arm/10
/tmp/division.s:
# count how often we can take Y from X
.global main
main:
MOV R1, #X
MOV R2, #Y
MOV R3, #0 # Q
_loop:
CMP R1, R2
BLT _exit
SUB R1, R2
ADD R3, #1
B _loop
_exit:
MOV R0, R3
MOV R7, #1
SWI 0
.data
.equ X, 23
.equ Y, 4
Compiling:
/opt/arm/10/gcc-arm-10.2-2020.11-x86_64-arm-none-linux-gnueabihf/bin/arm-none-linux-gnueabihf-gcc -static -o /tmp/division /tmp/division.s
Executing - WSL:
qemu-arm /tmp/division
echo $?
5
Which is the expected result, since 23 div 4 is 5.
Executing - Windows 10:
C:\>c:\Windows\System32\bash -c "qemu-arm /tmp/division; echo $?"
5
C:\>
Or:
C:\>c:\Windows\System32\bash -c "qemu-arm /tmp/division"
C:\>echo %ERRORLEVEL%
5
Note that division.s may have been compiled in Windows 10 as well by downloading/installing gcc-arm-10.2-2020.11-mingw-w64-i686-arm-none-linux-gnueabihf.tar.xz instead of gcc-arm-10.2-2020.11-x86_64-arm-none-linux-gnueabihf.tar.xz - your choice.
I let it to you than to go into the details of using the information above for running your program from vscode, you question being a bit too broad IMHO.
Update: division.s was compiled statically on purpose for avoiding having to specify the locations for any non-needed dynamic libraries.
Compiling it without using the -static option, and executing it would result in the following error message to be displayed:
qemu-arm division
/lib/ld-linux-armhf.so.3: No such file or directory
It can be avoided by telling qemu-arm where to look for required dynamic libraries, /lib/ld-linux-armhf.so.3 in this case:
qemu-arm -L /opt/arm/10/gcc-arm-10.2-2020.11-x86_64-arm-none-linux-gnueabihf/arm-none-linux-gnueabihf/libc division
echo $?
5
That looks like a Linux program. And I guess you have an 64-bit x86 computer.
You want QEMU, specifically the executable qemu-arm which emulates an ARM processor running Linux on another Linux compatible system. In Debian derived Linux distributions it is in the package qemu-arm.
And on ebian derived Linux distributions for a compiler you can install the gcc-arm-linux-gnueabihf package for compiling for ARMv7 and ARMv8 with hardware floating point (Debian port name armhf), or gcc-arm-linux-gnueabi for some older ARMs with no hardware floating point Debian port name armel).
If you wish to install libraries, you need add the architecture to dpkg's list, for example:
dpkg --add-architecture armhf

Just bought STM32F446 but the STM32IDE is not doing what I expect

while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
I Installed STMCubeMX and built a project for STM32IDE
In the IDE I successfully built the project using: project -> build all
I'm expecting to see the default led to stop blinking given my while loop is completely blank, but it's still blinking like crazy.
Try this, quite minimal, will test your tools and ability to copy the file to the board. I assume this is a NUCLEO board.
.cpu cortex-m0
.thumb
.thumb_func
.global _start
_start:
stacktop: .word 0x20000100
.word reset
.word reset
.word reset
.word reset
.thumb_func
reset:
b .
build
arm-none-eabi-as flash.s -o flash.o
arm-none-eabi-ld -Ttext=0x08000000 flash.o -o flash.elf
arm-none-eabi-objdump -D flash.elf > flash.list
arm-none-eabi-objcopy -O binary flash.elf flash.bin
check build
cat flash.list
Disassembly of section .text:
08000000 <_start>:
8000000: 20000100
8000004: 08000015
8000008: 08000015
800000c: 08000015
8000010: 08000015
08000014 <reset>:
8000014: e7fe b.n 8000014 <reset>
Looks good exactly what we want.
Now copy command line or drag and drop flash.bin to the virtual drive that is mounted when you plug in the NUCLEO board. It will load this into the target mcu on the board. The STM32F446, and should reset it and you will end up in this loop, no blinking user led.
As you make more complicated projects you simply expand on this a bootstrap, a program, linked (,checked), and copied to the virtual flash drive.
I normally do a firmware upgrade of the debug end (stlink plus thumb drive thing) when I get a new NUCLEO board. ST provides a Java-based tool that itself does not update that often, but it checks the board vs I guess a database at their site and can upgrade your flash. Depending on your host OS I have had NUCLEOs that you can only copy to a few times or one time and you have to unplug and replug, newer firmware versions for those and more recent boards that problem has pretty much gone away. It would say no room left on the device, unplug/replug and it would be fine.
Also providing stlink capabilities you can use openocd or other tools to stop and examine the device, with openocd for example when you telnet in to the openocd server you can use mdw 0x08000000 20 and examine the start of the user flash to see if it matches the binary you think you have loaded on the device. Depending on the part you can also write/erase that flash via openocd, but do not assume that support is always there for all ST or other branded parts. Write to ram and run from there (different startup not a vector table) sure, but flashing requires someone to add that support for each part or family into openocd.
As pointed out in the comments either you are not building what you think or you are not actually loading the program into the flash. Examine the binary examine the flash to see what actually happened if anything. The above should avoid all the barriers to success, CMSIS, IDE tools, STMCubeMX, etc. Once you are able to succeed then work your way to the middle from both ends (between this trivial example and your project) and find where the real problem is/was. You should be able to for example use the IDE and all that stuff to build the binary, use the gnu tools to examine that binary, hexdump/whatever to examine the .bin file, and then drag and drop outside the IDE to program.

Load a binary into flash memory using gdb

I'd like to flash a binary file into my ARM MCU flash memory using gdb.
Currently I'm able to load an elf like this:
# arm-none-eabi-gdb --command=flash.gdb "myfirmware.elf"
# cat flash.gdb
set confirm off
target remote 127.0.0.1:7224
monitor reset
load
detach
quit
Basically the load command is good at loading elf sections to the right addresses.
However to put multiple firmware in the MCU flash memory, I'd like to send a complete binary image.
In order to test it, I made a zero.bin image (containing nothing but 0):
# hexdump zero.bin
0000000 0000 0000 0000 0000 0000 0000 0000 0000
*
0020000
# arm-none-eabi-gdb
(gdb) target remote 127.0.0.1:7224
(gdb) mon reset halt
(gdb) mon reset init
(gdb) set arm fallback-mode auto
(gdb) set debug arm
(gdb) restore zero.bin binary 0x0
Restoring binary file zero.bin into memory (0x0 to 0x20000)
Writing to flash memory forbidden in this context
(gdb) info mem
Using memory regions provided by the target.
Num Enb Low Addr High Addr Attrs
0 y 0x00000000 0x00020000 flash blocksize 0x800 nocache
1 y 0x00020000 0x100000000 rw nocache
(gdb) delete mem 1
warning: Switching to manual control of memory regions; use "mem auto" to fetch regions from the target again.
(gdb) delete mem 0
(gdb) mem 0 0x100000000 rw nocache
(gdb) info mem
Using user-defined memory regions.
Num Enb Low Addr High Addr Attrs
1 y 0x00000000 0x100000000 rw nocache
(gdb) restore zero.bin binary 0x0
Restoring binary file zero.bin into memory (0x0 to 0x20000)
(gdb) x/10 0x0
0x0: 0x20003000 0x00003c5d 0x00003c7d 0x00003c7d
0x10: 0x00000000 0x00000000 0x00000000 0x00000000
0x20: 0x00000000 0x00000000
So this doesn't seem to work, as you can see in 0x0 it should be full of '0' but it still contains my previous firmware (the vector table actually)
What do I miss? Or maybe there is another way to load a binary using gdb?
If you are using OpenOCD,
mon flash write_bank <num> <file_name> <offset>
should help you.
For example, if your flash starts at 0x400000,
mon flash write_bank 0 zero.bin 0x100000
will write the zero.bin file at 0x500000, assuming that address is writable.
You can't delete memory region. Because GDB uses vFlashWrite packet for writing to flash memory and M or X packets for writing to RAM.
I know only one way to write binary data to flash memory using gdb.
You need to transform your binary image to elf-file with one single .data section.
powerpc-objcopy -I binary -O elf32-powerpc -B PowerPC -S zero.bin zero.elf
For checking your new elf-file use readelf.
powerpc-readelf -h -t zero.elf
In the end just use load command with flash base address, because this elf-file has not any address information. (or you can use --change-addresses 0x0 option with objcopy)
load zero.elf 0x0
I checked this on PowerPC. GDB version is 8.1.
This GDB was configured as "--host=x86_64-pc-linux-gnu --target=powerpc-eabi".

Resources