STM32: ST-Link tries to flash RAM region - gcc

I'm working with a STM32F407VG with 128kB of normal RAM and 64kB of Core Coupled Memory (CCM). I'm using a GCC toolchain (SW4STM32).
In my linker script I configured the CCM like this:
MEMORY
{
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 1024K
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K
CCM (xrw) : ORIGIN = 0x10000000, LENGTH = 64K
}
SECTIONS
{
...
.ccram :
{
*(.ccram)
*(.ccram*)
} >CCM
...
When I put any variables into the .ccram section I get an ELF file which seems to tell ST-Link that it has to flash the memory at 0x10000000. This fails, of course, and tells me
"Warn : no flash bank found for address 10000000".
When I create a HEX file from the ELF file, I find a block of zeros at 0x10000000. When I delete this block from the HEX file, I can flash the HEX file successfully (with ST-Link Utility) and my code runs perfectly on the target.
So how do I tell the linker (or whoever) that the CCM region shall not be marked as FLASH?

I think you need to replace >CCM with >CCM AT> FLASH
This should tell it to get the init values from flash

I got the solution:
Add "(NOLOAD)" to the deklaration of the section:
.ccram (NOLOAD):
{
*(.ccram)
*(.ccram*)
} >CCM

Related

macOS size command shows a really large number?

> size /bin/ls
__TEXT __DATA __OBJC others dec hex
20480 4096 0 4294983680 4295008256 10000a000
How could it be that ls is 4GB? Is size not meant to be used on executables? I have 4GB ram, so is it just showing me the amount memory it can use?
On macOS, 64-bit apps have a 4GB page zero, by default. Page zero is chunk of the address space starting at address 0 which allows no access. This is what causes access violations when a program dereferences a null pointer.
64-bit Mac programs use a 4GB page zero so that, should any valid pointer get accidentally truncated to 32 bits by a program bug (e.g. cast to int and back to a pointer), it will be invalid and cause a crash as soon as possible. That helps to find and fix such bugs.
The page zero segment in the Mach-O executable file doesn't actually use 4GB on disk. It's just a bit of metadata that tells the kernel and dynamic loader how much address space to reserve for it. It seems that size is including the virtual size of all segments, regardless of whether they take up space on disk or not.
Also, the page zero doesn't consume actual RAM when the program is loaded, either. Again, there's just some bookkeeping data to track the fact that the lower 4GB of the address space is reserved.
The size being reported for "others", 4294983680 bytes, is 0x100004000 in hex. That's the 4GB page zero (0x100000000) plus another 4 pages for some other segments.
You can use the -m option to size to get more detail:
$ size -m /bin/ls
Segment __PAGEZERO: 4294967296
Segment __TEXT: 20480
Section __text: 13599
Section __stubs: 456
Section __stub_helper: 776
Section __const: 504
Section __cstring: 1150
Section __unwind_info: 148
total 16633
Segment __DATA: 4096
Section __got: 40
Section __nl_symbol_ptr: 16
Section __la_symbol_ptr: 608
Section __const: 552
Section __data: 40
Section __bss: 224
Section __common: 140
total 1620
Segment __LINKEDIT: 16384
total 4295008256
You can also use the command otool -lV /bin/ls to see the loader commands of the executable, including the one establishing the __PAGEZERO segment.
The size command outputs information related to some binary executable and how it is running. It is not about the file. The 4Gb number might be (that is just my guess) related to the virtual address space needed to run it.
I don't have a MacOSX operating system (because it is proprietary and tied to hardware that I dislike and find too expensive). But on Linux (which is mostly POSIX, like MacOSX), size /bin/ls gives:
text data bss dec hex filename
124847 4672 4824 134343 20cc7 /bin/ls
while ls -l /bin/ls shows
-rwxr-xr-x 1 root root 138856 Feb 28 16:30 /bin/ls
Of course, when ls is running, it has some data (notably bss) which is not corresponding to a part of the executable
Try man size on your system to get an explanation. For Linux, see size(1) (it gives info about sections of an ELF executable) and ls(1) (it gives the file size).
On MacOSX, executables follow the Mach-O format.
On Linux, if you try size on a non-executable file such as /etc/passwd, you get
size: /etc/passwd: file format not recognized
and I guess that you should have some error message on MacOSX if you try that.
Think of size giving executable size information. The name is historical and a bit misleading.

Allocating a larger u-boot image

I am compiling my own kernel and bootloader (U-boot). I added a bunch of new environmental variables, but U-boot doesn't load anymore (it just doesn't load anything from the memory). I am using pocketbeagle and booting from an SD card. Thus I am editing the file "am335x_evm.h" found in /include/configs/.
I am trying to allocate U-boot in a way that it has more space for the environmental variables and that it can load succesfully from the memory, but I have been unable to do so. As far as I understand, by default it allocates 128kb of memory to U-boot env variables. Since I added a bunch of them, I am trying to increase its size from 128kb to 512kb.
I have changed the following line (from 128kb to 512kb):
#define CONFIG_ENV_SIZE (512 << 10)
(By the way, anyone knows why it is shifted to the left 10 bits?)
I have also changed CONFIG_ENV_OFFSET and CONFIG_ENV_OFFSET_REDUND to:
#define CONFIG_ENV_OFFSET (1152 << 10) /* Originally 768 KiB in */
#define CONFIG_ENV_OFFSET_REDUND (1664 << 10) /* Originally 896 KiB in */
Then after compiling the new U-boot, I format the SD card and insert the new kernel and U-boot.
I start by erasing partitions:
export DISK=/dev/mmcblk0
sudo dd if=/dev/zero of=${DISK} bs=1M count=10
Then I transfer U-boot by doing:
sudo dd if=./u-boot/MLO of=${DISK} count=1 seek=1 bs=512k
sudo dd if=./u-boot/u-boot.img of=${DISK} count=2 seek=1 bs=576k
I then create the partition layout by doing:
sudo sfdisk ${DISK} <<-__EOF__
4M,,L,*
__EOF__
Then I add the kernel, binary trees, kernel modules, etc... When trying to boot and reading the serial port, I get nothing at all. U-boot is not able to load anything from the SD card. What am I doing wrong? I'd appreciate if you could point me what my problem is and exactly what I should be doing to increase the size and allocate everything correctly.

fw_printenv fw_setenv on var-som-am33 is failing

Depending on a few configurations I tried in /etc/fw_env.config such as one or two entries, I got the following errors when trying to read the U-boot environment variables:
root#varsomam33:~# fw_printenv serverip
Warning: Bad CRC, using default environment
or
root#varsomam33:~# fw_printenv serverip
Cannot read bad block mark: Invalid argument
According to this tutorial (https://developer.ridgerun.com/wiki/index.php/Setting_up_fw_printenv_to_modify_u-boot_environment_variables), I constructed my /etc/fw_env.config to look like this:
# MTD device name Device offset Env. size Flash sector size Number of sectors
/dev/mtd6 0x1C0000 0x20000 0x20000 1
/dev/mtd7 0x1E0000 0x20000 0x20000 1
FYI I'm using a TI Omap ARM chip (var-som-am33) with Yocto Fido default out-of-box from Variscite with these software versions:
U-boot version: u-boot-var-som-am33 2014-+gitrAUTOINC+adf9a14020
U-boot-fw-utils version: u-boot-fw-utils v2014.07+gitAUTOINC+524123a707-r0-arago0-var
The main problem is that "Device offset" is incorrectly described in the RidgeRun tutorial. It is not the absolute offset in NAND flash, but rather the offset from the partition which should be "0x0" in my case.
Here is my working /etc/fw_env.config
root#varsomam33:~# cat /etc/fw_env.config
# MTD device name Device offset Env. size Flash sector size Number of sectors
/dev/mtd6 0x0 0x20000 0x20000 1
/dev/mtd7 0x0 0x20000 0x20000 1
Further, the CRC error I was getting is thrown when there is not a U-boot backup (redundant) environment described in the /etc/fw_env.config file. The fw_printenv utility works by copying the "selected" environment, modifying the variable you have changed, and writing it out to the "new" environment. Then it swaps "selected" and "new".
So if you only have one environment in /etc/fw_env.config, it uses default values for the "selected" environment.
Here is the code tools/env/fw_env.c
1230 crc0_ok = (crc0 == *environment.crc);
1231 if (!HaveRedundEnv) {
1232 if (!crc0_ok) {
1233 fprintf (stderr,
1234 "Warning: Bad CRC, using default environment\n");
1235 memcpy(environment.data, default_environment, sizeof default_environment);

Linux: boot arguments with U-Boot and Flat Image Tree (FIT)

I am trying to get my own build of U-Boot to boot Linux on a Jetson TK1 board. As we are pushing for verified boot I am using the Flat Image Tree (unifying kernel image, device tree blob, ...) to describe my system. U-Boot can load the ITB file and tries to start the kernel but the system hangs after this message.
I assume that this is because no boot arguments are passed to the kernel (the original startup adds loads of arguments) but I am a little dumbfounded on how to pass the arguments to the kernel. I tried setting the bootargs environment variable but this did not change the situation.
How do I pass kernel arguments to the kernel when using an ITB file?
Command line arguments (taken from the APPEND command of the examples extlinux.conf):
console=ttyS0,115200n8 console=tty1 no_console_suspend=1
lp0_vec=2064#0xf46ff000 video=tegrafb mem=1862M#2048M memtype=255 ddr_die=2048M#2048M
section=256M pmuboard=0x0177:0x0000:0x02:0x43:0x00 vpr=151M#3945M tsec=32M#3913M
otf_key=c75e5bb91eb3bd947560357b64422f85 usbcore.old_scheme_first=1 core_edp_mv=1150
core_edp_ma=4000 tegraid=40.1.1.0.0 debug_uartport=lsport,3 power_supply=Adapter
audio_codec=rt5640 modem_id=0 android.kerneltype=normal usb_port_owner_info=0
fbcon=map:1 commchip_id=0 usb_port_owner_info=0 lane_owner_info=6 emc_max_dvfs=0
touch_id=0#0 tegra_fbmem=32899072#0xad012000 board_info=0x0177:0x0000:0x02:0x43:0x00
root=/dev/mmcblk0p1 rw rootwait tegraboot=sdmmc gpt
Content of ITS file:
/dts-v1/;
/ {
description = "Simple image with single Linux kernel and FDT blob";
#address-cells = <1>;
images {
kernel#1 {
description = "Vanilla Linux kernel";
data = /incbin/("./zImage");
type = "kernel";
arch = "arm";
os = "linux";
compression = "none";
load = <0x81008000>;
entry = <0x81008000>;
hash#1 {
algo = "crc32";
};
hash#2 {
algo = "sha1";
};
};
fdt#1 {
description = "Flattened Device Tree blob";
data = /incbin/("./tegra124-pm375.dtb");
type = "flat_dt";
arch = "arm";
compression = "none";
hash#1 {
algo = "crc32";
};
hash#2 {
algo = "sha1";
};
};
};
configurations {
default = "conf#1";
conf#1 {
description = "Boot Linux kernel with FDT blob";
kernel = "kernel#1";
fdt = "fdt#1";
};
};
};
U-Boot Output:
Tegra124 (Jetson TK1) # fatload mmc 1 0x90000000 /kernel_fdt.itb
reading /kernel_fdt.itb
5946200 bytes read in 497 ms (11.4 MiB/s)
Tegra124 (Jetson TK1) # bootm 0x90000000
## Loading kernel from FIT Image at 90000000 ...
Using 'conf#1' configuration
Verifying Hash Integrity ... OK
Trying 'kernel#1' kernel subimage
Description: Vanilla Linux kernel
Type: Kernel Image
Compression: uncompressed
Data Start: 0x900000ec
Data Size: 5910168 Bytes = 5.6 MiB
Architecture: ARM
OS: Linux
Load Address: 0x00000000
Entry Point: 0x00000000
Hash algo: crc32
Hash value: c5b4b377
Hash algo: sha1
Hash value: f001007efe83f563425bfe0659186a32395c946c
Verifying Hash Integrity ... crc32+ sha1+ OK
## Loading fdt from FIT Image at 90000000 ...
Using 'conf#1' configuration
Trying 'fdt#1' fdt subimage
Description: Flattened Device Tree blob
Type: Flat Device Tree
Compression: uncompressed
Data Start: 0x905a30ac
Data Size: 34678 Bytes = 33.9 KiB
Architecture: ARM
Hash algo: crc32
Hash value: e466b23e
Hash algo: sha1
Hash value: ec909ae16e62233d0ed1e1f4c909085abc9b5879
Verifying Hash Integrity ... crc32+ sha1+ OK
Booting using the fdt blob at 0x905a30ac
Loading Kernel Image ... OK
Using Device Tree in place at 905a30ac, end 905ae821
Starting kernel ...
The salient issue is that the system seems to hang after U-Boot outputs the text
Starting kernel ...
If an uncompressed kernel Image file has been loaded, then the actual kernel startup code would be executed next.
But if a uImage or zImage file has been loaded (which are also reported as "uncompressed" because they are self-extracting), then the next code executed would be the decompression routine that is attached to the zImage file. Normally this decompression routine will output text such as
Uncompressing Linux............ done, booting the kernel.
before the actual kernel startup code would be executed, before any processing of the kernel command line, before any processing of the Device Tree blob, and prior to any console output from the kernel (including earlyprintk).
There's a discrepancy between the kernel load & start addresses specified in the image header
Load Address: 0x00000000
Entry Point: 0x00000000
versus what is specified in the DT:
load = <0x81008000>;
entry = <0x81008000>;
Since the kernel image is temporarily loaded at
## Loading kernel from FIT Image at 90000000 ...
the addresses in the DT would seem to be correct, and the addresses in the image header are bogus.
Assuming that there is no physical RAM at 0x00000000, the result will be that the kernel image is copied (or decompressed) to the bogus load address of 0, and then the kernel image will be executed by branching to the bogus entry point of 0. The CPU is likely to hang trying to execute garbage from nonexistent memory, and that correlates perfectly with what you report.
Solution is (1) confirm that the kernel is linked to the correct address and (2) to specify the correct addresses in the mkimage command using the -a and -e command options.
This correction should at least get you past this one point.
When using device tree, you still use bootargs to provide arguments.
Check that:
You have compiled the tree (using compiler scripts/dtc/dtc inside the Linux kernel)
Support for device tree is enabled in the kernel config (symbol CONFIG_USE_OF) (where OF stands for "Open Firmware")
You provided U-Boot the address of the tree: bootm <uImage address> - <dtb address>
Serial console is enabled in the kernel config under Device Drivers -> Character Devices -> Serial Drivers
Console is enabled in bootargs (e.g., console=ttyS0,115200)
I experienced the same or similar issue. My solution (or work around) for this issue was to set the U-Boot environment variables initrd_high and fdt_high to an address in RAM before the relocated U-boot (in my case 8effffff).

Floppy disk sector count

I am trying to understand why lseek() is used in this image creator. Why 5 bytes away from start of file? If I changed that number, the OS won't boot.
The image creator creates a .img file with the bootloader.bin inside.
/* modify the sector count */
total_sector_number = file_size / 512
lseek(disk_image_fd, 5, SEEK_SET);
write(disk_image_fd, &total_sector_number, 2);
write(disk_image_fd, &kernel_32_sector_number, 2);
//printf("%d\n", lawl);
printf("TOTAL_SECTOR_NUMBER : %d\n", total_sector_number);
printf("KERNEL_32_SECTOR_NUMBER : %d\n", kernel_32_sector_number);
The source code (image maker):
http://pastebin.com/raw.php?i=MuDpYP3Y
Bootloader:
http://pastebin.com/raw.php?i=kzw2ZaU1
The hexdump with lseek() and writing umber of sectors to byte at offset 5:
Without lseek() OS does not boot correctly.
I only figured this out because of your previous post Bootloader memory location which contained different source code for the bootloader.
You mentioned the two unknown variables TOTALSECTORCOUNT and KERNEL32SECTORCOUNT. These variables were near the beginning of the file, and I guess when assembled they sit 5 bytes into the binary. Calling lseek with the SEEK_SET parameter moves the file pointer to 5 bytes after the beginning of the file. It then writes the two values which will overwrite the ones in the bootloader code.
When you remove the lseek it will instead append the two values to the end of the file. If you changed the offset parameter of lseek to zero it would overwrite the jmp command of the bootloader instead.
Notice in your hexdump.
00000000 00eb b8fa 02c0 0000 c000 e08e e88e 00b8
^ ^- kernel_32_sector_number is never initialized.
|-total_sector_number which was calculated in code before the write.

Resources