riverajl
Posts: 10
Joined: Thu Dec 06, 2018 10:03 am

Using ldrex instruction hangs

Thu Dec 06, 2018 10:28 am

Hi forum guys.

I am writing first my bare metal sw in a RPI 3B and trying to build a lock mechanism between cores using ldrex and strex instructions.

It's a simple thing only to begin. I have a issue that the ldrex instruction hangs. I don't know if it's necessary more configuration, but my code is here:
config.txt:

Code: Select all

kernel_old=1
disable_commandline_tags=1
disable_overscan=1
framebuffer_swap=0
start:

Code: Select all

.section ".text.startup"

.equ CPU_STACK_SIZE,0x4000
.equ IRQ_STACK_SIZE,0x4000

.equ CPU_STACK_CORE0,0x3f000000
.equ CPU_STACK_CORE1,0x3f000000-CPU_STACK_SIZE
.equ CPU_STACK_CORE2,0x3f000000-CPU_STACK_SIZE*2
.equ CPU_STACK_CORE3,0x3f000000-CPU_STACK_SIZE*3

.equ IRQ_STACK_CORE0,0x3f000000-CPU_STACK_SIZE*4
.equ IRQ_STACK_CORE1,0x3f000000-CPU_STACK_SIZE*4-IRQ_STACK_SIZE
.equ IRQ_STACK_CORE2,0x3f000000-CPU_STACK_SIZE*4-IRQ_STACK_SIZE*2
.equ IRQ_STACK_CORE3,0x3f000000-CPU_STACK_SIZE*4-IRQ_STACK_SIZE*3


.equ    CPSR_MODE_USER,         0x10
.equ    CPSR_MODE_FIQ,          0x11
.equ    CPSR_MODE_IRQ,          0x12
.equ    CPSR_MODE_SVR,          0x13
.equ    CPSR_MODE_ABORT,        0x17
.equ    CPSR_MODE_HYP,		    0x1A
.equ    CPSR_MODE_UNDEFINED,    0x1B
.equ    CPSR_MODE_SYSTEM,       0x1F

.equ    CPSR_IRQ_INHIBIT,       0x80
.equ    CPSR_FIQ_INHIBIT,       0x40
.equ    CPSR_THUMB,             0x20



.global _start
_start:
ldr pc, _reset_h
ldr pc, _undefined_instruction_vector_h
ldr pc, _software_interrupt_vector_h
ldr pc, _prefetch_abort_vector_h
ldr pc, _data_abort_vector_h
ldr pc, _unused_handler_h
ldr pc, _interrupt_vector_h
ldr pc, _fast_interrupt_vector_h

_reset_h:                           .word   _reset_
_undefined_instruction_vector_h:    .word   undefined_instruction_vector
_software_interrupt_vector_h:       .word   software_interrupt_vector
_prefetch_abort_vector_h:           .word   prefetch_abort_vector
_data_abort_vector_h:               .word   data_abort_vector
_unused_handler_h:                  .word   _reset_
_interrupt_vector_h:                .word   interrupt_vector
_fast_interrupt_vector_h:           .word   fast_interrupt_vector

_reset_:
mrc     p15, 0, r0, c0, c0, 5
ubfx    r0, r0, #0, #2
cmp     r0, #0					@ is it core 0?
beq     core0
cmp     r0, #1					@ is it core 1?
beq     core1
cmp     r0, #2					@ is it core 2?
beq     core2
cmp     r0, #3					@ is it core 3?
beq     core3
@ CPU ID is not 0..3 -
b hang
hang: b hang

core0:
ldr sp,=CPU_STACK_CORE0

mov r0, #(CPSR_MODE_IRQ | CPSR_IRQ_INHIBIT | CPSR_FIQ_INHIBIT )
msr cpsr_c,r0
ldr sp,=IRQ_STACK_CORE0

mov r0, #(CPSR_MODE_SVR | CPSR_IRQ_INHIBIT | CPSR_FIQ_INHIBIT )
msr cpsr_c,r0

bl _cstartup

halt:
wfe		// wait for event
b halt

core1:
ldr sp,=CPU_STACK_CORE1

mov r0, #(CPSR_MODE_IRQ | CPSR_IRQ_INHIBIT | CPSR_FIQ_INHIBIT )
msr cpsr_c,r0
ldr sp,=IRQ_STACK_CORE1

mov r0, #(CPSR_MODE_SVR | CPSR_IRQ_INHIBIT | CPSR_FIQ_INHIBIT )
msr cpsr_c,r0

wfe		
bl core1_main
b halt


core2:
ldr sp,=CPU_STACK_CORE2

mov r0, #(CPSR_MODE_IRQ | CPSR_IRQ_INHIBIT | CPSR_FIQ_INHIBIT )
msr cpsr_c,r0
ldr sp,=IRQ_STACK_CORE2

mov r0, #(CPSR_MODE_SVR | CPSR_IRQ_INHIBIT | CPSR_FIQ_INHIBIT )
msr cpsr_c,r0

wfe	
bl core2_main
b halt

core3:
ldr sp,=CPU_STACK_CORE3

mov r0, #(CPSR_MODE_IRQ | CPSR_IRQ_INHIBIT | CPSR_FIQ_INHIBIT )
msr cpsr_c,r0
ldr sp,=IRQ_STACK_CORE3

mov r0, #(CPSR_MODE_SVR | CPSR_IRQ_INHIBIT | CPSR_FIQ_INHIBIT )
msr cpsr_c,r0

wfe	
bl core1_main
b halt

locks

Code: Select all

.global LDEX32
LDEX32:
ldrex r1,[r0]
mov r0,r1
bx lr

.global STEX32
STEX32:
strex r2,r1,[r0]
mov r0,r2
bx lr


.global BARRIER
BARRIER:
dmb sy
bx lr

.global LOCK
LOCK:
// r0 -> address
1:
ldrex r1,[r0]		// HANGS HERE !!!!
cmp r1,#0
bne 1b
mov r1,#1
2:
strex r2,r1,[r0]
cmp r2,#0
bne 2b
dmb sy
bx lr

.global UNLOCK
UNLOCK:
// r0 -> address
dmb sy
mov r1,#0
str r1,[r0]
bx lr
test

Code: Select all


...
volatile uint32_t __semaf_leds;
...

	LOCK(&__semaf_leds);	// here it hangs at ldrex instruction
	UNLOCK(&__semaf_leds);
	LOCK(&__semaf_leds);
	UNLOCK(&__semaf_leds);
	LOCK(&__semaf_leds);
	UNLOCK(&__semaf_leds);
	LOCK(&__semaf_leds);
	UNLOCK(&__semaf_leds);
	LOCK(&__semaf_leds);
	UNLOCK(&__semaf_leds);
	LOCK(&__semaf_leds);
	UNLOCK(&__semaf_leds);

Can anyone tell if it's something to do to enable ldrex instruction?

Thanks a lot in advance.

José Luiz

User avatar
Paeryn
Posts: 2373
Joined: Wed Nov 23, 2011 1:10 am
Location: Sheffield, England

Re: Using ldrex instruction hangs

Thu Dec 06, 2018 11:51 am

I think you need to have the MMU on and the address used for the lock needs to be in a section of memory marked as Normal. Without the MMU on all memory is effectively marked as Strongly Ordered.
She who travels light — forgot something.

timanu90
Posts: 64
Joined: Sat Dec 24, 2016 11:54 am

Re: Using ldrex instruction hangs

Wed Dec 12, 2018 3:11 pm

I think you need to have the MMU on and the address used for the lock needs to be in a section of memory marked as Normal. Without the MMU on all memory is effectively marked as Strongly Ordered.
The previous answer plus the caches need to be enabled and the memory marked as normal, shareable and global.

Hope it helps

Tiago

Return to “Bare metal, Assembly language”