I'm having a memory problem in a bare metal app.
I have 2 global variables in a C file:
int var = 1;
int *p_var = &(var);
The same file has a function (IRQ handler) where the following statements are true:
var == 1
*p_var != var
Desired behavior: Isn't *p_var supposed to be equals to var?
Any help is appreciated!
UPDATE: Thank you for your replies so far.
Since the problem is in the memory, here are some relevant parts of my code:
This is my entry point. Maybe el1_entry is not good?
#include "mm.h"
#include "arm/sysreg.h"
.section ".text.boot"
.globl _start
_start:
mrs x0, mpidr_el1 // Get info about the CPU from reg mpidr_el1
and x0, x0, #0xFF // Extract the ID of the CPU
cmp x0, #0 // Comopare the id of the CPU core with 0
beq master // If the core's id == 0, branch to mater
b proc_hang // If the core' id != 0, branch to hang
master:
// Disable the MMU
ldr x0, =SCTLR_VALUE_MMU_DISABLED
msr sctlr_el1, x0
// EL1 will execute at Aarch64
ldr x0, =HCR_VALUE
msr hcr_el2, x0
// EL1 will execute at Aarch64; and EL0 and 1 will be "non secure"
ldr x0, =SCR_VALUE
msr scr_el3, x0
// Configure EL1 to use its own stack and disable interrupts when EL1
ldr x0, =SPSR_VALUE
msr spsr_el3, x0
// Jump to el1_entry
adr x0, el1_entry
msr elr_el3, x0
eret
el1_entry:
/* Clean memory from addresses bss_begin to bss_end */
adr x0, bss_begin
ldr x1, =bss_end
sub x1, x1, x0
bl memzero // Call function to clean memory
mov sp, #LOW_MEMORY // Initialize stack pointer
bl kernel_main // Transfer control to kernel_main function
b proc_hang
proc_hang:
b proc_hang
Vector table, Saving & Restoring states in between interrupts. Maybe something is wrong with the saving & restoring?
#include "entry.h"
/* Macro to save EL1 state when an exception happens */
.macro kernel_entry
sub sp, sp, #S_FRAME_SIZE
stp x0, x1, [sp, #16 * 0]
stp x2, x3, [sp, #16 * 1]
stp x4, x5, [sp, #16 * 2]
stp x6, x7, [sp, #16 * 3]
stp x8, x9, [sp, #16 * 4]
stp x10, x11, [sp, #16 * 5]
stp x12, x13, [sp, #16 * 6]
stp x14, x15, [sp, #16 * 7]
stp x16, x17, [sp, #16 * 8]
stp x18, x19, [sp, #16 * 9]
stp x20, x21, [sp, #16 * 10]
stp x22, x23, [sp, #16 * 11]
stp x24, x25, [sp, #16 * 12]
stp x26, x27, [sp, #16 * 13]
stp x28, x29, [sp, #16 * 14]
mrs x22, elr_el1
mrs x23, spsr_el1
stp x30, x22, [sp, #16 * 15]
str x23, [sp, #16 * 16]
.endm
/* Macro to restore EL1 state and return from the exception handling */
.macro kernel_exit
ldr x23, [sp, #16 * 16]
ldp x30, x22, [sp, #16 * 15]
msr elr_el1, x22
msr spsr_el1, x23
ldp x0, x1, [sp, #16 * 0]
ldp x2, x3, [sp, #16 * 1]
ldp x4, x5, [sp, #16 * 2]
ldp x6, x7, [sp, #16 * 3]
ldp x8, x9, [sp, #16 * 4]
ldp x10, x11, [sp, #16 * 5]
ldp x12, x13, [sp, #16 * 6]
ldp x14, x15, [sp, #16 * 7]
ldp x16, x17, [sp, #16 * 8]
ldp x18, x19, [sp, #16 * 9]
ldp x20, x21, [sp, #16 * 10]
ldp x22, x23, [sp, #16 * 11]
ldp x24, x25, [sp, #16 * 12]
ldp x26, x27, [sp, #16 * 13]
ldp x28, x29, [sp, #16 * 14]
add sp, sp, #S_FRAME_SIZE
eret
.endm
/*
* Exception vectors table is initialized in this file..., but I'm not including the code in this post.
*/
...
// IRQ Handler
el1_irq:
kernel_entry
bl handle_irq
kernel_exit
handle_irq
...
void handle_irq(void) {
u32 irq;
irq = REGS_IRQ->irq0_pending_0;
while(irq) {
if(irq & SYS_TIMER_IRQ_1) {
irq &= ~SYS_TIMER_IRQ_1;
handle_timer_1();
}
}
}
handle_timer_1
...
void handle_timer_1(void)
{
// Set the next timer interrupt
currrent_value_1 += interval_1;
REGS_TIMER->compare[1] = currrent_value_1;
REGS_TIMER->control_status |= SYS_TIMER_IRQ_1;
timer_tick();
}
timer_tick() (where the unexpected behavior is observed)
...
int var = 1;
int *p_var = &(var); // Current task being executed
void timer_tick(void)
{
char buff[] = "0000000000000000";
parse_int(*p_var, buff, 16);
uart_send_string("*p_var: ");
uart_send_string(buff);
uart_send_string("\n");
parse_int(var, buff, 16);
uart_send_string("var: ");
uart_send_string(buff);
uart_send_string("\n");
if(p_var == &var) {
uart_send_string("equal: true");
} else {
uart_send_string("equal: false");
}
}
A "minimal example" is somewhat extensive, so I can't post directly here. I put it on github (I'm linking to the entry point)
if(p_var == &var)
is nonsensical code, any decent optimizer will evaluate that to always true and then remove the whole if-else and replace it withuart_send_string("equal: true");
. In case the real code is*p_var == var
then it's another story. Also, if you failed tovolatile
qualify variables shared with an ISR, then that's another bug and not related to memory. – Lundin