This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] AM6442:使用__xin __XOUT 访问 HW SPINLOCK

Guru**** 2873850 points

Other Parts Discussed in Thread: AM6442

请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1626049/am6442-pru-accessing-hw-spinlocks-with-__xin-__xout

器件型号: AM6442

您好:

我尝试访问(AM6442 的)PRU_ICSSG SPINLOCK 以保护在 PRU 0 和 PRU1 之间共享的关键路径。

我现在使用的代码是:

#define SPINLOCK_DEV 0x90 /* PRU XFR Device für spinlocks */ 
#define BASE_REGISTER 1
#define USE_REmapping 0

静态内联 void spinlock_acquire (uint8_t lock_id){
uint32_t obj = lock_id 和 0x3FU;
执行{
__xin (SPINLOCK_DEV、BASE_REGISTER、USE_REmapping、OBJ);
//结果位在 R1.B3 中
if (((obj >> 24)& 0x01)== 1){
//已获取
返回;
}
//未获取
} while (1);
}

静态内联 void spinlock_release (uint8_t lock_id){
uint32_t obj =(lock_id 和 0x3F)<< 24;//为什么要在此处移位????
__XOUT (SPINLOCK_DEV、BASE_REGISTER、USE_REmapping、OBJ);
}

这个问题在代码中被读了出来:我不知道,为什么我需要转移来释放锁。 如果我不换班、就不起作用。 也许我只是误解了 TRM 中的表 6-98 (p632)、但评论指出:“此断言将清除由选择的标志 R1.b0 /own_req_vector“。

另外、我发现很难找到该主题的 (C -) 示例代码。

 

感谢您的帮助!

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    我 在 open-PRU/academy·问题#120·TexasInstruments/open-PRU 中创建了汇编/C 的创建硬件 spinlock 使用示例、并添加了基于汇编的示例。
    摘要

    • r1.b0 应保存 spinlock ID(由固件定义,可在 0 到 63 范围内选择)、这是输入 spinlock HW 小工具、可监测 r1.b0(低 6 位)以选择 spinlock 实例
    • XIN 和 XOUT 应使用 R1.B3 获取和释放(这说明了示例工作需要修改的原因)
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    感谢您的快速回复和示例代码。

    我的问题是了解 uint32_t 到 R1.BX 映射。 我假设是这样
    uint32_t val << 0 = b0、val << 8 = b1、val << 16 = b2 和 val << 24 = b3。

    我的代码和您的代码通过将锁 ID 写入 b0 来获取 spinlock。 状态在 (val << 24)= B3 中返回。 我可以看到使用我的代码、尽管我在 TRM 中找不到器件、但其中指出:您必须将 lock_id 写入 b0。 我发现:“这一仲裁的结果被返回
    R1.B3[0]“、有效->结果可通过 val << 24 (=B3) 找到

    要释放锁定、我无法将 lock_id 写入 b0、因为这不起作用。 相反、我将 lock_id 写入任何其他字节 b1、b2 或 b3。 是有效的。 I shift(至少)<< 8。

    但 TRM 显示:“此置为有效将清除 R1.b0 选择的标志“、这意味着:
    uint32_t value =(lock_id 和 0x3F);  // <-未发生移位-> b0(如示例代码中所示)
    __XOUT(SPINLOCK_DEV、SPINLOCK_BASE_REGISTER、SPINLOCK_USE_REmapping,值);

    我测试了很长时间 — 它不起作用。

    因此、要么假设 uint32_t 值中的哪个字节会变为寄存器中的哪个字节不同(至少对于发布操作)、要么假设文档不同(或者我对这些内容的工作方式有一个完全错误的看法)。

    您说:“ XIN 和 XOUT 应使用 R1.B3 获取和释放“、但在您的获取示例中、您写入 b0:
    R1.b0 = SPINLOCK_ID

    提示:“必须在 M_SPINLOCK_ACQUIVE 之后调用“。 这从何而来? 我的应用程序在启动时将所有锁作为初始状态发布 — 我以前没有检查,如果设置了,我没有发现任何问题...

    再次感谢

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好 Stefan、

    我正在与 Pratheesh 核实有关在 M_SPINLOCK_QUADE 之后调用 M_SPINLOCK_RELEASE 的注释。

    要确认:普拉泰什的代码是否适用于您?  

    我需要对硬件设计进行更多深入研究、以解读 TRM 中的信息、并可能修复一些措辞。 但是、如果 Pratheesh 的代码有效、这对我们来说是一个很好的起点。

    对于未来的读者、您可以在此处查看完整的解释:
    https://github.com/TexasInstruments/open-pru/issues/120

    但代码摘要是

    ; first, acquire the spinlock
    M_SPINLOCK_ACQUIRE .macro
    
    ; do NOT need to XOUT to R1.b0, just set R1.b0
    LDI R1.b0, SPINLOCK_ID ; can range from 0-63, fixed in PRU firmware
    
    ; XIN to request ownership of spinlock
    ; 0 means did not get ownership, so loop
    $1:
    XIN INT_SPIN_XID, &R1.b3, 1
    QBBC $1, R1.b3, 0
    .endm
    
    ; later, release the spinlock with XOUT
    M_SPINLOCK_RELEASE .macro
    XOUT INT_SPIN_XID, &R1.b3, 1
    .endm

    关于 register.byte 表示法

    是的、寄存器符号为[R1.B3][R1.B2][R1.B1][R1.b0]。 有关更多信息、请参阅 OpenPRU 汇编指令速查表:
    https://github.com/TexasInstruments/open-pru/blob/main/docs/PRU%20Assembly%20Instruction%20Cheat%20Sheet.md

    关于 SPINLOCK 的 TRM 章节呢?  

    我也不理解 TRM 文档。 我将研究硬件正在执行的确切操作、并提交错误以更新“TRM"一“一章。

    到目前为止尚未解决的问题:

    1) 在表中、内部/外部、内部/外部 0(宽边 ID 0x91 - PRU 内核是否也可以调用此功能?)的含义是什么? /外部 1(宽边 ID 0x92,同一问题)

    2) 如何使用 R1.b0? 写信给它,否则不要触摸它? XOUT R1.b0 来执行某些操作? 如果是这样, XOUT 会完成什么,因为 Spinlock 已经窥探了它?

    3) 什么是“引起仲裁行动“/固定仲裁的意思? 这与“仲裁事件“有何关系?

    4) 释放旋锁(清除),您应该 XOUT R1.B3 还是 R1.b0 ?

    5) 确认:PRU 内核应与宽边接口交互、PRU 子系统之外的内容应通过 ICSSG_SPIN_LOCK0 / ICSSG_SPIN_LOCK1 寄存器进行交互? 其他 PRU 子系统是使用备用宽边 ID 还是对寄存器进行读取/写入?

    此致、

    Nick

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Nick、

    我已经检查了 Pratheesh asm 代码、可以确认它有效。

    我编写了一个小型测试程序、将汇编器函数与 C 函数进行比较:

    汇编器部分为 Pratheesh 代码:

        .global spinlock_acquire
    spinlock_acquire:
        MOV    R1.b0, R14.b0
    $1:
        XIN INT_SPIN_XID, &R1.b3, 1
        QBBC $1, R1.b3, 0
        JMP    R3.w2
    
        .global spinlock_release
    spinlock_release:
        MOV    R1.b0, R14.b0
        XOUT INT_SPIN_XID, &R1.b3, 1
        JMP    R3.w2

    和 C 部分:

    (很抱歉放置图片-代码插入不起作用)

    这是我观察到的情况:

    在以下情况下运行 C 版本可以正常工作:
    *您在代码中的重要行执行任何 (8、16 或 24) 移位操作
    *您没有优化(例如-O2)

    如果使用 O2 进行编译、即使最初调用 spinlock_release(后跟延迟)、两个内核也无法获取 LOCK(仅每个内核的 DEBUG_PIN_SHIFT_C 切换)。

    如果不在重要线路上执行移位操作、则只有一个内核获取(并释放)LOCK(打开和关闭 DEBUG_PIN_SHIFT_B)、并且永远不会等待它(永远不会切换其 DEBUG_PIN_SHIFT_C)。 另一个内核无法获取锁并持续等待(切换其 DEBUG_PIN_SHIFT_C)。

    此致、

    Stefan

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好 Stefan、

    感谢您迄今为止的调试。 希望在我们两个人之间、我们可以找出预期的行为。

    您的测试的后续

    我能否让您在 C 语言中检查不同测试代码生成的汇编代码? 这可能有助于我们了解您为何在不同的优化设置下看到不同的行为。

    我能想到的一个潜在问题是 r1.b0 值被 spinlock 窥探、而不管 XIN/XOUT 如何(据我们所知)。 但我认为 C 编译器通常不会跟踪寄存器编号 — 我不记得是否可以像您定义的 R30 那样定义 R1、然后希望 C 将该寄存器值单独保留。 可能 C 编译器会向该寄存器位字段写入不同的值、从而混淆 spinlock 命令。

    有关组合 C 语言和汇编语言的更多资源、请参阅 PRU 入门实验、网址为:
    https://dev.ti.com/tirex/explore/node?isTheia=false&node=A__AfG7HXFogfKtAWtxs36Cag__AM64-ACADEMY__WI1KRXP__LATEST 

    有关如何保留生成的汇编代码的指导、请参阅 PRU 入门实验>实验 3:编译。

    如果使用 CCS:Advanced Options > Assembler 选项
    https://dev.ti.com/tirex/explore/node?isTheia=false&node=A__AUR8lo3Cik3JV1avCUKaGw__AM64-ACADEMY__WI1KRXP__LATEST

    如果使用 makefile:C 编译器设置
    https://dev.ti.com/tirex/explore/node?isTheia=false&node=A__ARYD7uMfUFtdM7yNuJ9Tlg__AM64-ACADEMY__WI1KRXP__LATEST

    查看源文件进行更新  

    还在这里挖掘一切。 在 TRM 表中、您可以忽略“External0/External1"条“条目。

    每个 PRU_ICSSG 有 1 个 spinlock 实例。 如“内部“所示、当您访问自己 PRU 子系统中的 SPINLOCK 时、“External0/External1"可能“可能是指允许一个 PRU_ICSSG 实例中的 PRU 内核使用宽边接口快速访问另一个 PRU_ICSSG 实例中的 SPINLOCK 的直接连接。 似乎这部分文档是从 AM65x 复制/粘贴的、AM65x 具有 3 个 PRU_ICSSG 实例(因此有 2 个“外部“ spinlock 实例)。 AM64x 只有 2 个 PRU_ICSSG 实例、因此我不希望这两个实例都适用... 不过我仍在跟踪信号。

    此致、

    Nick

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    其他更新:最重要的是保留 r1.b0 的值  

    好吧、从源代码看、实际上并不像 spinlock 使用任何数据、而是要与 spinlock 实例交互的数据、该实例存储在 R1.b0 中。 因此、无论您做什么、都只保留该数据字节。

    目前、我只研究了 PRU 内核访问其自身 PRU 子系统中 spinlock 的用例。 还需要了解信号如何在不同 PRU 子系统之间连接。

    请求旋锁的步骤  

    1) 在 r1.b0 中设置 spinlock 实例的值

    2) 对 0x90 执行 XIN。 您需要为命令提供存储请求结果的位置(成功/失败)。 因此、您可以按照上面的说明对 R1.B3 执行 Xin 操作、但我希望这可以与 R1.B1、R2.B3 等任意组合一起使用

    3) 检查返回值,确认是否实际获得了旋锁

    松开旋锁的步骤  

    1)  在 r1.b0 中设置 spinlock 实例的值(或只是确保该值未被修改)

    2) 执行 XOUT 到 0x90。 spinlock 实际上并不使用来自 XOUT 的任何数据、因此使用 R1.B3、R1.B1 等并不重要、而且该数据字节中的值无关紧要。

    未决问题  

    PRU 子系统之间的连接是什么样子的?
    - AM64x 上甚至有 0x91 或 0x92 连接吗? 如果是、则 连接了哪一个?
    -连接了哪些 PRU 内核? 所有 6 个内核? 一次 4 个内核、您需要在哪里切换一个位以在 PRU 内核或 TX_PRU 内核之间进行选择?
    -如果只有 4 个信号从 ICSSGm 0x91/92 输出,但有 6 个输入信号进入 ICSSGn 0x91/92 ,所有这些信号是否真的活跃?  

    如果您使用宽度大于 1 字节的 XIN 或 XOUT、会发生什么情况? 例如、是否为所有宽度填充 XIN 零、或者不会覆盖较高的位?

    此致、

    Nick

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    嗨、Nick、

    下面是要 diff 的 asm 文件(--keep_asm 的输出)。 一个带 O2、另一个没有启用优化。

    感谢您的检查!

    e2e.ti.com/.../main_5F00_O2.asme2e.ti.com/.../main_5F00_noO2.asm

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Nick、


    为了检查功能、我更改了您的主要部分:

    e2e.ti.com/.../changed_5F00_main.c

    查看它在日志分析器上的工作情况。

    然后代码编译并加载、但不起作用:引脚 DEBUG_PIN_SHIFT_C 始终在两个内核上切换(两者都在等待 spinlock_acquire)。

    如果我更换您的 ASM 线路:
    XIN         0x90, &R14.b0, 1

    搭配这两个:
    XIN         0x90, &R1.b3, 1
    MOV         R14.b0, R1.b3

    一切都按预期运行。
             
    为了完整起见,我附上了图片中的原始测试代码,以便查看#ifdef-paths 更多 easy.e2e.ti.com/.../4606.main.c
    我还重新检查了编译 C 时的结果(不是 ASM-codepath ),有和没有 O2 设置。
    我得到了同样的结果:没有 XOUT 指令在优化版本中找到。 唯一的 XOUT 是:
    $C$DW8美元  .dwtag DW_TAG_subprogram
      .dwattr $C$DW8美元、DW_AT_NAME(“__XOUT")“)
      .dwattr $C$DW8美元、DW_AT_TI_SYMBOL_NAME(“__XOUT")“)


    在 XIN 之前、XOUT 之后、固件应该有>= 8 个时钟:
    ->他们没有在 TRM 中为 INT_SPIN_ID(我们的 0x90)写入此值、他们提到仅为 EXT_SPIN_ID(例如 0x91、0x92)写入此值

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好 Stefan、

    Spinlock 通信必须使用 R1 及其含义

    良好的调试,感谢反馈使用除 R1 以外的寄存器接收 spinlock XIN 不起作用。

    如果 SPINLOCK 返回状态使用标准宽边接口路径、我们可以使用任何寄存器。 但看起来返回状态信号实际上是单独的侧通道。 我不具备在源代码中准确跟踪 PRU 内核的消耗情况的专业知识、但您的测试使其看起来像是信号以某种方式连接到 R1。 在这种情况下、我将只记录 TRM R1.B3 中记录的字节。

    作为我自己的参考、您之前说过如果您使用其他 R1 字节、也可以使用它吗?
    Xin      0x90、&R1.B2、1
    Xin      0x90、&R1.b1、1

    如果我们必须使用 R1、而我们不想覆盖 R1.b0 中的标志值、我认为在 C 代码中使用___ xin () 就不能了。 据我所知、__xin 在不写入.b0 的情况下无法写入.b1、.b2、.b3。

    您还需要做什么?  

    您是否需要从您的身边任何其他东西来不断取得进步?

    我仍在研究 PRU 子系统之间的 SPINLOCK 连接、但仍需要更新 TRM 文档并发布示例代码、但这不应成为您的阻止程序。

    更新了示例代码  

    感谢您发布您的示例代码、非常感谢。 我将提取示例中的元素、如下所示:

    /*
     * SPDX-License-Identifier: BSD-3-Clause
     * Copyright (C) 2026 Texas Instruments Incorporated - http://www.ti.com/
     */
    
    #include <stdint.h>
    
    /* Declaration of the external assembly functions (defined in spinlock.asm) */
    /*
     * NOTE: These functions are written to use BS_ID = 0x90, which is the spinlock
     * in the local PRU subsystem. A separate function would be needed for
     * accessing spinlocks in a different PRU subsystem.
     */
    uint8_t spinlock_acquire(uint8_t flag_id);
    void spinlock_release(uint8_t flag_id);
    
    /* Spinlock values */
    #define SPINLOCK_FLAG 11 /* Value 0-63 */
    
    /* Debug signals */
    /* R30 is used to write to PRU GPO signals */
    /* TODO: implement pinmuxing for signals as discussed in GPIO lab */
    volatile register uint32_t __R30;
    /* TODO: Verify PRU0 defined in makefile */
    /* TODO: update shift value based on specific board pinmuxing */
    #if PRU0
    #define DEBUG_PIN_SHIFT 4 /* PRU0 debug pin */
    #else
    #define DEBUG_PIN_SHIFT 5 /* PRU1 debug pin */
    #endif
    
    /* Number of clocks for each PRU to hold the spinlock */
    #if PRU0
    #define HOLD_SPINLOCK_TIME 1000 /* PRU0 holds for 1000 clocks */
    #else
    #define HOLD_SPINLOCK_TIME 2000 /* PRU1 holds for 2000 clocks */
    #endif
    
    void main(void)
    {
            uint8_t result = 0;
            /* zero out all PRU GPO signals */
            __R30 = 0x00000000;
    
            while(1) {
                    /* loop until we get the spinlock */
                    result = 0;
                    do {
                            result = spinlock_acquire(SPINLOCK_FLAG);
                    } while (result != 1);
    
                    /* toggle debug signal high while we hold the spinlock */
                    __R30 |= (1 << DEBUG_PIN_SHIFT);
    
                    __delay_cycles(HOLD_SPINLOCK_TIME);
    
                    /* now release the spinlock */
                    spinlock_release(SPINLOCK_FLAG);
    
                    /* toggle debug signal low after releasing the spinlock */
                    __R30 &= ~(1 << DEBUG_PIN_SHIFT);
            }
    
            /* This program will not reach __halt because of the while loop */
            __halt();
    }
    

    ; SPDX-License-Identifier: BSD-3-Clause
    ; Copyright (C) 2026 Texas Instruments Incorporated - http://www.ti.com/
    
    ;******************************************************************************
    ; Build Configuration
    ;******************************************************************************
    
    ; Required for building .out with assembly file
        .retain
        .retainrefs
    
    ;******************************************************************************
    ; uint8_t spinlock_acquire(uint8_t flag_id);
    ;******************************************************************************
    
    ; .sect ".text:spinlock_acquire" places all code below the .sect directive into
    ; the .text section, grouped into a subsection named "spinlock_acquire"
        .sect       ".text:spinlock_acquire"
        .clink
        .global     spinlock_acquire
    
    spinlock_acquire:
    
    ;------------------------------------------------------------------------------
    ;   Function input arguments are stored in R14-R29.
    ;   flag_id is a uint8_t (8-bit), so it is stored in R14.b0.
    ;   The return value (uint8_t) is stored in R14.b0.
    ;
    ;   For more details about how function arguments are stored in registers,
    ;   reference the document "PRU Optimizing C/C+ Compiler User's Guide",
    ;   section "Function Structure and Calling Conventions"
    ;------------------------------------------------------------------------------
    
        ; 1) Copy flag_id from R14.b0 to R1.b0 for the spinlock hardware
        MOV         R1.b0, R14.b0
    
        ; 2) XIN: Request spinlock flag. The spinlock hardware writes the result
        ;    (0 = not acquired, 1 = acquired) into R1.b3.
        ;    NOTE: Uses BS_ID = 0x90 (spinlock in the local PRU subsystem).
        ;    A separate function would be needed for a different PRU subsystem.
        XIN         0x90, &R1.b3, 1
        MOV         R14.b0, R1.b3
    
        ; Return from spinlock_acquire. Return value (lock status) is in R14.b0.
        JMP         r3.w2
    
    ;******************************************************************************
    ; void spinlock_release(uint8_t flag_id);
    ;******************************************************************************
    
        .sect       ".text:spinlock_release"
        .clink
        .global     spinlock_release
    
    spinlock_release:
    
    ;------------------------------------------------------------------------------
    ;   Function input arguments are stored in R14-R29.
    ;   flag_id is a uint8_t (8-bit), so it is stored in R14.b0.
    ;   No return value.
    ;
    ;   For more details about how function arguments are stored in registers,
    ;   reference the document "PRU Optimizing C/C+ Compiler User's Guide",
    ;   section "Function Structure and Calling Conventions"
    ;------------------------------------------------------------------------------
    
        ; 1) Copy flag_id from R14.b0 to R1.b0 for the spinlock hardware
        MOV         R1.b0, R14.b0
    
        ; 2) XOUT: Release the spinlock flag. The spinlock hardware looks at
        ;    R1.b0 for the flag ID when it receives an XOUT command.
        ;    NOTE: Uses BS_ID = 0x90 (spinlock in the local PRU subsystem).
        ;    A separate function would be needed for a different PRU subsystem.
        XOUT        0x90, &R1.b3, 1
    
        ; Return from spinlock_release
        JMP         r3.w2

    此致、

    Nick

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Nick、

    感谢您的提问 — 我可以:我可以使用当前的 C 实现(因为我不使用优化 — 仍然想知道,为什么编译器会丢弃___ xout,但可以)。

    它看起来是有线的、但已经过测试:

    uint32_t obj = lock_id & SPINLOCK_ID_MASK;
    __xin(SPINLOCK_DEV, SPINLOCK_BASE_REGISTER, SPINLOCK_USE_REMAPPING, obj);

    将更改 OBJ 中的 byte[3]-这将反映 R1.B3
    这是为什么

    if (((obj >> 24) & 0x01) == 1) { /* acquired */ }

    可行。

    尽管它看起来像一个由值调用的函数、但值会以某种方式发生变化。
    但编译器用户指南清楚地说明了:
    void __xout ( unsigned int device_id, unsigned int base_register , unsigned int use_remapping , void& object );
    ->就像 fas void&一样“清晰“在 c.

    对于您的问题、如果我们可以使用 R1.B3 以外的其他功能、答案是“否“:只有 R1.B3 有效(已测试)。


    “[...]你之前说过如果你做了其他 R1 字节也可以用“:我说的是、在 C-Code-I 中、我可以使用 3 个(4 个)字节来释放 spinlock:

    uint32_t obj = (lock_id & SPINLOCK_ID_MASK) << 24;   // works
    uint32_t obj = (lock_id & SPINLOCK_ID_MASK) << 16;   // works
    uint32_t obj = (lock_id & SPINLOCK_ID_MASK) << 8;    // works
    uint32_t obj = (lock_id & SPINLOCK_ID_MASK)          // does not work

    __xout(SPINLOCK_DEV, SPINLOCK_BASE_REGISTER, SPINLOCK_USE_REMAPPING, obj);

    这是最初的问题。

    实际上、对于 ASM-VERSION、设置的 R1 字节来解锁特定 spinlock 至关重要:

    LDI         R1, 0
    MOV         R1.b0, R14.b0
    XOUT        0x90, &R14.b0, 1

    它必须为 r1.b0、其他值不起作用(已测试)。

    因此、我仍然想知道、对于带有__XOUT-的 C-Code、谁将 r1.b0 设置为正确的 spinlock_id? 用户可能会想:如果我将 uint32 的 b0 设置为 spinlock_id、则它将映射到 r1.b0。 但事实并非如此。 这是 R1.b0 设置不正确的唯一情况。 所有其他情况都在做这项工作。 但谁在做这种映射? 我的意思是、 _xout 是一个通用的“函数“(不仅适用于 spinlock)、我认为它使用的“映射“总是相同的:uint32_t 转至 R1.b0、依此类推。

    此致、

    Stefan