ARM_Linux_NOTE_3

本文介绍了ARM_Linux环境下汇编与C语言混合编程的方法,包括LED实验中的具体实现细节、C语言函数传参方式、内联汇编的使用技巧以及如何通过C代码实现片外模块的功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

ARM_Linux NOTE_3

Vine Farer
2016.08.10

3、ARM汇编、C混合编程

1)LED实验

  • 汇编
    .text
    .globl _start
    _start:
        nop
    
        bl main    #跳进main函数
    
        nop
    
    _stop:
        b _stop
    
  • main.c中的main函数

    volatile:

    1、修饰代码块,屏蔽编译器优化
    2、修饰变量,等式两边对同一变量都读一次

    int main(int argc, char *argc[])
    {
        (*((volatile unsigned int *)(0x11400000 + 0x01e0))) =
                ((*((volatile unsigned int *)(0x11400000 + 0x01e0))) & (0x0fffff)) | (0x100000);
    
        (*((volatile unsigned int *)(0x11400000 + 0x01e4))) |= (0b100000);
    
    return 0;
    }
    
  • Makefile
    SHELL=C:\WINDOWS\system32\cmd.exe
    all:
        arm-none-eabi-gcc -c -g asm.s -o asm.o
        arm-none-eabi-gcc -c -g main.c -o main.o
        arm-none-eabi-ld  -Ttext 0x40008000 asm.o main.o -o asm.elf
        arm-none-eabi-objdump -D asm.elf > asm.dis
    clean:
        rm -rf *.elf *.o
    

2)C语言的传参

  • asm:
    .text
    .globl _start
    _start:
    
        nop
    
        bl main
    
        nop
    
    _stop:
        b _stop
    
    .globl _fun     #全局调用_fun函数,要先用.globl声明
    _fun:
    
        mov r3,#1
        mov r4,#2
        mov pc,lr
    
  • main:
    int _fun();
    
    int fun(int a, int b, int c, int d)
    {
        return 300;
    }
    
    int main(int argc, char *argv[])
    {
        int a = 100;
    
        a = fun(6,7,8,9);
    
        a = _fun();
    
        return 250;
    }
    

3)内联汇编

如果全局调用汇编函数,则pc不断跳转很浪费时间
所以,内联汇编使C中内嵌汇编,省去跳转时间,提高效率
输出列表中的变量,内联结束后,变量会得到寄存器返回的值

int main(int argc, char *argv[])
{
    int a = 100;
    int b, c, d;

    //内联汇编
    asm volatile(               /*也可__asm__ __volatile__*/
                                /*volatile用来关闭编译器优化*/
        "mov r0,#123\n\r"

        "mov %0,#45\n\r"        /* \n是回车,\r是行首 */
        "str r1,%1\n\r"
        "mov r2,%2\n\r"
        "ldr r3,%3\n\r"

        :"+r"(a),"=m"(b)        /*输出列表output table*/
        :"r"(c),"m"(d)          /*输入列表input table*/
        :"r0","r1","r2","r3"    /*异变列表change table*/
    );                          /*r是寄存器传输、m是内存传输*/
                                /*+是可读可写、=是只写、*/
                                /*输出列表的元素默认只读*/
    a = fun(6,7,8,9);

    a = _fun();

    return 250;
}



4)C代码实现片外模块功能

先包含exynos_4412.h头文件,里面包含了所有的片外寄存器声明

  • LED闪烁
    
    #include "exynos_4412.h"
    
    
    void mydelay_ms(int ms)
    {
        int i, j;
        while(ms--)
        {
            for (i = 0; i < 5; i++)
                for (j = 0; j < 514; j++);
        }
    }
    
    int main(int argc, char *argv[])
    {
        int i;
    
        GPF3.CON = (GPF3.CON & (~(0xf << 20))) | (0x1 << 20);
        for(i = 0; i < 100; i ++)
        {
            GPF3.DAT ^= (0b1 << 5);     //异或取反
            mydelay_ms(500);
        }
    
        return 0;
    }
    
  • 蜂鸣器驱动
    
    #include "exynos_4412.h"
    
    
    void mydelay_ms(int ms)
    {
        int i, j;
        while(ms--)
        {
            for (i = 0; i < 5; i++)
                for (j = 0; j < 514; j++);
        }
    }
    
    void mydelay_10us(int us)
    {
        int i, j;
        while(us--)
        {
            for (i = 0; i < 5; i++)
                for (j = 0; j < 5; j++);
        }
    }
    
    int main(int argc, char *argv[])
    {
        int i;
    
        GPD0.CON = (GPD0.CON & ~(0xf << 0)) | (0x1 << 0);
        while(1)
        {
            GPD0.DAT ^= (0x1 << 0);
    //      mydelay_ms(1);
            mydelay_10us(1);
        }
    
        return 0;
    }
    
  • 按键
    /*beep  GPD0_0*/
    GPD0.CON = (GPD0.CON & (~(0xf << 0))) | (0x1 << 0);
    /*led5  GPX3_5*/
    GPF3.CON = (GPF3.CON & (~(0xf << 20))) | (0x1 << 20);
    /*key4  GPX3_5*/
    GPX3.CON &= ~(0xf << 8);
    
    while(1)
    {
        if(0 == (GPX3.DAT & (1 << 2))){
            mydelay_ms(50);
            if(0 == (GPX3.DAT & (1 << 2))){
                GPF3.DAT ^= (1 << 5);
                while(0 == (GPX3.DAT & (1 << 2)))
                    ;
            }
        }
    }
    



DESCEND objtool HOSTCC scripts/mod/modpost.o INSTALL libsubcmd_headers CC /usr/src/kernels/linux-6.12.33/tools/objtool/libsubcmd/exec-cmd.o scripts/mod/modpost.c: In function ‘addend_arm_rel’: scripts/mod/modpost.c:1178:7: error: ‘R_ARM_MOVW_ABS_NC’ undeclared (first use in this function); did you mean ‘R_ARM_THM_ABS5’? case R_ARM_MOVW_ABS_NC: ^~~~~~~~~~~~~~~~~ R_ARM_THM_ABS5 scripts/mod/modpost.c:1178:7: note: each undeclared identifier is reported only once for each function it appears in scripts/mod/modpost.c:1179:7: error: ‘R_ARM_MOVT_ABS’ undeclared (first use in this function); did you mean ‘R_ARM_THM_ABS5’? case R_ARM_MOVT_ABS: ^~~~~~~~~~~~~~ R_ARM_THM_ABS5 scripts/mod/modpost.c:1185:7: error: ‘R_ARM_CALL’ undeclared (first use in this function); did you mean ‘R_ARM_COPY’? case R_ARM_CALL: ^~~~~~~~~~ R_ARM_COPY scripts/mod/modpost.c:1186:7: error: ‘R_ARM_JUMP24’ undeclared (first use in this function); did you mean ‘R_ARM_PC24’? case R_ARM_JUMP24: ^~~~~~~~~~~~ R_ARM_PC24 scripts/mod/modpost.c:1190:7: error: ‘R_ARM_THM_MOVW_ABS_NC’ undeclared (first use in this function); did you mean ‘R_ARM_THM_ABS5’? case R_ARM_THM_MOVW_ABS_NC: ^~~~~~~~~~~~~~~~~~~~~ R_ARM_THM_ABS5 scripts/mod/modpost.c:1191:7: error: ‘R_ARM_THM_MOVT_ABS’ undeclared (first use in this function); did you mean ‘R_ARM_THM_ABS5’? case R_ARM_THM_MOVT_ABS: ^~~~~~~~~~~~~~~~~~ R_ARM_THM_ABS5 scripts/mod/modpost.c:1200:7: error: ‘R_ARM_THM_JUMP19’ undeclared (first use in this function); did you mean ‘R_ARM_THM_PC9’? case R_ARM_THM_JUMP19: ^~~~~~~~~~~~~~~~ R_ARM_THM_PC9 scripts/mod/modpost.c:1222:7: error: ‘R_ARM_THM_JUMP24’ undeclared (first use in this function); did you mean ‘R_ARM_THM_PC8’? case R_ARM_THM_JUMP24: ^~~~~~~~~~~~~~~~ R_ARM_THM_PC8 make[2]: *** [scripts/Makefile.host:133: scripts/mod/modpost.o] Error 1 make[1]: *** [/usr/src/kernels/linux-6.12.33/Makefile:1216: prepare0] Error 2 make[1]: *** 正在等待未完成的任务.... CC /usr/src/kernels/linux-6.12.33/tools/objtool/libsubcmd/help.o CC /usr/src/kernels/linux-6.12.33/tools/objtool/libsubcmd/pager.o CC /usr/src/kernels/linux-6.12.33/tools/objtool/libsubcmd/parse-options.o CC /usr/src/kernels/linux-6.12.33/tools/objtool/libsubcmd/run-command.o CC /usr/src/kernels/linux-6.12.33/tools/objtool/libsubcmd/sigchain.o CC /usr/src/kernels/linux-6.12.33/tools/objtool/libsubcmd/subcmd-config.o LD /usr/src/kernels/linux-6.12.33/tools/objtool/libsubcmd/libsubcmd-in.o AR /usr/src/kernels/linux-6.12.33/tools/objtool/libsubcmd/libsubcmd.a CC /usr/src/kernels/linux-6.12.33/tools/objtool/weak.o CC /usr/src/kernels/linux-6.12.33/tools/objtool/arch/x86/special.o CC /usr/src/kernels/linux-6.12.33/tools/objtool/arch/x86/decode.o CC /usr/src/kernels/linux-6.12.33/tools/objtool/arch/x86/orc.o CC /usr/src/kernels/linux-6.12.33/tools/objtool/check.o LD /usr/src/kernels/linux-6.12.33/tools/objtool/arch/x86/objtool-in.o CC /usr/src/kernels/linux-6.12.33/tools/objtool/special.o CC /usr/src/kernels/linux-6.12.33/tools/objtool/builtin-check.o CC /usr/src/kernels/linux-6.12.33/tools/objtool/elf.o CC /usr/src/kernels/linux-6.12.33/tools/objtool/objtool.o CC /usr/src/kernels/linux-6.12.33/tools/objtool/orc_gen.o CC /usr/src/kernels/linux-6.12.33/tools/objtool/orc_dump.o CC /usr/src/kernels/linux-6.12.33/tools/objtool/libstring.o CC /usr/src/kernels/linux-6.12.33/tools/objtool/libctype.o CC /usr/src/kernels/linux-6.12.33/tools/objtool/str_error_r.o CC /usr/src/kernels/linux-6.12.33/tools/objtool/librbtree.o LD /usr/src/kernels/linux-6.12.33/tools/objtool/objtool-in.o LINK /usr/src/kernels/linux-6.12.33/tools/objtool/objtool make: *** [Makefile:224: __sub-make] Error 2 是什么意思,该怎么解决
06-18
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值