實驗步驟
在設備原理圖中找到LED的電路:
分析電路,可知當CHG_COK爲高電平時,LED點亮;當CHG_COK爲低電平時,LED熄滅。
在覈心電路原理圖中找到CHG_COK引腳:
分析核心板的引腳圖,可以知道,CHG_COK由GPX2_7控制,這是一組GPIO引腳中的一個。
查詢芯片手冊中GPX2這一節,可以得知控制GPX2組中GPIO引腳的寄存器地址以及功能定義,如圖:
編寫彙編程序控制寄存器,實現硬件控制
.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;
}