Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/flash/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
ARM程序集内联C互斥执行_C_Assembly_Arm_Mutex_Xilinx - Fatal编程技术网

ARM程序集内联C互斥执行

ARM程序集内联C互斥执行,c,assembly,arm,mutex,xilinx,C,Assembly,Arm,Mutex,Xilinx,我正在使用Xilinx Zedboard进行一个嵌入式系统项目。该板能够不对称地拆分其双核ARM A9处理器,以同时运行两个独立的程序。我已经将主板配置为在一个内核上运行Linux,在另一个内核上运行裸机应用程序,作为硬件控制器。对于处理器间通信,我使用两个处理器之间共享的片上内存。我正在努力实现我的锁,我很好奇是否有人经历过这样的事情,或者是否有人能为我指明正确的方向 我在ARM参考网站上找到了一个互斥实现,并将其改编为C内联汇编。测试后,锁定功能似乎挂起,我不知道为什么。我在组装方面的经验有

我正在使用Xilinx Zedboard进行一个嵌入式系统项目。该板能够不对称地拆分其双核ARM A9处理器,以同时运行两个独立的程序。我已经将主板配置为在一个内核上运行Linux,在另一个内核上运行裸机应用程序,作为硬件控制器。对于处理器间通信,我使用两个处理器之间共享的片上内存。我正在努力实现我的锁,我很好奇是否有人经历过这样的事情,或者是否有人能为我指明正确的方向

我在ARM参考网站上找到了一个互斥实现,并将其改编为C内联汇编。测试后,锁定功能似乎挂起,我不知道为什么。我在组装方面的经验有点有限,我在学校见过它,了解高级概念,但我完全迷失在低级实现中

这看起来是正确的还是正确的方法?我所需要的只是一个简单的机制,它允许我在进程间通信结构(几个消息队列)上执行原子操作

mutex.h

#ifndef __OCM_MUTEX_H__
#define __OCM_MUTEX_H__

#include <stdint.h>

#define LOCKED      1
#define UNLOCKED    0

typedef uint32_t mutex_t;

extern void ocm_lock_mutex(volatile mutex_t* mutex);
extern void ocm_unlock_mutex(volatile mutex_t* mutex);

#endif

为什么不使用GNU汇编?应该是这样的

.equ locked,1
.equ unlocked,0

@ lock_mutex
@ Declare for use from C as extern void lock_mutex(void * mutex);
    .global lock_mutex
lock_mutex:
    LDR     r1, =locked
1:  LDREX   r2, [r0]
    CMP     r2, r1        @ Test if mutex is locked or unlocked
    BEQ     2f            @ If locked - wait for it to be released, from 2
    STREXNE r2, r1, [r0]  @ Not locked, attempt to lock it
    CMPNE   r2, #1        @ Check if Store-Exclusive failed
    BEQ     1b            @ Failed - retry from 1
    # Lock acquired
    DMB                   @ Required before accessing protected resource
    BX      lr

2:  @ Take appropriate action while waiting for mutex to become unlocked
    @ WAIT_FOR_UPDATE
    B       1b            @ Retry from 1


@ unlock_mutex
@ Declare for use from C as extern void unlock_mutex(void * mutex);
    .global unlock_mutex
unlock_mutex:
    LDR     r1, =unlocked
    DMB                   @ Required before releasing protected resource
    STR     r1, [r0]      @ Unlock mutex
    @ SIGNAL_UPDATE   
    BX      lr
$ arm-linux-gnueabihf-objdump -d mutex.o

mutex.o:     file format elf32-littlearm


Disassembly of section .text:

00000000 <lock_mutex>:
   0:   e3a01001    mov r1, #1
   4:   e1902f9f    ldrex   r2, [r0]
   8:   e1520001    cmp r2, r1
   c:   0a000004    beq 24 <lock_mutex+0x24>
  10:   11802f91    strexne r2, r1, [r0]
  14:   13520001    cmpne   r2, #1
  18:   0afffff9    beq 4 <lock_mutex+0x4>
  1c:   f57ff05f    dmb sy
  20:   e12fff1e    bx  lr
  24:   eafffff6    b   4 <lock_mutex+0x4>

00000028 <unlock_mutex>:
  28:   e3a01000    mov r1, #0
  2c:   f57ff05f    dmb sy
  30:   e5801000    str r1, [r0]
  34:   e12fff1e    bx  lr
然后它的垃圾堆看起来像这样

.equ locked,1
.equ unlocked,0

@ lock_mutex
@ Declare for use from C as extern void lock_mutex(void * mutex);
    .global lock_mutex
lock_mutex:
    LDR     r1, =locked
1:  LDREX   r2, [r0]
    CMP     r2, r1        @ Test if mutex is locked or unlocked
    BEQ     2f            @ If locked - wait for it to be released, from 2
    STREXNE r2, r1, [r0]  @ Not locked, attempt to lock it
    CMPNE   r2, #1        @ Check if Store-Exclusive failed
    BEQ     1b            @ Failed - retry from 1
    # Lock acquired
    DMB                   @ Required before accessing protected resource
    BX      lr

2:  @ Take appropriate action while waiting for mutex to become unlocked
    @ WAIT_FOR_UPDATE
    B       1b            @ Retry from 1


@ unlock_mutex
@ Declare for use from C as extern void unlock_mutex(void * mutex);
    .global unlock_mutex
unlock_mutex:
    LDR     r1, =unlocked
    DMB                   @ Required before releasing protected resource
    STR     r1, [r0]      @ Unlock mutex
    @ SIGNAL_UPDATE   
    BX      lr
$ arm-linux-gnueabihf-objdump -d mutex.o

mutex.o:     file format elf32-littlearm


Disassembly of section .text:

00000000 <lock_mutex>:
   0:   e3a01001    mov r1, #1
   4:   e1902f9f    ldrex   r2, [r0]
   8:   e1520001    cmp r2, r1
   c:   0a000004    beq 24 <lock_mutex+0x24>
  10:   11802f91    strexne r2, r1, [r0]
  14:   13520001    cmpne   r2, #1
  18:   0afffff9    beq 4 <lock_mutex+0x4>
  1c:   f57ff05f    dmb sy
  20:   e12fff1e    bx  lr
  24:   eafffff6    b   4 <lock_mutex+0x4>

00000028 <unlock_mutex>:
  28:   e3a01000    mov r1, #0
  2c:   f57ff05f    dmb sy
  30:   e5801000    str r1, [r0]
  34:   e12fff1e    bx  lr
$armlinux gnueabihf objdump-d mutex.o
mutex.o:文件格式elf32 littlearm
第节的分解。正文:
00000000 :
0:e3a01001 mov r1,#1
4:e1902f9f ldrex r2[r0]
8:e1520001凸轮轴位置r2,r1
c:0a000004 beq 24
10:11802f91 strexne r2,r1[r0]
14:13520001 cmpne r2,#1
18:0AFFFF9第4季度
1c:f57ff05f dmb sy
20:E12FF1E bx lr
24:eafffff6 b 4
00000028 :
28:e3a01000 mov r1,#0
2c:f57ff05f dmb sy
30:e5801000 str r1[r0]
34:E12FF1E bx lr

然而,我想知道的是,您是否成功地将两个核心配置为包含在核心一致性中。据我所知,您可以指定哪些内核参与ldrex/strex操作。

至于代码挂起的原因,可能是因为WFE指令。 如果没有事件发生,它将一事无成。永远。 事先检查事件是否已启用和生成

(同时,检查ARM体系结构参考手册中STREX和LDREX的使用限制,该手册应在第A2.9.4节“使用限制”中)

下面是一个关于如何在上实现旋转锁定的示例:

将他们的示例应用到您的代码中会产生如下结果:

__asm__ __volatile__("@ocm_lock_mutex\n"
"   LDREX   %[r2], [%[r0]]\n"
"   CMP     %[r2], %[locked]\n"
"   STREXNE %[r2], %[locked], [%[r0]]\n"
"   CMPNE   %[r2], #1\n"
"   BEQ     ocm_lock_mutex\n"
    : [r2] "=r" (result), [r0] "=r" (mutex)
    : [locked] "r" (locked));
这将在忙等待时实现互斥

如果您想让代码告诉您是否在没有繁忙等待的情况下获取了互斥,只需修改结尾:

__asm__ __volatile__("@ocm_lock_mutex\n"
[...]
"   CMPNE   %[r2], #1\n"
"   BEQ     ocm_lock_mutex_end\n"
"   MOV    %[r2], #2\n"
"@ocm_lock_mutex_end\n"
"   NOP\n"
    : [r2] "=r" (result), [r0] "=r" (mutex)
    : [locked] "r" (locked));
只需签入C:

if (result==0) {/*You didn't get the mutex, it was locked*/}
else if (result==1) {/*You didn't get the mutex, access not exclusive*/}
else if (result==2) {/*You got the mutex!*/}
(如ARM架构参考手册2005版A2.9.4“加载和存储操作”所示)

在C中构造外部“忙等待”循环是完全合理的。 或者,如果您想要一个基于中断的方案,从那里挂起操作

经验法则:

  • 使内联汇编代码尽可能小,无循环

  • 使内联程序集一次只做一件事


你知道为什么Linux在调用lock and unlock时会出现分段错误吗?@Wade我想我在r1中加载了错误的东西。我应该加载一个地址而不是常量。我会尽快修复的。@Wade忽略我之前的评论,我不认为这在这个意义上是错误的,目前我看不出我的组装建议有什么问题。您是否使用一个参数调用lock_mutex/unlock_mutex,该参数是单词的有效地址。像
无符号整数输出\u mutex=unlocked;锁定\u互斥体(&输出\u互斥体)如您提供的链接中的示例所示?分段错误是我方疏忽的结果。我正在正确传递指针,但指针超出范围。谢谢你的帮助,这个问题我已经解决了很久了。我现在对手臂装配有点了解了。干杯我传递的指针特定于片上内存,而不是Linux映射内存。