`.bss' is not within region `ram' error - esp32 ulp risv-v - c

I'm trying to copy array elements from one array to another.
One of the arrays uses a int32_t index to track the current index.
int32_t pres_log_last_5_readings_raw[5];
int32_t final_arr_pressure[100];
int32_t final_array_index = 0;
for (int i = 0; i < 4; i++)
{
final_arr_pressure[final_array_index] = pres_log_last_5_readings_raw[i]; // This line will compile without error if the next line is commented
final_array_index++;
}
If the line is active I will get this error:
/Users/user/.espressif/tools/riscv32-esp-elf/esp-2022r1-11.2.0/riscv32-esp-elf/bin/../lib/gcc/riscv32-esp-elf/11.2.0/../../../../riscv32-esp-elf/bin/ld: address 0x10dc of ulp_main section `.bss' is not within region `ram'
/Users/user/.espressif/tools/riscv32-esp-elf/esp-2022r1-11.2.0/riscv32-esp-elf/bin/../lib/gcc/riscv32-esp-elf/11.2.0/../../../../riscv32-esp-elf/bin/ld: address 0x10dc of ulp_main section `.bss' is not within region `ram'
collect2: error: ld returned 1 exit status
I've tried many variations but nothing seems to work, I'm not sure if the problem is with my C skills or with the esp idf compiler.
**
Solved:
**
The right answer is indeed me running out if memory, reducing the size of the arrays to 50 fixed the problem.
I do need to mention that I should have increased the memory allocation for slow rtc memory from 4kb to 8kb in idf.py menuconfig! This would solve the problem without changing the size to 50 (in my case).
Thanks everyone

This error message says that your uninitialized static storage data (stored in the .bss section) is too big. Basically, you ran out of RAM. You need to reduce the number and size of your variables.

Related

Ethernet is stopped after using global variables in STM32

I am using STM32H735ZGTx_ LQFP144.
I have done Ethernet configuration according to this link https://controllerstech.com/stm32-ethernet-1-connection/
If I am not using any global in any of the source file, I am not facing any issue, Ethernet is working fine.
Whenever I declare and use global variables or static variables, I am facing some issue and the Ethernet is stopped.
I am getting different errors based on the global variables size, as follows
char buff[5] = "123"; //initialized
Error : Hard Fault error
char buff[100]; // uninitialized
Error: ssertion "pc>custom_free_function != NULL" failed at line 767 in../Middlewares/Third_Party/LwIP/sr/core/pbuf.c
char buff[200]: //uninitialized
Error:
Assertion "pbuf_free: p->ref > 0" failed at line 753 in../Middlewares/Third_Party/LwIP/src/core/pbuf.c
Error: Assertion "mem_trim: legal memory" failed at line 721 in ../Middlewares/Third_Party/LwIP/src/core/mem.c
Changing the variable size is changing the errors.
I'm new to STM, please help me with this issue.
I have checked the address of global variables, all are stored in RAM_D1.
In the hard fault, I noticed that, it's causing error when it is in pbuf_free() function.
I have found that, some of the STM32H7x series have the ethernet issues.
Although we configured the address in CubeMX in ethernetif.c but we need to place RX_POOL buffer at specific RAM.
/* USER CODE BEGIN 2 */
#if defined ( __GNUC__ ) /* GNU Compiler */
__attribute__((section(".Rx_PoolSection"))) extern u8_tmemp_memory_RX_POOL_base[];
#endif
/* USER CODE END 2 */
Modify the linkerscript (*.ld) that the ETH descriptors and buffers are located in D2 SRAM. Also it is recommended to place all RAM to RAM_D1. In STM32CubeMX generated project, the "_FLASH" suffix linkerscript should be modified, which is used by default
(e.g.: STM32H750XBHx_FLASH.ld). The "_RAM" suffix linkerscript is template for executing code from internal RAM memory.
} >RAM_D1
/* Modification start */
.lwip_sec (NOLOAD) :
{
. = ABSOLUTE(0x30040000);
*(.RxDecripSection)
. = ABSOLUTE(0x30040060);
*(.TxDecripSection)
/* Rx_Pool section must be added in linker */
. = ABSOLUTE(0x30040200);
*(.Rx_PoolSection)
} >RAM_D2
After these modifications, my issue was resolved.
Rx_Pool stores the pbufs, but due to improper alignment it was over writing some of the pbuf pointers.
Note: If you are storing Rx_Pool in some other ram or address, the alignment must be proper, or else it wil over write again.

Offload into MIC (Xeon Phi) error iterating over loaded array

I have problems when offloading some datastructures to my MIC.
I am offloading into MIC with the following directives:
#pragma offload target(mic:mic_no)\
inout(is_selected : length(query_sequences_count)ALLOC)\
in(a:length(a_size) ALLOC)\
in(a_disp:length(offload_db_count)ALLOC)
However if I try to execute inside the offloaded region:
//loads next 64 characters of a into datadb
__m512i datadb __attribute__ ((aligned(64)));
datadb = _mm512_load_epi32(a+iter_db+a_disp[j]);
This causes the following error:
Offload error:process on the device 0 was terminated by signal 11(SIGSEGV)
But if I instead copy the content of a into another array like this:
char db[64];
for(window_db_iter = 0; window_db_iter < 64; window_db_iter++)
db[window_db_iter] = *(a+iter_db+a_disp[j]+window_db_iter);
//Now this works fine
datadb = _mm512_load_epi32(db);
I have checked that a offloads with the correct length, a_size is the size of a and that a_disp is correct as well. Also a+iter_db+a_disp[j] remains always inside the bounds of memory. My guess is that it has to do with the process of copying the memory onto the MIC. Any ideas?
Thanks!
After some time, I have found the answer to my question.
First the data structure needs to be aligned. If not, it is going to return an error. The Offload error does not mean the error was caused during the process of copying memory from host CPU to coprocessor, it can be caused anywhere in the code.
Second, if you have unaligned memory and cannot/dont want to align it you can use the align modifier during the offload like this:
#pragma offload target(mic:mic_no)\
inout(is_selected : length(query_sequences_count)ALLOC)\
in(a[0:a_size]: aligned(64) ALLOC)\
in(a_disp:length(offload_db_count)ALLOC)
Now the copied memory will be copied aligned.

snprintf() prints garbage floats with newlib nano

I am running a bare metal embedded system with an ARM Cortex-M3 (STM32F205). When I try to use snprintf() with float numbers, e.g.:
float f;
f = 1.23;
snprintf(s, 20, "%5.2f", f);
I get garbage into s. The format seems to be honored, i.e. the garbage is a well-formed string with digits, decimal point, and two trailing digits. However, if I repeat the snprintf, the string may change between two calls.
Floating point mathematics seems to work otherwise, and snprintf works with integers, e.g.:
snprintf(s, 20, "%10d", 1234567);
I use the newlib-nano implementation with the -u _printf_float linker switch. The compiler is arm-none-eabi-gcc.
I do have a strong suspicion of memory allocation problems, as integers are printed without any hiccups, but floats act as if they got corrupted in the process. The printf family functions call malloc with floats, not with integers.
The only piece of code not belonging to newlib I am using in this context is my _sbrk(), which is required by malloc.
caddr_t _sbrk(int incr)
{
extern char _Heap_Begin; // Defined by the linker.
extern char _Heap_Limit; // Defined by the linker.
static char* current_heap_end;
char* current_block_address;
// first allocation
if (current_heap_end == 0)
current_heap_end = &_Heap_Begin;
current_block_address = current_heap_end;
// increment and align to 4-octet border
incr = (incr + 3) & (~3);
current_heap_end += incr;
// Overflow?
if (current_heap_end > &_Heap_Limit)
{
errno = ENOMEM;
current_heap_end = current_block_address;
return (caddr_t) - 1;
}
return (caddr_t)current_block_address;
}
As far as I have been able to track, this should work. It seems that no-one ever calls it with negative increments, but I guess that is due to the design of the newlib malloc. The only slightly odd thing is that the first call to _sbrk has a zero increment. (But this may be just malloc's curiosity about the starting address of the heap.)
The stack should not collide with the heap, as there is around 60 KiB RAM for the two. The linker script may be insane, but at least the heap and stack addresses seem to be correct.
As it may happen that someone else gets bitten by the same bug, I post an answer to my own question. However, it was #Notlikethat 's comment which suggested the correct answer.
This is a lesson of Thou shall not steal. I borrowed the gcc linker script which came with the STMCubeMX code generator. Unfortunately, the script along with the startup file is broken.
The relevant part of the original linker script:
_estack = 0x2000ffff;
and its counterparts in the startup script:
Reset_Handler:
ldr sp, =_estack /* set stack pointer */
...
g_pfnVectors:
.word _estack
.word Reset_Handler
...
The first interrupt vector position (at 0) should always point to the startup stack top. When the reset interrupt is reached, it also loads the stack pointer. (As far as I can say, the latter one is unnecessary as the HW anyway reloads the SP from the 0th vector before calling the reset handler.)
The Cortex-M stack pointer should always point to the last item in the stack. At startup there are no items in the stack and thus the pointer should point to the first address above the actual memory, 0x020010000 in this case. With the original linker script the stack pointer is set to 0x0200ffff, which actually results in sp = 0x0200fffc (the hardware forces word-aligned stack). After this the stack is misaligned by 4.
I changed the linker script by removing the constant definition of _estack and replacing it by _stacktop as shown below. The memory definitions were there before. I changed the name just to see where the value is used.
MEMORY
{
FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 128K
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 64K
}
_stacktop = ORIGIN(RAM) + LENGTH(RAM);
After this the value of _stacktop is 0x20010000, and my numbers float beautifully... The same problem could arise with any external (library) function using double length parameters, as the ARM Cortex ABI states that the stack must be aligned to 8 octets when calling external functions.
snprintf accepts size as second argument. You might want to go through this example http://www.cplusplus.com/reference/cstdio/snprintf/
/* snprintf example */
#include <stdio.h>
int main ()
{
char buffer [100];
int cx;
cx = snprintf ( buffer, 100, "The half of %d is %d", 60, 60/2 );
snprintf ( buffer+cx, 100-cx, ", and the half of that is %d.", 60/2/2 );
puts (buffer);
return 0;
}

Go: Effects of empty curly braces on array initialisation memory allocation

I was playing with different ways to initialise/declare arrays in golang. I got different behaviours/results.
go version go1.3 darwin/amd64
version 1:
func main() {
a := [100000000]int64{}
var i int64
for i = 0; i < 100000000; i++ {
a[i] = i
}
}
Produces a 763MB binary. It crashes after a few seconds when I run it with this message.
runtime: goroutine stack exceeds 1000000000-byte limit
fatal error: stack overflow
version 2:
func main() {
var a [100000000]int64
var i int64
for i = 0; i < 100000000; i++ {
a[i] = i
}
}
Produces a 456KB binary. It runs in less than one second.
Question:
Can anybody help me understand why those differences (and other I may have missed) are there? Thanks!
edit:
Running times:
I built the two different snippets and run the compiled versions, so the compilation time wasn't added. The first time I run version1 is extremely slow in comparison though. Here is the output.
go build version1.go
go build version2.go
These are the execution outputs
version 1
first run
time ./version1
runtime: goroutine stack exceeds 1000000000-byte limit
fatal error: stack overflow
runtime stack:
runtime.throw(0x2fb42a8e)
/usr/local/Cellar/go/1.3/libexec/src/pkg/runtime/panic.c:520 +0x69
runtime.newstack()
/usr/local/Cellar/go/1.3/libexec/src/pkg/runtime/stack.c:770 +0x486
runtime.morestack()
/usr/local/Cellar/go/1.3/libexec/src/pkg/runtime/asm_amd64.s:228 +0x61
goroutine 16 [stack growth]:
main.main()
/Users/ec/repo/offers/lol/version1.go:3 fp=0x2b7b85f50 sp=0x2b7b85f48
runtime.main()
/usr/local/Cellar/go/1.3/libexec/src/pkg/runtime/proc.c:247 +0x11a fp=0x2b7b85fa8 sp=0x2b7b85f50
runtime.goexit()
/usr/local/Cellar/go/1.3/libexec/src/pkg/runtime/proc.c:1445 fp=0x2b7b85fb0 sp=0x2b7b85fa8
created by _rt0_go
/usr/local/Cellar/go/1.3/libexec/src/pkg/runtime/asm_amd64.s:97 +0x120
goroutine 17 [runnable]:
runtime.MHeap_Scavenger()
/usr/local/Cellar/go/1.3/libexec/src/pkg/runtime/mheap.c:507
runtime.goexit()
/usr/local/Cellar/go/1.3/libexec/src/pkg/runtime/proc.c:1445
./version1 0.00s user 0.10s system 1% cpu 7.799 total
second run
runtime: goroutine stack exceeds 1000000000-byte limit
fatal error: stack overflow
runtime stack:
runtime.throw(0x2fb42a8e)
/usr/local/Cellar/go/1.3/libexec/src/pkg/runtime/panic.c:520 +0x69
runtime.newstack()
/usr/local/Cellar/go/1.3/libexec/src/pkg/runtime/stack.c:770 +0x486
runtime.morestack()
/usr/local/Cellar/go/1.3/libexec/src/pkg/runtime/asm_amd64.s:228 +0x61
goroutine 16 [stack growth]:
main.main()
/Users/ec/repo/offers/lol/version1.go:3 fp=0x2b7b85f50 sp=0x2b7b85f48
runtime.main()
/usr/local/Cellar/go/1.3/libexec/src/pkg/runtime/proc.c:247 +0x11a fp=0x2b7b85fa8 sp=0x2b7b85f50
runtime.goexit()
/usr/local/Cellar/go/1.3/libexec/src/pkg/runtime/proc.c:1445 fp=0x2b7b85fb0 sp=0x2b7b85fa8
created by _rt0_go
/usr/local/Cellar/go/1.3/libexec/src/pkg/runtime/asm_amd64.s:97 +0x120
goroutine 17 [runnable]:
runtime.MHeap_Scavenger()
/usr/local/Cellar/go/1.3/libexec/src/pkg/runtime/mheap.c:507
runtime.goexit()
/usr/local/Cellar/go/1.3/libexec/src/pkg/runtime/proc.c:1445
./version1 0.00s user 0.10s system 98% cpu 0.102 total
version 2
first run
time ./version2
./version2 0.16s user 0.26s system 99% cpu 0.429 total
second run
time ./version2
./version2 0.17s user 0.25s system 97% cpu 0.421 total
In Version 1, you're declaring a literal array of [100000000]int64{} which the compiler immediately allocates.
Version 2, you're only declaring the type of a as [100000000]int64.
When you only have a variable declaration, the contents aren't known at that point during compilation. In version 2, the compiler knows that a is of type [100000000]int64, but the memory isn't allocated until runtime.
When you use a literal, that exact memory representation is written into the binary. It works the same as if you declared a string literal vs a variable of type string; the string literal will be written in place, while a variable declaration is only a placeholder.
Even though the current compiler (go 1.3) allows a to escape to the heap, the literal data is expected to live in the stack frame. You can see this in the assembly output (frame size is 800000016):
TEXT "".func1+0(SB),$800000016-0
If you actually need a larger literal than what can fit in the stack, you can place it in a global variable. The following executes just fine:
var a = [100000000]int64{1}
func func1() {
var i int64
for i = 0; i < 100000000; i++ {
a[i] = i
}
}
I did have to initialize at least one value in a here, because it seems that the compiler can elide this literal, if it's equal to the zero value.
It's not actually an answer but maybe someone can find this useful.
In my case this happens when I've try to json.Marshal following structure:
type Element struct {
Parent *Element
Child []*Element
}
Where Parent points to element which has current element in Child.
So I just mark "Parent" as json:"-" to be ignored in marshalling.

Why does using a structure in C program cause Link error

I am writing a C program for a 8051 architecture chip and the SDCC compiler.
I have a structure called FilterStructure;
my code looks like this...
#define NAME_SIZE 8
typedef struct {
char Name[NAME_SIZE];
} FilterStructure;
void ReadFilterName(U8 WheelID, U8 Filter, FilterStructure* NameStructure);
int main (void)
{
FilterStructure testStruct;
ReadFilterName('A', 3, &testFilter);
...
...
return 0;
}
void ReadFilterName(U8 WheelID, U8 Filter, FilterStructure* NameStructure)
{
int StartOfName = 0;
int i = 0;
///... do some stuff...
for(i = 0; i < 8; i++)
{
NameStructure->Name[i] = FLASH_ByteRead(StartOfName + i);
}
return;
}
For some reason I get a link error "?ASlink-Error-Could not get 29 consecutive bytes in internal RAM for area DSEG"
If I comment out the line that says FilterStructure testStruct; the error goes away.
What does this error mean? Do I need to discard the structure when I am done with it?
The message means that your local variable testStruct couldn't be allocated in RAM (or DSEG that should be DATA SEGMENT of your binary), since your memory manager couldn't find 29 consecutive bytes to allocate it.
This is strange since your struct should be 8 bytes long.. but btw it's nothing to do with discarding the structure, this seems a memory management problem.. I don't know 8051 specs so well but it should be quite limited right?
EDIT: looking at 8051 specs it seems it just has 128 bytes of RAM. This can cause the problem because the variable, declared as a local, is allocated in internal RAM while you should try to allocate it on an external RAM chip if it's possible (using the address/data bus of the chip), but I'm not sure since this kind of microcontroller shouldn't be used to do these things.
you've run out of memory....by the looks of it.
try moving it out as a global variable, see if that makes it better.
Just a guess: 8051 has only 128 or 256 bytes of "internal RAM". Not so much... It can use part of it as stack and part for registers. Maybe your "large" (8 bytes!!!) structure on the stack forces the compiler to reserve too much stack space inside the internal memory. I suggest to have a look into the linker map file, maybe you can "rearrange" the memory partition. The massage says "consecutive bytes", so perhaps there is still enough space availabe, but it's fragmented.
Bye

Resources