1. 程式人生 > 其它 >C語言下的Led燈

C語言下的Led燈

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
主要是給自己看的,所以肯定會出現很多錯誤哈哈哈哈哈