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.
Related
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.
AVR processors can have their fuses programmed via the ELF file (see http://www.nongnu.org/avr-libc/user-manual/group__avr__fuse.html).
Is there a way to do the same for the SAM D21 ARM-based controller in AtmelStudio 6.2?
According to Atmel, the answer is no:
Question
Is it possible to include fuse information in elf production file for SAMDx devices?
Answer
No it is not possible to include fuse information in elf production file for SAMDx devices. Please see http://atmel.force.com/support/articles/en_US/FAQ/SAMD20-SAMD21-Programming-the-fuses-from-application-code on the recommended procedure to program the fuses from application code.
Your options appear to be:
Program fuses from application code, as Atmel suggests above.
Manually flip bits in the Fuses tab of Atmel Studio's Device Programming tool.
Program the fuses using atprogram.exe:
Question
How to set fuse bits for SAMR21 device using atprogram.exe?
Answer
Refer to the below command for overwriting the fuses bits.
atprogram.exe -t edbg -i SWD -d ATSAMR21G18A write -fs -o 0x804000 --values 0xEFCDAB8967452301
For fuse bit details in the NVM user row refer to Table 8-3. NVM User Row Mapping, SAMR21 datasheet.
Note:
"-o" mentions the offset, NVM user row starts at 0x804000
Reverse the value byte order: for example if 0x123456789ABCDEF has to be written, pass the value as 0xEFCDAB8967452301
Same procedure is applicable for SAM D/L/C Cortex M0+ devices as well.
I want to build a dedicated Linux system that only ever runs one binary program. This program takes control of the screen via the OpenGL driver and displays patterns. There needs to be keyboard input as well to configure the patterns. Since running this one program will be the sole purpose of the machine, I don't need any GUI, networking, etc. Also, I probably don't need any process scheduling in the kernel since only one process will ever run.
Is it possible to replace /sbin/init with my own binary to achieve this? After the kernel loads, it would then immediately execute my own binary, and that would run the entire time the machine was on. Basically, I want to emulate the way a microcontroller works, but with the benefit of being able to use an x86 CPU with different hardware devices and drivers.
Minimal init hello world program step-by-step
Compile a hello world without any dependencies that ends in an infinite loop. init.S:
.global _start
_start:
mov $1, %rax
mov $1, %rdi
mov $message, %rsi
mov $message_len, %rdx
syscall
jmp .
message: .ascii "FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR\n"
.equ message_len, . - message
We cannot use sys_exit, or else the kernel panics.
Then:
mkdir d
as --64 -o init.o init.S
ld -o init d/init.o
cd d
find . | cpio -o -H newc | gzip > ../rootfs.cpio.gz
ROOTFS_PATH="$(pwd)/../rootfs.cpio.gz"
This creates a filesystem with our hello world at /init, which is the first userland program that the kernel will run. We could also have added more files to d/ and they would be accessible from the /init program when the kernel runs.
Then cd into the Linux kernel tree, build is as usual, and run it in QEMU:
git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
cd linux
git checkout v4.9
make mrproper
make defconfig
make -j"$(nproc)"
qemu-system-x86_64 -kernel arch/x86/boot/bzImage -initrd "$ROOTFS_PATH"
And you should see a line:
FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR
on the emulator screen! Note that it is not the last line, so you have to look a bit further up.
You can also use C programs if you link them statically:
#include <stdio.h>
#include <unistd.h>
int main() {
printf("FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR\n");
sleep(0xFFFFFFFF);
return 0;
}
with:
gcc -static init.c -o init
You can run on real hardware with a USB on /dev/sdX and:
make isoimage FDINITRD="$ROOTFS_PATH"
sudo dd if=arch/x86/boot/image.iso of=/dev/sdX
Great source on this subject: http://landley.net/writing/rootfs-howto.html It also explains how to use gen_initramfs_list.sh, which is a script from the Linux kernel source tree to help automate the process.
Next step: setup BusyBox so you can interact with the system through a shell. Buildroot is a great way to do it.
Tested on Ubuntu 16.10, QEMU 2.6.1.
It might be possible to replace /sbin/init by your program, but you should be aware that process 1 has some specific duties. So I think it is not advisable to replace it.
Remember that a Linux kernel can also start some processes magically, outside of the usual fork from a process inherited by the init process. I'm thinking of things like /sbin/modprobe or /sbin/hotplug etc.
Also, udev (or systemd) have some special roles. On some systems, fan control was related to such things (I really forgot the details). If unlucky, you could burn your hardware if fan is not working well (but AFAIK this is no more true on recent hardware).
By seeking with string the vmlinux in a recent 3.15.3 kernel, I find that it knows about:
/bin/init
/bin/sh
/sbin/request-key
/sbin/tomoyo-init
/sbin/modprobe
/sbin/poweroff
/sbin/hotplug
I would recommend instead keeping some existing init program, and configure it to run only your program.
You can put your program to initrd, and then run it from initrd's init.
Simply use a boot paramter eg) init=/bin/bash
init is the process 1, used by kernel to start user space, which as a few specific duties like reaping children periodical to clean out zombies. Sounds like you don't even need that.
Linux Boot parameters you should know
I'm trying to get a stand-alone application for U-Boot running.
Target is a LEGO EV3 brick - it has an TI OMAP (ARM9) CPU.
The output of U-Boot before hanging is:
U-Boot > fatload mmc 0:1 c0007FC0 uimage
reading uimage
384 bytes read
U-Boot > bootm
## Booting kernel from Legacy Image at c0007fc0 ...
Image Name: ITK EV3 sample OS
Image Type: ARM Linux Standalone Program (uncompressed)
Data Size: 320 Bytes = 0.3 kB
Load Address: c0008000
Entry Point: c0008000
Loading Standalone Program ... OK
OK
I tried the following commands to be located at address 0xC0008000 in "uimage":
mov pc, lr (ARM code)
bx lr (ARM code)
bx lr (Thumb code)
These commands should simply return (depending on ARM or Thumb mode being active). However all three commands result in U-Boot hanging so no more output is done after the last "OK".
Why does U-Boot hang?
I found out the answer myself:
In the version of u-boot used on the EV3 brick there is a bug: The starting address that is already converted to little-endian is converted twice so the result is - of course - wrong.
By storing the number little endian in the file the output of u-boot will be wrong:
Image Type: ARM Linux Standalone Program (uncompressed)
Data Size: 320 Bytes = 0.3 kB
Load Address: c0008000
Entry Point: 008000c0 <--- actually 0xC0008000!!!
Loading Standalone Program ... OK
OK
U-Boot >
however booting will work. This bug only affects stand-alone programs and not Linux kernels.
My problem is that the program will possibly be published so it must work with both buggy and bug-fixed u-boot versions.
Therefore I think about loading the program to an address like
0xC00101C0
which is stored little and big endian the same way.
I have a problem.I have an evaluation kit and a starter_kit program which works pretty well with the toolsuites plugin of the IDE under WINDOWS xp.The same toolsuites plugin of the IDE sous Ubuntu 12.0.4 does work but doesn't do the same thing.Weired no ? just for information, my tools are:
MCU:PIC24HJ128GP504
Board:MPLAB STARTER KIT for PIC24H MCU
USB connection for load/debug SKDE PIC24H SENSOR
IDE:MPLABX IDE v1.85
C compiler:XC16 V1.11
source code: starter kit for pic24 H sensor Demo
in UBUNTU, I compile and link that source code in MPLAB X ide using XC16 C compiler without any error and then program the device but then after that Microchip logo (start-up exercise) appears on OLED,the other parts of the code are not executed (
Home screen e.g).and OLED just blinks and repeats showing Microchip logo while blinking.seems to me that it enters to a RESET LOOP.
What is weird is that when i change the OS from ubuntu to windows xp and use the same IDE installed on windows xp and same C compiler and program the device, it works perfect and doesn't enter to this seemingly reset loop.and it shows Microchip logo(start-up exercise) and executes the rest of the program(which is a Home screen).
and I don't know what is wrong.
I used this step to debug this problem with no succeed, and i would like to know what you would do if you're in my case, and if you can help me find my problem.
compare map files (linker outputs):
the two files are almost the same except that map of winXP has a resetPRI function, but that of ubuntu uses reset(which seems to me that it's a memory section, not a function).you can see the common part of map file and the differences below.
External Symbols in Program Memory (by address):
0x000200 __resetPRI
Memory Configuration:
Name Origin Length Attributes
data 0x000800 0x002000 a !xr
reset 0x000000 0x000004
program 0x000200 0x015600
LOAD libp24HJ128GP504-elf.a
.reset 0x000000 0x4
0x000000 0x2 SHORT 0x200 ABSOLUTE (__reset)
0x000001 0x2 SHORT 0x4
0x000002 0x2 SHORT 0x0 ((ABSOLUTE (__reset) >> 0x10) & 0x7f)
0x000003 0x2 SHORT 0x0
.text 0x000200 0xf06
libpic30-elf.a(crt0_standard.o)
0x000200 __reset (difference:from ubuntu map file)
0x000200 __resetPRI (difference:from winxp map file)
build/default/production/_ext/1360937237/**Main.o**
_0x40c515645214dac2 (difference:from ubuntu map file)
_0213CF005214c228 (difference:from winxp map file)
0x2600 0x1c0
_0x40c515645214dac2 (difference:from ubuntu map file)
_0213CF005214c228 (difference:from winxp map file)
0x2600 0x1c0 build/default/production/_ext/1360937237 /Accelerometer.o (ONE function in the program )
0x2600 _BufferA
_0x40c515c05214dac2 (difference:from ubuntu map file)
_0213D1205214c228 (difference:from winxp map file)
any idea where should i look for the problem would be greatly appreciated.