0
votes

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)

1
Please use the tags to specify an architecture and post a minimal reproducible example. Otherwise, we cannot even guess what's going on.Margaret Bloom
SO is moderated by human users; it doesn't have an AI that instantly recognizes and reopens questions when you've added details. You have to wait for a few users to vote to reopen. However, it's not very minimal of a minimal reproducible example, and you've only shown code, not anything you found with GDB checking the value at run-time or setting a watch-point. The point of making a MCVE is to strip your program down until it's as small as possible while reproducing the error. (And typically not still doing anything else useful: ericlippert.com/2014/03/05/how-to-debug-small-programs)Peter Cordes
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 with uart_send_string("equal: true");. In case the real code is *p_var == var then it's another story. Also, if you failed to volatile qualify variables shared with an ISR, then that's another bug and not related to memory.Lundin
Allocating buffers on the stack inside an ISR is a very bad idea. And so on. I don't think there is one isolated problem here, but multiple ones.Lundin

1 Answers

0
votes

Am I messing up with memory elsewhere without realizing?

Yes.