I am experiencing extremely bizarre behavior where variables are randomly changing.
I have distilled it to the simplest example, encoder_1_position and encoder_2_position get updated with randomly values inside the NVIC_SetPriority(UART_IRQn,2); function. I have reordered declarations of the global variables in the file and I noticed it makes a difference as to what/if garbage gets added to them. I since disabled "remove unused sections" in the linker command and it seemed to fix the problem(apparently the BSS section was being tossed out) but I don't understand why particularly since every global variable I have is declared with volatile.
Reducing the buffer size from 1000 to 100 seems to correct the random change to the encoder variables, but I'm not confident it's an actual fix nor should it be required. The SAM3X8E has 65kbytes of ram - the stack shouldn't overflow regardless.
#include "sam.h"
#define HEAP_SIZE 0x500
#define STACK_SIZE 0x3500
int encoder_1_position = 0;
int encoder_2_position = 0;
void IntializeWatchdogTimer(void)
{
// disable watchdog timer
WDT->WDT_MR = WDT_MR_WDDIS;
}
void InitializeUart(void)
{
PMC->PMC_PCER0 = PMC_PCER0_PID8;// ID_UART 8
// baud rate is 84Mhz/(16*45) = 116667
UART->UART_BRGR = uint32_t(45);
// set to no parity
UART->UART_MR = UART_MR_PAR_NO;
// Enable transmit and receive
UART->UART_CR = UART_CR_TXEN|UART_CR_RXEN;
// Enable UART control of port A pin 8, 9
PIOA->PIO_PDR = PIO_PER_P8|PIO_PER_P9;
// Enable UART interrupt on RX RDY
UART->UART_IER = UART_IER_RXRDY;
// Set priority
NVIC_SetPriority(UART_IRQn,2);
NVIC_EnableIRQ(UART_IRQn);
}
int main(void)
{
__disable_irq();
IntializeWatchdogTimer();
SystemInit();
InitializeUart();
__enable_irq();
/* Initialize the SAM system */
//char* RX_message;
char TX_message[1000];
while (true)
{
int a = encoder_1_position;
int b = encoder_2_position;
}
}
readelf output:
Elf file type is EXEC (Executable file)
Entry point 0x80000
There are 2 program headers, starting at offset 52
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
LOAD 0x010000 0x00080000 0x00080000 0x02a58 0x02a58 R E 0x10000
LOAD 0x020000 0x20000000 0x00082a58 0x001d4 0x00808 RW 0x10000
Section to Segment mapping:
Segment Sections...
00 .text
01 .relocate .bss .stack .heap
I since disabled "remove unused sections" in the linker command and it seemed to fix the problem(apparently the BSS section was being tossed out)
This is just a guess, but that could mean that your program loader is not processing the BSS section correctly. It is supposed to allocate and zero the memory region the linker assigned to the BSS, even if there are no bits to copy from the executable image to that range. (It's a little more complicated than that, but unless you are stuck writing the loader yourself, that should give you enough of an idea.)
but I don't understand why particularly since every global variable I have is declared with volatile.
volatile doesn't do what you think it does. (More detail.)
Related
I am coding a bootloader for Nucleo-F429ZI. I have two different STM32 projects, one for the bootloader itself and an application to jump from the bootloader.
Linker script for bootloader
MEMORY
{
CCMRAM (xrw) : ORIGIN = 0x10000000, LENGTH = 64K
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 32K
FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 32K
}
Linker script for app
_estack = ORIGIN(RAM) + LENGTH(RAM);
MEMORY
{
CCMRAM (xrw) : ORIGIN = 0x10000000, LENGTH = 64K
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 192K
FLASH (rx) : ORIGIN = 0x8008000, LENGTH = 64K
}
I did not forget to set the flash offset of the app.
system_stm32f4xx.c (in the app project)
#define VECT_TAB_BASE_ADDRESS FLASH_BASE // 0x8000000
#define VECT_TAB_OFFSET 0x00008000U
The tutorial of STMicroelectronics about bootloaders has the following code to jump
main.c (in bootloader project)
#define FLASH_APP_ADDR 0x8008000
typedef void (*pFunction)(void);
uint32_t JumpAddress;
pFunction Jump_To_Application;
void go2APP(void)
{
JumpAddress = *(uint32_t*)(FLASH_APP_ADDR + 4);
Jump_To_Application = (pFunction) JumpAddress;
__set_MSP(*(uint32_t*)FLASH_APP_ADDR); // in cmsis_gcc.h
Jump_To_Application();
}
cmsis_gcc.h (in bootloader project)
__STATIC_FORCEINLINE void __set_MSP(uint32_t topOfMainStack)
{
__ASM volatile ("MSR msp, %0" : : "r" (topOfMainStack) : );
}
As you can see, __set_MSP function sets the main stack pointer before jumping to FLASH_APP_ADDR + 4.
I found the memory location of the target place by debugging. FLASH_APP_ADDR + 4 caused to run Reset_Handler function of app project. Lets see what will be executed.
startup_stm32f429zitx.c (in the app project)
.section .text.Reset_Handler
.weak Reset_Handler
.type Reset_Handler, %function
Reset_Handler:
ldr sp, =_estack /* set stack pointer */
/* Copy the data segment initializers from flash to SRAM */
ldr r0, =_sdata
ldr r1, =_edata
ldr r2, =_sidata
movs r3, #0
b LoopCopyDataInit
First thing of what Reset_Handler does is setting the stack pointer. _estack was defined in linker script.
If Reset_Handler is setting stack pointer, why did we call the __set_MSP function? I remove the function __set_MSP and bootloding process is still working. However I examined some other bootloader codes and found the exact same logic.
I tried what i have said and could not find an explanation.
Cortex-M core the loads SP register with initial value from address FLASH_BASE+0 during boot sequence. Then jumps to the code entry point (Reset vector) from address FLASH_BASE+4. Any bootloader code mimics core behaviour. Note, that FLASH_BASE here is not necessarily actual flash base, but an abstract value, that depends on the used processor, and it's settings.
Provided Reset_Handler code loads the sp register with __estack (Main stack top) value, but it doesn't have to! Bootloader can not expect the main program to do it, but has perform the same boot sequence as the core after reset. This way the main code doesn't have to rely on knowing, who started it - core, bootloader, jtag, or something else.
I've seen startup code, that doesn't load SP, but disables interrupts with the first instruction. Or startup code, written in C, which could use stack with the first instruction.
The real question here could be: Why this startup code loads SP if it is already loaded? But perhaps it should be forwarded to the original code author.
Let's see what's happening line by line.
JumpAddress = *(uint32_t*)(FLASH_APP_ADDR + 4);
Okay, so we take FLASH_APP_ADDR, add 1 word to it, call it a pointer to a word, dereference it. So it's the content of 0x8008004 (which is the one word after start of the vector table - list of interrupt handler pointers). You can find it in the vector table in reference manual. Here is reference manual for your MCU. Page 375
Next,
Jump_To_Application = (pFunction) JumpAddress;
Okay, so we treat reset handler address as a void function(void).
Eventually, you get to the stack
__set_MSP(*(uint32_t*)FLASH_APP_ADDR);
This function, as we see from its source code, simply sets main stack pointer to its argument. The argument is take vector table address, treat it as a pointer to a word, dereference it. So it's the first word of that vector table. And the first word of the vector table is the main stack pointer auto-loaded after power on. By definition of the vector table. You reset the stack to cold boot value, same value as the first word of your Flash. Your bootloader has used some stack until this point, but it won't be needed anymore, and the bootloader function will never return and free that stack, so you just reset stack to its initial value for your program. It will reuse all stack used by the bootloader.
So right now you've reset the stack pointer and you assigned reset handler to the function you call. And then you, well, call it.
Your vector table and the program that the bootloader starts are two different entities in memory. If you don't need to remap the interrupt handlers at runtime, don't move the vector table. It will stay at the beginning of the flash and will lead to the default interrupt handlers. Just make sure the address you execute from contains executable code and you run it from the start (well, if you don't, you will hardfault).
I want to implement a stack usage monitor for my NRF52840-Mikrocontroller with Segger Embedded Studio.
To monitor the maximum stack usage, I need some information during runtime like the end address of the .bss segment, which is the start of my free memory.
My approach is, to fill the ram from the .tbss section until to the stackpointer with a magic word.
During runtime, the stack will grow and will overwrite my magic words with data.
In a cyclic check, I am able to dedicate the end of the stack. From that information, I can derive the approximate stack usage.
Is it possible to get the addresses from the picture below during runtime in my c (or ASM) Program?
Here is a part of my .map file, where for example the symbol __bss_start is defined. Is it possible to access this symbol from c code?
*(COMMON)
0x0000000020020ec4 __bss_end__ = (__bss_start__ + SIZEOF (.bss))
0x000000000001b8c8 __bss_size__ = SIZEOF (.bss)
0x0000000020020ec4 __bss_load_end__ = __bss_end__
0x0000000000000001 . = ASSERT (((__bss_start__ == __bss_end__) || ((__bss_end__ - __RAM_segment_start__) <= __RAM_segment_size__)), error: .bss is too large to fit in RAM memory segment)
0x0000000020020ec4 __tbss_load_start__ = ALIGN (__bss_end__, 0x4)
Thanks for your help, I have solved the Problem now.
To access the symbols of the .map file during runtime, I used the following code:
extern char __bss_end__;
int main()
{
char * bss = &__bss_end__;
}
After this line of code, the bss variable contains the start address of the bss-section.
With this code, I am able to get the addresses of the RAM segments during runtime to monitor my stack usage.
I use a STM32F411RE.
Since I've no more memory in my RAM. I decided to store large variable in my flash. For that I created a section in section.ld.
.large_buffer: ALIGN(4)
{
. = ALIGN(4) ;
*(.large_buffer.large_buffer.*)
. = ALIGN(4) ;
} >FLASH
In the main.c file, I declare the variable as follow :
uint8_t buffer[60 * 200] __attribute__ ((section(".large_buffer"), used));
At this point everything is OK, the buffer is not stocked in the RAM (bss), I can access it and rewrite it.
buffer[25] = 42;
printf("%d\n", buffer[25]); // 42
The problem comes when I want to edit the variable from an other file.
main.c
uint8_t buffer[60 * 200] __attribute__ ((section(".large_buffer"), used));
int main()
{
myFunc(buffer);
}
other.c
myFunc(uint8_t* buffer)
{
buffer[25] = 42;
printf("%d\n", buffer[25]); // 0
}
buffer never change in another file (passed as parameter).
Did I miss something ?
You cannot write to flash memory the same way as you write to RAM, because of physical design of flash memories. To be exact you need to erase sector/page (let's say ~ 1-4kB, it's specified in your MCU datasheet). The reason is that flash are made that they retain state even if they're not powered, whenever you want to change any bit from value 0 -> 1 you need to erase whole sector (After erase all of bits will be set to 1).
So you cannot use Flash as data memory, what you could do is use Flash as storing variables that are const (read-only) value, so any look-up tables will perfectly fit in there (usually compilers when you stat variable to const will put them inside of flash). How to write to flash you can read in Reference Manual of your MCU.
I use GNU for ARM and want to define some cell in RAM memory space as following:
#define FOO_LOCATION 0x20000000
#define foo (*((volatile uint32_t *) FOO_LOCATION ))
My question is - if such declaration will prohibit usage of the cell with FOO_LOCATION address in stack or heap? What address preffered to avoid memory fragmentation?
Update
I want to place some variable at a certain memory address and access it after watchdog reset. I guess that if i will declare it as usual
uint32_t foo;
it will have another physical location after reset. Also i read a post where said that most probably there is no such way to declare variable adddress. And i have idea to tell the GNU not to use some memory address. As for example special registers are not used by custom variables.
Update 2
In addition to previous definitions i added section to linker script
SECTIONS
{
. = 0x20000000
.fooSection :
{
*(.fooSection)
. = 0x04 /* size = 4 bytes */
}
/* other placements follow here... */
}
Below is a portion of the C code I am using:
pushbutton_ISR()
{
int press;
int key_pressed;
press = *(KEYS_ptr + 3); // read the pushbutton Edge Det Register interrupt register
*(KEYS_ptr + 3) = 0; // Clear the Edge Det registers.
if (press & 0x1) { // KEY1
key_pressed = KEY1;
//sum = sum + *NEW_NUMBER;
}
else if (press & 0x2) { // KEY2
key_pressed = KEY2;
*GREEN_LEDS = *NEW_NUMBER;
sum = sum + *NEW_NUMBER;
*RED_LEDS = sum;
}
else // i.e. (press & 0x8), which is KEY3
sum = *(NEW_NUMBER); // Read the SW slider switch values; store in pattern
return;
}
The compiler compiles this fine and the code appears to run (on an Altera board) fine. However, when I change the first if statement to:
if (press & 0x1) { // KEY1
//key_pressed = KEY1;
sum = sum + *NEW_NUMBER;
}
the compiler gives the following error messages:
.../nios2-elf/bin/ld.exe: section .data loaded at [00000a00,00000e0f] overlaps section .text loaded at [00000500,00000a0f]
.../nios2-elf/bin/ld.exe: section .ctors loaded at [00000a10,00000a13] overlaps section .data loaded at [00000a00,00000e0f]
.../nios2-elf/bin/ld.exe: Z:/Projects/Altera/3215_W15_LabB/Part2/from_handout.elf: section .data vma 0xa00 overlaps previous sections
.../nios2-elf/bin/ld.exe: Z:/Projects/Altera/3215_W15_LabB/Part2/from_handout.elf: section .ctors vma 0xa10 overlaps previous sections
.../nios2-elf/bin/ld.exe: Z:/Projects/Altera/3215_W15_LabB/Part2/from_handout.elf: section .rodata vma 0xa14 overlaps previous sections
.../nios2-elf/bin/ld.exe: Z:/Projects/Altera/3215_W15_LabB/Part2/from_handout.elf: section .sdata vma 0xe10 overlaps previous sections
.../nios2-elf/bin/ld.exe: Z:/Projects/Altera/3215_W15_LabB/Part2/from_handout.elf: section .sbss vma 0xe18 overlaps previous sections
Could you please advise me about the reasons for these errors, and how to resolve them.
This has nothing to do with your code being incorrect.
These are linker errors (it even tells you ld.exe is the program complaining) about output sections overlapping. This probably means you just ran out of space, but could also mean the linker directive file your project is using has some problems.
When you add in this line, it causes the size of the compiled code to be too big for the memory area that you are loading the code into.
You can see from the first line of the linker error message that .text (the code) is loaded at 0x500, and .data (the non-zero static variables) is loaded at 0xa00. However, the .text section is so long that it is too big to fit in the space between 0x500 and 0xa00.
To fix this you will either need to:
Make your code smaller
Increase the amount of space available for .text
To do the first one, you could use -Os or similar compiler option to compile for minimum code size ; or manually rewrite your code to be smaller.
For the second one you really need to understand the hardware you are loading the code into. Is it a hardware requirement that code goes at 0x500 and data goes at 0xa00? If not, then you may be able to load the code and/or data into different addresses.
These addresses are configured in your linker script (this may be hardcoded into the makefile or it may be an actual file somewhere). Hopefully the hardware device came with documentation that explains how much memory it has and where you're allowed to load your code to.