Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Acquiring spinlock in ZYNQ 7000 loops forever #309

Open
f-zl opened this issue Aug 31, 2024 · 2 comments
Open

Acquiring spinlock in ZYNQ 7000 loops forever #309

f-zl opened this issue Aug 31, 2024 · 2 comments
Assignees

Comments

@f-zl
Copy link

f-zl commented Aug 31, 2024

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
@arnopo
Copy link
Contributor

arnopo commented Sep 4, 2024

@tnmysh : Do you have any idea what the issue might be?

@tnmysh
Copy link
Collaborator

tnmysh commented Sep 4, 2024

@arnopo zynq7000 use and development is not active for long time. So, I am not sure. I think libmetla support will be deprecated on zynq7000 platform, so I am not sure if I will get chance to debug this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants
@arnopo @f-zl @tnmysh and others