C語言下的Led燈
阿新 • • 發佈:2021-11-17
1. 設計思想
1.1 設定處理器模式
設定sp啥的彙編要先進入SVC模式,超級管理員特權模式,這樣就可以訪問所有暫存器了,需要用到cpsr暫存器
0到4位要設定svc模式10011 = 0x13, 就不能用ldr和str了因為不能操作這兩個暫存器
1.2 設定sp指標
進入C語言之前要設定出棧和入棧。sp可以指向內部ram,也可以指向ddr。在6u啟動的時候上一章講的,其實ddr已經被初始化了,sp設定到哪裡呢?要設定堆疊大小,0x200000 = 2M(隨便設定)。
處理器棧增長方式:
對於A7而言是向下增長的,就是從高地址向低地址增長,512M DDR的地址是0x80000000-0x9FFFFFFF, 如果設定成8000000了就相當於0了!那樣的話sp就是0x80200000
1.3 跳轉到C語言
用b來跳轉main函式
2.程式碼
start.s
.global _start _start: /* 操作cpsr暫存器使其進入到超級管理員模式 */ mrs r0, cpsr bic r0, r0, #0x1f @位消除,將後面5位設定為0 orr r0, r0, #0x13 @按位或,上面5位設定位0之後就可以賦值進入svc啦 @ mov r0 #0x13 這種賦值語句,看起來還可以,但是前面27位都為0啦,我們只關心後面5位 msr cpsr, r0 /* 設定棧指標 */ ldr sp,=0x80200000 /* 跳轉C */ b main
main.h
#ifndef __MAIN_C #define __MAIN_C /* * CCM 相關暫存器地址 */ #define CCM_CCGR0 *((volatile unsigned int *)0X020C4068) #define CCM_CCGR1 *((volatile unsigned int *)0X020C406C) #define CCM_CCGR2 *((volatile unsigned int *)0X020C4070) #define CCM_CCGR3 *((volatile unsigned int *)0X020C4074) #define CCM_CCGR4 *((volatile unsigned int *)0X020C4078) #define CCM_CCGR5 *((volatile unsigned int *)0X020C407C) #define CCM_CCGR6 *((volatile unsigned int *)0X020C4080) /* * IOMUX 相關暫存器地址 */ #define SW_MUX_GPIO1_IO03 *((volatile unsigned int *)0X020E0068) #define SW_PAD_GPIO1_IO03 *((volatile unsigned int *)0X020E02F4) /* * GPIO1 相關暫存器地址 */ #define GPIO1_DR *((volatile unsigned int *)0X0209C000) #define GPIO1_GDIR *((volatile unsigned int *)0X0209C004) #define GPIO1_PSR *((volatile unsigned int *)0X0209C008) #define GPIO1_ICR1 *((volatile unsigned int *)0X0209C00C) #define GPIO1_ICR2 *((volatile unsigned int *)0X0209C010) #define GPIO1_IMR *((volatile unsigned int *)0X0209C014) #define GPIO1_ISR *((volatile unsigned int *)0X0209C018) #define GPIO1_EDGE_SEL *((volatile unsigned int *)0X0209C01C) #endif // !__MAIN_C
main.c
#include "main.h"
void clock_enable()
{
CCM_CCGR0 = 0xFFFFFFFF;
CCM_CCGR1 = 0xFFFFFFFF;
CCM_CCGR2 = 0xFFFFFFFF;
CCM_CCGR3 = 0xFFFFFFFF;
CCM_CCGR4 = 0xFFFFFFFF;
CCM_CCGR5 = 0xFFFFFFFF;
CCM_CCGR6 = 0xFFFFFFFF;
}
void led_init()
{
SW_MUX_GPIO1_IO03 = 0x5;
SW_PAD_GPIO1_IO03 = 0x10b0;
GPIO1_GDIR = 0x8;
GPIO1_DR = 0xfffffff7;
}
/*
* 將 GPIO1_DR 的 bit3 清零
*/
void led_on(void)
{
GPIO1_DR &= ~(1<<3);
}
/*
* @description : 關閉 LED 燈
* @param : 無
* @return : 無
*/
void led_off(void)
{
/*
* 將 GPIO1_DR 的 bit3 置 1
*/
GPIO1_DR |= (1<<3);
}
void delay_short(volatile unsigned int n)
{
while(n--);
}
void delay(volatile unsigned int n)
{
while (n--)
{
/* code */
delay_short(0x7ff);
}
}
void main()
{
clock_enable();
led_init();
while (1)
{
/* code */
led_on();
delay(500);
led_off();
delay(500);
}
}
Makefile
objs := start.o main.o # 檔案定義
# $^表示所有依賴檔案的集合
# $@表示所有生成目標檔案
ledc.bin : $(objs)
arm-linux-gnueabihf-ld -Ttext 0x87800000 -o ledc.elf $^
arm-linux-gnueabihf-objcopy -O binary -S ledc.elf $@
arm-linux-gnueabihf-objdump -D -m arm ledc.elf > ledc.dis
# $< 表示依賴檔案的第一個目標,為啥不用$^?
# 因為比如是main.o main.c,usart.c,main對應的第一個檔案沒錯
# $^是所有的該出錯啦
%.o : %.c
arm-linux-gnueabihf-gcc -Wall -nostdlib -c -o $@ $<
%.o : %.S
arm-linux-gnueabihf-gcc -Wall -nostdlib -c -o $@ $<
%.o : %.s
arm-linux-gnueabihf-gcc -Wall -nostdlib -c -o $@ $<
clean:
rm -rf *.o *.elf *.dis *.bin
主要是給自己看的,所以肯定會出現很多錯誤哈哈哈哈哈