单片机C代码嵌套汇编案例

嵌入式技术

1332人已加入

描述

单片机开发或多或少都会接触一些汇编代码,今天就来说说关于汇编在C中的定义和调用,以及举例说明嵌套汇编代码。

概 述

有认真研究,或者说细心一点的读者应该都知道:C中定义汇编代码与编译器有关。   比如,你在core_cm4.h文件会看到如下的代码:

#if   defined ( __CC_ARM )  #define __ASM           
 __asm                                    
  /*!< asm keyword for ARM Compiler          
*/  #define __INLINE      
   __inline                        
           /*!< inline keyword for ARM Compiler   
    */  #define __STATIC_INLINE  static __inline

 

#elif defined ( __GNUC__ )  #define __ASM            __asm                                
     /*!< asm keyword for GNU Compiler    
     */  #define __INLINE         inline                    
                /*!< inline keyword for GNU Compiler    
  */  #define __STATIC_INLINE  static inline

#elif defined ( __ICCARM__ )  #define __ASM            __asm                          
           /*!< asm keyword for IAR Compiler      
   */  #define __INLINE         inline          
 /*!< inline keyword for IAR Compiler. Only available in High optimization mode! */  #define __STATIC_INLINE  static inline

#elif defined ( __TMS470__ )  #define __ASM      
     __asm                  
                   /*!< asm keyword for TI CCS Compiler    
  */  #define __STATIC_INLINE  static inline

#elif defined ( __TASKING__ )  #define __ASM    
       __asm                                    
 /*!< asm keyword for TASKING Compiler  
   */  #define __INLINE         inline                                
    /*!< inline keyword for TASKING Compiler   */  #define __STATIC_INLINE  static inline

#elif defined ( __CSMC__ )  #define __packed  #define __ASM            _asm                                    
 /*!< asm keyword for COSMIC Compiler      */  #define __INLINE         inline                                  
 /*use -pc99 on compile line !< inline keyword for COSMIC Compiler  
*/  #define __STATIC_INLINE  static inline#endif

编译器

如果你写过Keil C51,你还会发现有如下(通过预处理)嵌套汇编:

#pragma asm

; Assembler Code Here

#pragma endasm

所以,你会发现,不同的编译器,汇编代码还是有差异。当然,这里主要是说C中嵌套汇编与编译器有关。

C中嵌套汇编代码

常见的两种定义: • 在C函数中定义一段汇编代码 • 在C文件中定义一个汇编函数   当然,两个意思差不多,都是在C中嵌套汇编。   上面说了C中定义汇编代码与编译器有关,换句话说:不同编译器解析汇编代码的方式不同。   这里还是拿core_cm3.c来举例说明,定义一个__get_PSP函数。   在Keil MDK中定义:

__ASM uint32_t __get_PSP(void){  mrs r0, psp  bx lr}
在IAR EWARM中定义:  
uint32_t __get_PSP(void){  __ASM("mrs r0, psp");  __ASM("bx lr");}
__asm(__ASM)关键字用于调用内联汇编程序,并且可在 C 或 C++ 语句合法时出现。

举 例

下面举一些常见的例子。   1、FreeRTOS中portmacro.h文件下源代码:

static portFORCE_INLINE void vPortRaiseBASEPRI( void ){uint32_t ulNewBASEPRI = configMAX_SYSCALL_INTERRUPT_PRIORITY;

__asm  {    /* Set BASEPRI to the max syscall priority to effect a critical section. */    msr basepri, ulNewBASEPRI    dsb    isb  }}

2、FreeRTOS中port.c文件下源代码:

__asm void xPortPendSVHandler( void ){  extern uxCriticalNesting;  extern pxCurrentTCB;  extern vTaskSwitchContext;

PRESERVE8

mrs r0, psp  isb

ldr  r3, =pxCurrentTCB    /* Get the location of the current TCB. */  ldr  r2, [r3]

stmdb r0!, {r4-r11}      /* Save the remaining registers. */  str r0, [r2]        /* Save the new top of stack into the first member of the TCB. */

stmdb sp!, {r3, r14}  mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY  msr basepri, r0  dsb  isb  bl vTaskSwitchContext  mov r0, #0  msr basepri, r0  ldmia sp!, {r3, r14}

ldr r1, [r3]  ldr r0, [r1]        /* The first item in pxCurrentTCB is the task top of stack. */  ldmia r0!, {r4-r11}      /* Pop the registers and the critical nesting count. */  msr psp, r0  isb  bx r14  nop} 3、内核复位

这是分享过的一篇文章《一文弄懂STM32复位来源,以及系统与内核复位的区别》中的代码:

__asm void NVIC_CoreReset_a(void){  LDR R0, =0xE000ED0C  LDR R1, =0x05FA0001  STR R1, [R0]deadloop_Core  B deadloop_Core}

以上这些常见例子,可能还没有说透,但相信只要认真理解了都能明白。
编辑:黄飞

 

 

 

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分