【ARM】LED實驗——eclipse

實驗步驟

  1. 在設備原理圖中找到LED的電路:

    LED電路

  2. 分析電路,可知當CHG_COK爲高電平時,LED點亮;當CHG_COK爲低電平時,LED熄滅。

  3. 在覈心電路原理圖中找到CHG_COK引腳:

    核心板原理圖

  4. 分析核心板的引腳圖,可以知道,CHG_COK由GPX2_7控制,這是一組GPIO引腳中的一個。

  5. 查詢芯片手冊中GPX2這一節,可以得知控制GPX2組中GPIO引腳的寄存器地址以及功能定義,如圖:

    GPX2寄存器地址

  6. 編寫彙編程序控制寄存器,實現硬件控制

    .global _start
_start:      @彙編入口

    @ .global _start    將_start聲明稱一個全局的符號  使其全局可用

    @ .equ 相當於C中的宏定義
    @ .equ DATA, 0xFF
    @ mov r1, #DATA

    @ mov r1, #1
    @ 在當前地址申請一個字的空間並將其初始化
    @ .word 0x12345678
    @ mov r1, #1

    @ mov r1, #1
    @ 在當前地址申請一個字節的空間並將其初始化
    @ .byte 0x12
    @ .byte 0x12
    @ .byte 0x12
    @ .byte 0x12
    @ mov r1, #1

    @ mov r1, #1
    @ .space 100, 0xFF
    @ mov r1, #1
    @在當前的地址申請多個字節的空間  並將其初始化

    @ 條件編譯
    @ .if 0
    @   mov r1, #1
    @ .endif

    @/******************C語言和彙編語言的混合編程*******************/
    @ C語言和彙編語言的混合編程的原則就是在哪種語言下符合哪種語言的語法
    @ 1.彙編語言跳轉到C語言
        @ 彙編語言 -> 將C函數看做彙編標號
        @   mov r1, #1
        @   mov r2, #2
        @   b main
        @ C語言
        @   int main()
        @   {
        @
        @   }
    @ 2.C語言跳轉到彙編語言
        @ C語言
        @ extern void FUNC(void);
        @ int main()
        @ {
        @   int a;
        @   a = 1;
        @   FUNC();
        @   a = 2;
        @ }
        @ 彙編語言
        @ FUNC:
        @   mov r1, #1
        @   mov pc, lr
    @ 3.C語言內聯彙編語言
        @ C語言
        @ int main()
        @ {
        @   int a;
        @   a = 1;
        @   asm
        @   (
        @       "mov r1, #1\n"
        @       "mov r2, #2\n"
        @   );
        @   a = 2;
        @ }

    @/******************ATPCS協議*******************/
        @ 1.棧的使用:使用滿減棧
        @ 2.寄存器的使用
        @ a.如果函數有參數的時候  使用r0-r3傳參  多於4個參數的時候使用數據棧
        @ b.如果有返回值  使用r0傳遞  如果返回值是64位  使用r0、r1共同傳遞
        @ c.棧指針使用r13

    @/******************uboot下載程序*******************/
        @ 將開發板薄碼開關撥成0110
        @ 安裝好CH340驅動後在 “我的電腦”-“管理”-“設備管理器”-“端口”-“COMx”
        @ 打開超級終端  波特率:115200 流控制:無
        @ 打開開發板進行設置:
        @   1、set bootcmd
        @   2、save
        @ 程序下載
        @   loadb 40008000  將二進制程序下載到40008000地址(kermit協議)
        @   go 40008000     程序跳轉到40008000執行

    @/******************接口實驗的基本原理*******************/
        @ 一個處理器能夠操作的地址空間是固定的,是由處理器的地址總線寬度決定的
        @ CPU想要操作CPU之外的數據就必須將這些數據放到其地址空間
        @ CPU不能直接控制硬件,所以將硬件的控制映射到CPU的地址空間的一段地址即特殊功能寄存器
        @ CPU可以直接操作特殊功能寄存器,而特殊功能寄存器又能控制硬件,這樣CPU通過操作特殊功能寄存器實現了對硬件間接的控制

    @/******************LED實驗*******************/

        @/*實驗步驟*/
            @ 1.分析LED的控制原理-高低電平控制亮滅
            @ 2.找出LED與主處理器的連接關係
            @ 3.設置寄存器將對應的引腳設置成輸出功能
MAIN:
    BL CONFIG
LOOP:
    BL LEDON
    BL DELAY
    BL LEDOFF
    BL DELAY
    B  LOOP


CONFIG:
    LDR R1, =0x11000c40
    LDR R2, =0x10000000
    STR R2, [R1]
    MOV PC, LR

LEDOFF:
    LDR R1, =0x11000c44
    LDR R2, =0x00000000
    STR R2, [R1]
    MOV PC, LR

LEDON:
    LDR R1, =0x11000c44
    LDR R2, =0x00000080
    STR R2, [R1]
    MOV PC, LR

DELAY:
    LDR R1, =100000000
T:
    SUB R1, R1, #1
    CMP R1, #0
    BNE T
    MOVEQ PC, LR

stop:
    b stop     @死循環,防止跑飛 while(1)
.end         @彙編程序結束

Makefile如下

TARGET=asm-arm
all:
    arm-none-eabi-gcc-4.6.2 -O0 -g -c -o $(TARGET).o $(TARGET).s
    arm-none-eabi-ld        $(TARGET).o -Ttext 0x40008000 -o $(TARGET).elf
    arm-none-eabi-objcopy   -O binary -S  $(TARGET).elf  $(TARGET).bin
    arm-none-eabi-objdump   -D $(TARGET).elf >$(TARGET).dis 
clean:
    rm -rf *.o *.elf *.dis *.bin

如果要使用C語言控制,需要進行初始化C程序的運行環境

初始化彙編代碼:

.text
.global _start
_start:
        b       reset
        ldr     pc,_undefined_instruction
        ldr     pc,_software_interrupt
        ldr     pc,_prefetch_abort
        ldr     pc,_data_abort
        ldr     pc,_not_used
        ldr     pc,_irq
        ldr     pc,_fiq

_undefined_instruction: .word  _undefined_instruction
_software_interrupt:    .word  _software_interrupt
_prefetch_abort:        .word  _prefetch_abort
_data_abort:            .word  _data_abort
_not_used:          .word  _not_used
_irq:                   .word  irq_handler
_fiq:               .word  _fiq


reset:

    ldr r0,=0x40008000
    mcr p15,0,r0,c12,c0,0       @ Vector Base Address Register

        mrs     r0,cpsr
        bic     r0,r0,#0x1f
        orr     r0,r0,#0xd3
        msr     cpsr,r0         @ Enable svc mode of cpu

        mov r0, #0xfffffff
        mcr p15, 0, r0, c1, c0, 2   @ Defines access permissions for each coprocessor
                                    @ Privileged and User mode access

    /*
     * Invalidate L1 I/D
     */
    mov r0, #0          @ set up for MCR
    mcr p15, 0, r0, c8, c7, 0   @ invalidate TLBs
    mcr p15, 0, r0, c7, c5, 0   @ invalidate icache


    @Set the FPEXC EN bit to enable the FPU:
    MOV r3, #0x40000000
    fmxr FPEXC, r3

    /*
     * disable MMU stuff and caches
     */
    mrc p15, 0, r0, c1, c0, 0
    bic r0, r0, #0x00002000 @ clear bits 13 (--V-)
    bic r0, r0, #0x00000007 @ clear bits 2:0 (-CAM)
    orr r0, r0, #0x00001000 @ set bit 12 (---I) Icache
    orr r0, r0, #0x00000002 @ set bit 1  (--A-) Align
    orr r0, r0, #0x00000800 @ set bit 11 (Z---) BTB
    mcr p15, 0, r0, c1, c0, 0

/* LED Test Code */

    ldr r0, =0x114001E0
    ldr r1, [r0]
    bic r1, r1, #0xf0000
    orr r1, r1, #0x10000
    str r1, [r0]

    ldr r0, =0x114001E8
    ldr r1, [r0]
    bic r1, r1, #0x300
    str r1, [r0]

    ldr r0, =0x114001E4
    ldr r1, [r0]
    orr r1, r1, #0x10
    str r1, [r0]

init_stack:
        ldr     r0,stacktop         /*get stack top pointer*/

    /********svc mode stack********/
        mov     sp,r0
        sub     r0,#128*4          /*512 byte  for irq mode of stack*/
    /****irq mode stack**/
        msr     cpsr,#0xd2
        mov     sp,r0
        sub     r0,#128*4          /*512 byte  for irq mode of stack*/
    /***fiq mode stack***/
        msr     cpsr,#0xd1
        mov     sp,r0
        sub     r0,#0
    /***abort mode stack***/
        msr     cpsr,#0xd7
        mov     sp,r0
        sub     r0,#0
    /***undefine mode stack***/
        msr     cpsr,#0xdb
        mov     sp,r0
        sub     r0,#0
   /*** sys mode and usr mode stack ***/
        msr     cpsr,#0x10
        mov     sp,r0             /*1024 byte  for user mode of stack*/

        b       main

    .align  4

    /****  swi_interrupt handler  ****/


    /****  irq_handler  ****/
irq_handler:

    sub  lr,lr,#4
    stmfd sp!,{r0-r12,lr}
    .weak do_irq
    bl  do_irq
    ldmfd sp!,{r0-r12,pc}^

stacktop:    .word      stack+4*512
.data

stack:   .space  4*512

Makefile如下

CROSS_COMPILE = arm-none-eabi-
NAME =interface
#=============================================================================#
CFLAGS += -g   -O0  -mabi=apcs-gnu -mfpu=neon -mfloat-abi=softfp  -fno-builtin \
            -nostdinc  -I ./common/include                                                     
LD  = $(CROSS_COMPILE)ld
CC  = $(CROSS_COMPILE)gcc
OBJCOPY = $(CROSS_COMPILE)objcopy
OBJDUMP = $(CROSS_COMPILE)objdump
#============================================================================#
OBJSss  := $(wildcard start/*.S) $(wildcard common/src/*.S) $(wildcard *.S)\
           $(wildcard start/*.c) $(wildcard common/src/*.c)              \
           $(wildcard usr/*.c) $(wildcard *.c) 
OBJSs   := $(patsubst %.S,%.o,$(OBJSss))
OBJS    := $(patsubst %.c,%.o,$(OBJSs))
#============================================================================#
%.o: %.S 
    $(CC) $(CFLAGS) -c -o  $@ $<
%.o: %.c
    $(CC) $(CFLAGS) -c -o  $@ $<
all:clean  $(OBJS)
    $(LD)  $(OBJS) -T map.lds -o $(NAME).elf
    $(OBJCOPY)  -O binary  $(NAME).elf $(NAME).bin 
    $(OBJDUMP) -D $(NAME).elf > $(NAME).dis 
#============================================================================#
clean:
    rm -rf $(OBJS) *.elf *.bin *.dis *.o
#============================================================================#

C程序如下,該程序爲流水燈的實現


typedef struct
{
    unsigned int CON;
    unsigned int DAT;
    unsigned int PUD;
    unsigned int DRV;
}gpx2;

typedef struct
{
    unsigned int CON;
    unsigned int DAT;
    unsigned int PUD;
    unsigned int DRV;
}gpx1;

typedef struct
{
    unsigned int CON;
    unsigned int DAT;
    unsigned int PUD;
    unsigned int DRV;
    unsigned int CONPDN;
    unsigned int PUDPDN;
}gpf3;

#define GPX1 (*(volatile gpx1 *)0x11000c20)
#define GPX2 (*(volatile gpx2 *)0x11000c40)
#define GPF3 (*(volatile gpf3 *)0x114001e0)

void init()
{
    unsigned int data;
    // init led2
    data = GPX2.CON;
    data &= ~(0xf << 28);
    data |= (0x1 << 28);
    GPX2.CON = data;

    // init led3
    data = GPX1.CON;
    data &= ~(0xf << 0);
    data |= (0x1 << 0);
    GPX1.CON = data;

    // init led4
    data = GPF3.CON;
    data &= ~(0xf << 16);
    data |= (0x1 << 16);
    GPF3.CON = data;

    // init led5
    data = GPF3.CON;
    data &= ~(0xf << 20);
    data |= (0x1 << 20);
    GPF3.CON = data;
}

void led_op(int num, int op)
{
    unsigned int data;
    switch(num)
    {
    case 2:
        data = GPX2.DAT;
        data = op==0?(data & ~(0x1 << 7)):(data | 0x1 << 7);
        GPX2.DAT = data;
        break;
    case 3:
        data = GPX1.DAT;
        data = op==0?(data & ~(0x1 << 0)):(data | 0x1 << 0);
        GPX1.DAT = data;
        break;
    case 4:
        data = GPF3.DAT;
        data = op==0?(data & ~(0x1 << 4)):(data | 0x1 << 4);
        GPF3.DAT = data;
        break;
    case 5:
        data = GPF3.DAT;
        data = op==0?(data & ~(0x1 << 5)):(data | 0x1 << 5);
        GPF3.DAT = data;
        break;
    default:
        break;
    }
}



void delay(int sec)
{
    int i = sec * 1000000;
    while(i--);
}

int main()
{
    init();
    int i = 0;
    while(1)
    {
        led_op(i % 4 + 2, 1);
        delay(1);
        led_op(i % 4 + 2, 0);
        i = (i + 1) % 4;
    }
    return 0;
}
發佈了461 篇原創文章 · 獲贊 271 · 訪問量 112萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章