ARM内核指令

4.3.5 汇编语言:指令隔离(barrier)指令和存储器隔离指令

CM3 中的另一股新鲜空气是一系列的隔离指令。它们在一些结构比较复杂的存储器系统中是需要的(典型地用于流水线和写缓冲——译者注)。在这类系统中,如果没有必要的隔离,会导致系统发生紊乱危象,(相当于数电中的“竞争 与冒险”——译者注).

举例来说,如果可以在运行时更改存储器的映射关系或者内存保护区的设置,(通过写 MPU 的寄存 器),就必须在更改之后立即补上一条 DSB 指令(数据同步指令)。因为对 MPU 的写操作很可能会被放到一个写缓冲中。写缓冲是为了提高存储器的总体访问效率而设的,但它也有副作用,其中之一,就是会导致写内存的指令被延迟几个周期执行,因此对存储器的设置不能即刻生效,这会导致紧临着的下一 条指令仍然使用旧的存储器设置——但程序员的本意显然是使用新的存储器设置。这种紊乱危象是后患无穷的,常会破坏未知地址的数据,有时也会产生非法地址访问。CM3 提供隔离指令族,就是要消灭这些紊乱危象。

CPSIE I PRIMASK=0;在符合CMSIS的设备驱动库中,可以使用“__enable_irq()”实现该操作;关中断
CPSID I PRIMASK=1;在符合CMSIS的设备驱动库中,可以使用“__disable_irq()”实现该操作;开中断
CPSID F FAULTMASK=1;关异常
CPSIE F FAULTMASK=0;开异常
DMB 数据存储器屏障,确保在新的存储器访问开始之前,所有的存储器访问已经完成。在符合CMSIS的设备驱动库中,可以使用“__DMB”函数实现该操作
DSB 数据同步屏障,确保在下一条指令开始执行前,所有的存储器访问已经完成。在符合CMSIS的设备驱动库中,可以使用“__DSB”函数实现该操作
ISB 指令同步屏障,清除流水线并且确保在新指令执行时,之前的指令都已经执行完毕。在符合CMSIS的设备驱动库中,可以使用“__ISB”函数实现该操作
NOP 无操作。在符合CMSIS的设备驱动库中,可以使用“__NOP()”实现该操作
SEV 多处理器环境中向所有的处理器发送事件(包括自身)。在符合CMSIS的设备驱动库中,可以使用“__SEV()”实现该操作
WFE 等待事件,如果没有之前该事件的记录,进入休眠模式;如果有的话,则清除事件锁存并继续执行;在符合CMSIS的设备驱动库中,可以使用“__WFE()”函数实现该操作,不过若你使用供应商特定的休眠模式,效果会更好
WFI 等待中断,进入休眠模式。在符合CMSIS的设备驱动库中,可以使用“__WFI()”实现该操作,不过若你使用供应商特定的休眠模式,效果会更好
YIELD 用于线程切换,表明任务被延迟了,在Cortex-M0上效果和NOP一样

ARM内核指令_第1张图片

DMB 在双口 RAM 以及多核架构的操作中很有用。如果 RAM 的访问是带缓冲的,并且写完之后马上读,就必须让它“喘口气”——用 DMB 指令来隔离,以保证缓冲中的数据已经落实到 RAM 中。 DSB 比 DMB 更保险(当然也是有执行代价的),它是宁可错杀也不漏网——清空了写缓冲,使得任何它后面的指令,不管要不要使用先前的存储器访问结果,通通等待访问完成。大虾们可以在有绝对信心时使用 DMB,新手还是使用 DSB 比较保险。

同 DMB/DSB 相比,ISB 指令看起来似乎最强悍,但是却一身都是“愣劲”,不由分说就“动粗”。不过它还有其它的用场——对于高级底层技巧:“自我更新”代码,非常有用。举例来说,如果某个程序从下一条要执行的指令处更新了自己,但是先前的旧指令已经被预取到流水线中去了,此时就必须清洗流水线,把旧版本的指令洗出去,再预取新版本的指令。因此,必须在被更新代码段的前面使用 ISB,以保证旧的代码从流水线中被清洗出去,不再有机会执行。

这些汇编指令初学者也许不会用到,一般我们都用符合CMSIS设备驱动库编程,可以在core_cminstr.h文件中中找到这些指令的声明和定义。部分源码如下:

/** \brief  No Operation
    No Operation does nothing. This instruction can be used for code alignment purposes.
 */
#define __NOP                             __nop
 
 
/** \brief  Wait For Interrupt
    Wait For Interrupt is a hint instruction that suspends execution
    until one of a number of events occurs.
 */
#define __WFI                             __wfi
 
 
/** \brief  Wait For Event
    Wait For Event is a hint instruction that permits the processor to enter
    a low-power state until one of a number of events occurs.
 */
#define __WFE                             __wfe
 
 
/** \brief  Send Event
    Send Event is a hint instruction. It causes an event to be signaled to the CPU.
 */
#define __SEV                             __sev
 
 
/** \brief  Instruction Synchronization Barrier
    Instruction Synchronization Barrier flushes the pipeline
    in the processor, so that all instructions following the ISB
    are fetched from cache or  memory, after the instruction
    has been completed.
 */
#define __ISB()                           __isb(0xF)
 
 
/** \brief  Data Synchronization Barrier
    This function acts as a special kind of Data Memory Barrier. 
    It completes when all explicit memory accesses before
    this instruction complete.
 */
#define __DSB()                           __dsb(0xF)
 
/** \brief  Data Memory Barrier
    This function ensures the apparent order of the explicit memory
    operations before and after the instruction,
    without ensuring their completion.
 */
#define __DMB()                           __dmb(0xF)
 
 
/** \brief  Reverse byte order (32 bit)
    This function reverses the byte order in integer value.
    \param [in] value Value to reverse
    \return Reversed value
 */

你可能感兴趣的:(软件编程)