Skip to content

Acquiring spinlock in ZYNQ 7000 loops forever #309

Description

@f-zl

I'm using ZYNQ 7000 and want to use spinlock to synchronize the two cores (baremetal). The problem is metal_spinlock_acquire loops forever.

The code of core0's main.c:

// some includes

#define SHARED_MEM_BASE_ADDR // an address of DDR or OCM unused by both cores' linkers, like 0x30000000 or 0xffff0000
typedef struct {
  struct some_struct variable;
  struct metal_spinlock lock;
} SharedMem;
#define SHARED_MEM ((volatile SharedMem *)SHARED_MEM_BASE_ADDR)

void protected_read(struct some_struct *s) {
  metal_spinlock_acquire(&SHARED_MEM->lock);
  *s = SHARED_MEM->variable;
  metal_spinlock_release(&SHARED_MEM->lock);
}
int main() {
  init_system(); 
  metal_spinlock_init(&SHARED_MEM->lock);
  wake_up_core1();
  struct some_struct s;
  for(;;) {
    protected_read(&s);
    // process data
    // core1 is supposed to read and write to variable with lock too
  }
}

metal_spinlock_acquire compiles to this:

 0:   e3a02001        mov     r2, #1 ; r2 = 1
 4:   f57ff05b        dmb     ish ; data memory barrier
 8:   e1d03f9f        ldrexb  r3, [r0] ; r3 = *r0, r0's type is struct metal_spinlock *, aka atomic_flag *
 c:   e1c01f92        strexb  r1, r2, [r0] ; *r0 = r2 = 1, save status in r1
10:   e3510000        cmp     r1, #0 ; exclusive store succeed?
14:   1afffffb        bne     8 <metal_spinlock_acquire+0x8> ; if not succeed, try again
18:   e31300ff        tst     r3, #255 ; any bit set in r3? was the lock held by others?
1c:   f57ff05b        dmb     ish
20:   1afffff7        bne     4 <metal_spinlock_acquire+0x4> ; if lock was held by others, try again
24:   e12fff1e        bx      lr

In metal_spinlock_acquire, strexb always fails, so it loops forever, even when core1 is halted by a debugger and never accesses the lock.

I find this link that says ZYNQ 7000 doesn't support exclusive access of OCM. But the behavior is still the same if SHARED_MEM_BASE_ADDR is a DDR address. How to make spinlock work on ZYNQ 7000?

P.S.:

  1. Xil_SetTlbAttributes(SHARED_MEM_BASE_ADDR, 0x14de2) is called in both cores' init function as in xapp1079, to mark the address as sharable
  2. -DUSE_AMP=1 is added in core1's bsp

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions