简体   繁体   中英

Why are my pointers changing? (bare metal)

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)

Am I messing up with memory elsewhere without realizing?

Yes.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM