- Focus on M4F on AM625.
- Entirely done on target board: BeaglePlay, NO HOST TOOLS ALLOWED :)
- Basic Hello world
- Loads with remoteproc
- Loads with self hosted openocd
- Integrate with vscode to allow self hosted development and debug and reload
⚠️ Beagleplay: These steps require decent amount of disk space, which you might find the onboard emmc lacking.. I used a 64GB sdcard entirely formatted as ext4fs as my workarea for this development. Helps extend emmc further to my needs
- https://docs.rust-embedded.org/book/
- https://code.visualstudio.com/docs/setup/linux
- https://www.rust-lang.org/tools/install
- https://github.com/rust-embedded/cortex-m-quickstart
- TRM https://www.ti.com/product/AM625#tech-docs -> https://www.ti.com/lit/pdf/spruiv7
- beagleplay schematics https://git.beagleboard.org/beagleplay/beagleplay
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
rustup target add thumbv7em-none-eabihf
cargo install cargo-generate
cargo install cargo-binutils
rustup component add llvm-tools-preview
cargo generate --git https://github.com/rust-embedded/cortex-m-quickstart
Appname: meapp
Follow instructions from https://github.com/rust-embedded/cortex-m-quickstart
cd meapp
vim cargo/config.toml and update to use:
[build]
# Pick ONE of these compilation targets
# target = "thumbv6m-none-eabi" # Cortex-M0 and Cortex-M0+
# target = "thumbv7m-none-eabi" # Cortex-M3
# target = "thumbv7em-none-eabi" # Cortex-M4 and Cortex-M7 (no FPU)
target = "thumbv7em-none-eabihf" # Cortex-M4F and Cortex-M7F (with FPU)
# target = "thumbv8m.base-none-eabi" # Cortex-M23
# target = "thumbv8m.main-none-eabi" # Cortex-M33 (no FPU)
# target = "thumbv8m.main-none-eabihf" # Cortex-M33 (with FPU)
Lets next modify the memory map to point to the AM62x memory map for M4f. As per (AM62 TRM)[https://www.ti.com/lit/pdf/spruiv7] (see Table 2-4 MCU M4F memory map view)
- 0x0 is MCU M4F Instruction RAM
- 0x3000_0000 MCU M4F's Data RAM.
we really dont have on-board flash, so it is a bit easy to kinda map things this way.
- DDR memory map actually should be parsed from devicetree, but for the moment, lets hack it. this memory is'nt visible till we map things with RAT (Region Address Translation) module used to map SoC memory map back to M4F's view - think of it as a poor man's MMU - kinda..
⚠️ We have'nt yet added resource table - so remote proc still has'nt understood how to load this image.. we can tackle that problem next after we have "something" working..
cat memory.x
MEMORY
{
/* NOTE 1 K = 1 KiBi = 1024 bytes */
/* FLASH : ORIGIN = 0x00000000, LENGTH = 256K */
FLASH : ORIGIN = 0x00000000, LENGTH = 192K
RAM : ORIGIN = 0x30000000, LENGTH = 64K
DDR_MEM_REG : ORIGIN = 0x9cb00000, LENGTH = 1M
DDR_DMA_MEM_REG : ORIGIN = 0x9cc00000, LENGTH = 13M
}
cargo build
Nothing special about the changes here -> Port maps to 3339 (more on this later).
target extended-remote :3339
All this does it to help gdb connect to the correct port that openOCD opens up. Full openocd.gdb:
target extended-remote :3339
# print demangled symbols
set print asm-demangle on
# set backtrace limit to not have infinite backtrace loops
set backtrace limit 32
# detect unhandled exceptions, hard faults and panics
break DefaultHandler
break HardFault
break rust_begin_unwind
# # run the next few lines so the panic message is printed immediately
# # the number needs to be adjusted for your panic handler
# commands $bpnum
# next 4
# end
# *try* to stop at the user entry point (it might be gone due to inlining)
break main
monitor arm semihosting enable
# # send captured ITM to the file itm.fifo
# # (the microcontroller SWO pin must be connected to the programmer SWO pin)
# # 8000000 must match the core clock frequency
# monitor tpiu config internal itm.txt uart off 8000000
# # OR: make the microcontroller SWO pin output compatible with UART (8N1)
# # 8000000 must match the core clock frequency
# # 2000000 is the frequency of the SWO pin
# monitor tpiu config external uart off 8000000 2000000
# # enable ITM port 0
# monitor itm port 0 on
load
# start the process but immediately halt the processor
stepi
Now we teach Cargo how to use openocd properly when we do cargo run
. -> main thing here is:
runner = "gdb-multiarch -q -x openocd.gdb"
Full .cargo/config.toml:
[target.thumbv7m-none-eabi]
# uncomment this to make `cargo run` execute programs on QEMU
# runner = "qemu-system-arm -cpu cortex-m3 -machine lm3s6965evb -nographic -semihosting-config enable=on,target=native -kernel"
[target.'cfg(all(target_arch = "arm", target_os = "none"))']
# uncomment ONE of these three option to make `cargo run` start a GDB session
# which option to pick depends on your system
# runner = "arm-none-eabi-gdb -q -x openocd.gdb"
runner = "gdb-multiarch -q -x openocd.gdb"
# runner = "gdb -q -x openocd.gdb"
- Will be working with a fork https://github.com/nmenon/openocd/commits/dap_dmem
- Upstream review https://review.openocd.org/c/openocd/+/7259/ -> need to refresh.. but till then..
sudo apt-get install libhidapi-dev libtool libusb-1.0-0-dev
cd
git clone https://github.com/nmenon/openocd
cd openocd
./bootstrap
./configure --enable-dmem
make -j8
- dmem interface uses root access to get to the memory map to control M4F directly.. hence the sudo..
cd ~/openocd/tcl
sudo ../src/openocd -f ./board/ti_am625_swd_native.cfg
[sudo] password for debian:
Open On-Chip Debugger 0.12.0-rc1+dev-02505-g4abd25327 (2023-03-22-01:02)
Licensed under GNU GPL v2
For bug reports, read
http://openocd.org/doc/doxygen/bugs.html
Info : only one transport option; autoselect 'dapdirect_swd'
adapter speed: 2500 kHz
Info : Listening on port 6666 for tcl connections
Info : Listening on port 4444 for telnet connections
Info : clock speed 2500 kHz
Info : starting gdb server for am625.cpu.sysctrl on 3333
Info : Listening on port 3333 for gdb connections
Info : starting gdb server for am625.cpu.a53.0 on 3334
Info : Listening on port 3334 for gdb connections
Info : starting gdb server for am625.cpu.a53.1 on 3335
Info : Listening on port 3335 for gdb connections
Info : starting gdb server for am625.cpu.a53.2 on 3336
Info : Listening on port 3336 for gdb connections
Info : starting gdb server for am625.cpu.a53.3 on 3337
Info : Listening on port 3337 for gdb connections
Info : starting gdb server for am625.cpu.main0_r5.0 on 3338
Info : Listening on port 3338 for gdb connections
Info : starting gdb server for am625.cpu.gp_mcu on 3339
Info : Listening on port 3339 for gdb connections
Info : accepting 'gdb' connection on tcp/3339
cargo run
cargo run
Finished dev [unoptimized + debuginfo] target(s) in 0.16s
Running `gdb-multiarch -q -x openocd.gdb target/thumbv7em-none-eabihf/debug/meapp`
Reading symbols from target/thumbv7em-none-eabihf/debug/meapp...
0x00000402 in cortex_m_rt::Reset ()
at /home/debian/.cargo/registry/src/github.com-1ecc6299db9ec823/cortex-m-rt-0.6.15/src/lib.rs:497
497 pub unsafe extern "C" fn Reset() -> ! {
Breakpoint 1 at 0x480: file /home/debian/.cargo/registry/src/github.com-1ecc6299db9ec823/cortex-m-rt-0.6.15/src/lib.rs, line 570.
Breakpoint 2 at 0x7d6: file /home/debian/.cargo/registry/src/github.com-1ecc6299db9ec823/cortex-m-rt-0.6.15/src/lib.rs, line 560.
Breakpoint 3 at 0x66a: file /home/debian/.cargo/registry/src/github.com-1ecc6299db9ec823/panic-halt-0.2.0/src/lib.rs, line 32.
Breakpoint 4 at 0x454: file src/main.rs, line 13.
semihosting is enabled
Loading section .vector_table, size 0x400 lma 0x0
Loading section .text, size 0x3e8 lma 0x400
Loading section .rodata, size 0x228 lma 0x7e8
Start address 0x00000400, load size 2576
Transfer rate: 2515 KB/sec, 858 bytes/write.
0x00000402 497 pub unsafe extern "C" fn Reset() -> ! {
(gdb) info breakpoints
Num Type Disp Enb Address What
1 breakpoint keep y 0x00000480 in cortex_m_rt::DefaultHandler_
at /home/debian/.cargo/registry/src/github.com-1ecc6299db9ec823/cortex-m-rt-0.6.15/src/lib.rs:570
2 breakpoint keep y 0x000007d6 in cortex_m_rt::HardFault_
at /home/debian/.cargo/registry/src/github.com-1ecc6299db9ec823/cortex-m-rt-0.6.15/src/lib.rs:560
3 breakpoint keep y 0x0000066a in panic_halt::panic
at /home/debian/.cargo/registry/src/github.com-1ecc6299db9ec823/panic-halt-0.2.0/src/lib.rs:32
4 breakpoint keep y 0x00000454 in meapp::__cortex_m_rt_main_trampoline
at src/main.rs:13
(gdb)
- https://github.com/cyrus-and/gdb-dashboard pretty interesting to use..
sudo python3 -m pip install pygments
wget -P ~ https://git.io/.gdbinit
cargo run
~
0x00000400 cortex_m_rt::Reset+0 push {r7, lr}
0x00000402 cortex_m_rt::Reset+2 mov r7, sp
0x00000404 cortex_m_rt::Reset+4 bl 0x492 <cortex_m_rt::DefaultPreInit>
0x00000408 cortex_m_rt::Reset+8 movw r0, #0
0x0000040c cortex_m_rt::Reset+12 movt r0, #12288 ; 0x3000
0x00000410 cortex_m_rt::Reset+16 movw r1, #0
0x00000414 cortex_m_rt::Reset+20 movt r1, #12288 ; 0x3000
─── Breakpoints ─────────────────────────────────────────────────────────────────────
[1] break at 0x00000480 in /home/debian/.cargo/registry/src/github.com-1ecc6299db9ec823/cortex-m-rt-0.6.15/src/lib.rs:570 for DefaultHandler
[2] break at 0x000007d6 in /home/debian/.cargo/registry/src/github.com-1ecc6299db9ec823/cortex-m-rt-0.6.15/src/lib.rs:560 for HardFault
[3] break at 0x0000066a in /home/debian/.cargo/registry/src/github.com-1ecc6299db9ec823/panic-halt-0.2.0/src/lib.rs:32 for rust_begin_unwind
[4] break at 0x00000454 in src/main.rs:13 for main
─── Expressions ─────────────────────────────────────────────────────────────────────
─── History ─────────────────────────────────────────────────────────────────────────
─── Memory ──────────────────────────────────────────────────────────────────────────
─── Registers ───────────────────────────────────────────────────────────────────────
r0 0xffffffff r1 0x00000000 r2 0x0007a121 r3 0x00000000
r4 0xa5a5a5a5 r5 0x0003e8fc r6 0x0003e8f8 r7 0x00039fd0
r8 0xe000ed04 r9 0x10000000 r10 0x0003b1b0 r11 0xa5a5a5a5
r12 0x0003da87 sp 0x00039fd0 lr 0x00008d31 pc 0x00000404
xPSR 0x81000000 fpscr 0x00000000 msp 0x00014e80 psp 0x00039fd0
primask 0x00 basepri 0x00 faultmask 0x00 control 0x02
─── Source ──────────────────────────────────────────────────────────────────────────
513
514 // This symbol will be provided by the user via `#[pre_init]`
515 fn __pre_init();
516 }
517
518 __pre_init();
519
520 // Initialize RAM
521 r0::zero_bss(&mut __sbss, &mut __ebss);
522 r0::init_data(&mut __sdata, &mut __edata, &__sidata);
─── Stack ───────────────────────────────────────────────────────────────────────────
[0] from 0x00000404 in cortex_m_rt::Reset+4 at /home/debian/.cargo/registry/src/github.com-1ecc6299db9ec823/cortex-m-rt-0.6.15/src/lib.rs:518
─── Threads ─────────────────────────────────────────────────────────────────────────
[1] id 0 from 0x00000404 in cortex_m_rt::Reset+4 at /home/debian/.cargo/registry/src/github.com-1ecc6299db9ec823/cortex-m-rt-0.6.15/src/lib.rs:518
─── Variables ───────────────────────────────────────────────────────────────────────
─────────────────────────────────────────────────────────────────────────────────────
>>>
- Fix up resource_table for remoteproc load
- integrate build and debug with vscode..