本文主要探讨210定时器相关知识,210定时器主要包含PWN定时器,系统定时器,看门狗,RTC。
PWM定时器
210有5个PWM定时器,timer0、1、2、3通过对应PIO产生PWM波形信号并输出,timer4没有GPIO只产生内部定时器中断
PWM定时器时钟源为PCLK_PSYS,timer0、1共用prescaler0预分频器(8位),timer2、3、4使用prescaler1预分频器(8位),且每个timer有分频器预分频器和分频器构成分频系统,将PCLK_PSYS分频后的时钟给timer作为时钟周期
预分频器分频值范围为1~256,分频器是MUX开关(1/1,1/2,1/4,1/8,1/16)
在PCLK_PSYS(66MHz)下,产生时钟周期范围为0.03us--62.061us,计数器TCNTB值范围为1--2^32,最大时间范围为266548.27s(74h+)


PWN配置寄存器TCFG0、TCFG1、TCON、TCNT、TCNTB、TCNTO、TCMPB

TCFG0用于配置预分频器和死区

TCFG1用于配置分频器

TCON用于配置自动重加载,手动刷入数据,时钟开关

TCNTB是地址寄存器(可写)用于存储计数值便于在自动模式下刷入
TCNT(不可读写)用于周期递减(-1)将计数值写入TCNTB中,启动timer前需要将TCNTB中的值刷到TCNT中(手写寄存器输入一次)

TCNTO(只读)用于读取目前TCNT的值

PWM波形参数:周期T,占空比duty(高电平时间占比),TCMPB决定PWM波形占空比

电平翻转器
电平翻转器是电平取反电路
定义TCNT>TCMPB时为高电平,反之为低电平
当占空比为30%翻转后变为70%(高低电平互换)
死区生成器
PWM应对交流电压进行整流。整流时2路整流分别在正电平和负电平时导通工作,不能同时导通(短路)
实际电路不可能同时上升或下降沿,保留留死区避免短路
死区少容易短路,死区多控制精度低产品性能低
210自带的死区生成器
蜂鸣器
蜂鸣器的2金属片通电吸附撞击产生声音,通过导通频率控制吸附频率控制声音(PWM驱动)
蜂鸣器通过GPD0_2(XpwmTOUT2)引脚连接在SoC
GPD0CON(0xE02000A0),bit8~bit11设置为0b0010(TOUT_2是PWM输出)



看门狗定时器
定时监测cpu防止跑飞,规定周期时间计数内若没有恢复计数,默认系统跑飞则会复位cpu
看门狗配置寄存器WTCON、WTDAT、WTCNT、WTCLRINT

WTCON用于配置时钟源启停,时钟分频,中断启停,复位启停
WTDAT配置第一次使用时间周期(上电到第一次触发的时间) 
WTCNT配置时间周期的计数值
WTCLRINT写任意值清除中断

实时时钟RTC
RTC是内部外设,有独立晶振提供RTC时钟源(32.768KHz),内部的寄存器用来记录时间(年月日时分秒星期),系统关机时时间仍在计时(独立电源供电)
闹钟发生器定点时间产生RTC中断
RTC寄存器

INTP 中断挂起寄存器

RTCCON RTC控制寄存器

RTCALM ALMxxx 闹钟功能有关的寄存器
BCDxxx 时间寄存器

BCD码
27<==转换==>0x27
RTC中所有的时间(年月日时分秒星期,闹钟)用BCD码编码
注意:RTC读写是禁止,读写前打开RTC,读写后关闭,读写RTC寄存器时,一定要注意BCD码和十进制之间的转换,BCDYEAR若2023写入(2023-2000)
demo1:
PWN定时器操作蜂鸣器
start.S
- #define WTCON 0xE2700000
- #define SVC_STACK 0xd0037d80
-
- .global _start
- .global IRQ_handler
-
- _start:
- //close watchDog
- ldr r0,=WTCON
- ldr r1,=0x0
- str r1,[r0]
-
- //init SVC stack
- ldr sp,=SVC_STACK
-
- //init icache
- mrc p15,0,r0,c1,c0,0
- bic r0,r0,#(1<<12) //close icache
- orr r0,r0,#(1<<12) //open icache
- mcr p15,0,r0,c1,c0,0
-
- //use func
- bl main
main.c
- #include "pwn_buzzer.h"
-
- static void dealy_time()
- {
- volatile unsigned int i = 900000;
- while(i--);
- }
-
- int main()
- {
- pwn_buzzer_timer_init();
-
- while(1)
- {
- dealy_time();
- }
-
- return 0;
- }
pwn_buzzer.h
void pwn_buzzer_timer_init();
pwn_buzzer.c
- #define GPD0CON 0xE02000A0
-
- #define TCFG0 0xE2500000
- #define TCFG1 0xE2500004
- #define TCON 0xE2500008
- #define TCNTB2 0xE2500024
- #define TCMPB2 0xE2500028
-
- #define rGPD0CON (*(volatile unsigned int *) GPD0CON)
- #define rTCFG0 (*(volatile unsigned int *) TCFG0)
- #define rTCFG1 (*(volatile unsigned int *) TCFG1)
- #define rTCON (*(volatile unsigned int *) TCON)
- #define rTCNTB0 (*(volatile unsigned int *) TCNTB2)
- #define rTCMPB2 (*(volatile unsigned int *) TCMPB2)
-
- void pwn_buzzer_timer_init()
- {
- //set gpio as buzzer
- rGPD0CON &= ~(0x0f << 8);
- rGPD0CON |= (2 << 8);
-
- //set Prescaler as 65,real Prescaleris 66,Prescaler is 66Mhz /66 = 1Mhz
- rTCFG0 &= ~(0xff<<8);
- rTCFG0 = (65<<8);
-
- //set div ,set div is 2 that mean 1/2,so 1Mhz /2 = 500000hz = 2us
- rTCFG1 &= ~(0x0f<<8);
- rTCFG1 = (1<<8);
-
- //set TCON,set Auto Reload open
- rTCON = (1<<15);
-
- //set TCNTB0,set the count of cycle
- //rTCNTB0 = time you need / set div
- //ex: 1ms / 2us = 500
- rTCNTB0 = 500;
-
- //set TCMPB2,set the rate of duty,mean the rate of high and low level on all cycle
- rTCMPB2 = 250;
-
- //set TCON,when firstly open timer that you Manual Refresh TCNTB0 to TCNT
- rTCON |= (1<<13);
- //after Manual Refresh,close Manual Refresh,then always Auto Reload
- rTCON &= ~(1<<13);
-
- //set TCON,open timer
- rTCON |= (1<<12);
- }
Makefile
- CC = arm-linux-gcc
- LD = arm-linux-ld
- OBJCOPY = arm-linux-objcopy
- OBJDUMP = arm-linux-objdump
-
- #预处理器的flag,flag就是编译器可选的选项
- CPPFLAGS := -nostdlib -nostdinc
- #C编译器的flag
- CFLAGS := -Wall -O2 -fno-builtin
-
- export CC LD OBJCOPY OBJDUMP CPPFLAGS CFLAGS
-
- objs := start.o main.o pwn_buzzer.o
-
- led.bin:$(objs)
- $(LD) -Ttext 0x0 -o buzzer.elf $^
- $(OBJCOPY) -O binary buzzer.elf buzzer.bin
- $(OBJDUMP) -D buzzer.elf > buzzer.dis
- gcc mkv210.c -o mkv210
- ./mkv210 buzzer.bin sd.bin
-
- %.o:%.S
- $(CC) $(CPPFLAGS) $(CFLAGS) -o $@ $< -c
-
- %.o:%.c
- $(CC) $(CPPFLAGS) $(CFLAGS) -o $@ $< -c
-
- clean:
- rm *.o *.elf *.bin *.dis mkv210 -f
demo2:
看门狗中断
start.S
- #define WTCON 0xE2700000
- #define SVC_STACK 0xd0037d80
- #define IRQ_STACK 0xd0037f80
-
- .global _start
- .global IRQ_handler
-
- _start:
- //close watchDog
- ldr r0,=WTCON
- ldr r1,=0x0
- str r1,[r0]
-
- //init SVC stack
- ldr sp,=SVC_STACK
-
- //init icache
- mrc p15,0,r0,c1,c0,0
- bic r0,r0,#(1<<12) //close icache
- orr r0,r0,#(1<<12) //open icache
- mcr p15,0,r0,c1,c0,0
-
- //use func
- bl main
-
- b .
-
- //all interrupt process:Protect the scene + mian iqr process + return scene
- IRQ_handler:
- //init IRQ_STACK
- ldr sp, =IRQ_STACK
- //protect lr
- sub lr, lr, #4
- //protect r0--r12 that in irq stack
- stmfd sp!, {r0-r12, lr}
- //mian iqr process
- bl irq_handler
- //return scene
- ldmfd sp!, {r0-r12, pc}^
main.c
- #include "uart_printf.h"
- #include "wdt_interrupt.h"
- #include "stdio.h"
-
- static void dealy_time()
- {
- volatile unsigned int i = 1000000;
- while(i--);
- }
-
- int main()
- {
- //init uart
- init_uart();
- printf("init uart over\n");
-
- //init outer interupt
- printf("init wdt\n");
- wdt_interrupt();
-
- //init inner interupt
- printf("init inner\n");
- init_inner_interrupt();
-
- //dealy time
- while(1)
- {
- printf("..");
- dealy_time();
- }
-
- return 0;
- }
uart_printf.h
void init_uart();
uart_printf.c
- #define GPA0CON 0xE0200000
-
- #define ULCON0 0xE2900000
- #define UCON0 0xE2900004
- #define UFCON0 0xE2900008
- #define UMCON0 0xE290000C
- #define UTRSTAT0 0xE2900010
- #define UTXH0 0xE2900020
- #define URXH0 0xE2900024
- #define UBRDIV0 0xE2900028
- #define UDIVSLOT0 0xE290002C
-
- #define rGPA0CON (*(volatile unsigned int *)GPA0CON)
- #define rULCON0 (*(volatile unsigned int *)ULCON0)
- #define rUCON0 (*(volatile unsigned int *)UCON0)
- #define rUFCON0 (*(volatile unsigned int *)UFCON0)
- #define rUMCON0 (*(volatile unsigned int *)UMCON0)
- #define rUTRSTAT0 (*(volatile unsigned int *)UTRSTAT0)
- #define rUTXH0 (*(volatile unsigned int *)UTXH0)
- #define rURXH0 (*(volatile unsigned int *)URXH0)
- #define rUBRDIV0 (*(volatile unsigned int *)UBRDIV0)
- #define rUDIVSLOT0 (*(volatile unsigned int *)UDIVSLOT0)
-
- //init uart
- void init_uart()
- {
- //set gpio as uart(rx,tx)
- rGPA0CON &= ~(0xff);
- rGPA0CON |= ((1<<2)|(1<<5));
-
- //set uart base configure(mode)
- rULCON0 = 0x3;
- rUCON0 = 0x5;
- rUMCON0 = 0;
- rUFCON0 = 0;
-
- //set uart baud
- //DIV_VAL = (PCLK / (bps x 16))-1
- //(66000000 /(115200 * 16)) -1 = 34.8
- rUBRDIV0 = 34;
-
- //set uart baud calibration
- //0.8 * 16 = 13,check 210 table
- rUDIVSLOT0 = 0xdfdd;
- }
-
-
- //send data
- void putc(char data)
- {
- while (!(rUTRSTAT0 & (1<<1)));
- rUTXH0 = data;
- }
-
- //receive data
- char getc()
- {
- while (!(rUTRSTAT0 & (1<<0)));
- return (rURXH0 & 0xff);
- }
wdt_interrupt.h
- void wdt_interrupt();
-
- void init_inner_interrupt()
wdt_interrupt.c
- #include "stdio.h"
-
- //watchDog interrupt register
-
- #define WTCON 0xE2700000
- #define WTDAT 0xE2700004
- #define WTCNT 0xE2700008
- #define WTCLRINT 0xE270000C
-
- #define rWTCON *((volatile unsigned int *) WTCON)
- #define rWTDAT *((volatile unsigned int *) WTDAT)
- #define rWTCNT *((volatile unsigned int *) WTCNT)
- #define rWTCLRINT *((volatile unsigned int *) WTCLRINT)
-
- //inner interrupt register
-
- //VIC base address
-
- #define VIC0_BASE 0xF2000000
- #define VIC1_BASE 0xF2100000
- #define VIC2_BASE 0xF2200000
- #define VIC3_BASE 0xF2300000
-
- //VIC0 register
-
- #define rVIC0IRQSTATUS (*(volatile unsigned int *)(VIC0_BASE + 0x0000))
- #define rVIC0FIQSTATUS (*(volatile unsigned int *)(VIC0_BASE + 0x0004))
- #define rVIC0INTSELECT (*(volatile unsigned int *)(VIC0_BASE + 0x000C))
- #define rVIC0INTENABLE (*(volatile unsigned int *)(VIC0_BASE + 0x0010))
- #define rVIC0INTENCLEAR (*(volatile unsigned int *)(VIC0_BASE + 0x0014))
- #define rVIC0VECTADDR (VIC0_BASE + 0x100)
- #define rVIC0ADDRESS (*(volatile unsigned int *)(VIC0_BASE + 0x0F00))
-
- //VIC1 register
-
- #define rVIC1IRQSTATUS (*(volatile unsigned int *)(VIC1_BASE + 0x0000))
- #define rVIC1FIQSTATUS (*(volatile unsigned int *)(VIC1_BASE + 0x0004))
- #define rVIC1INTSELECT (*(volatile unsigned int *)(VIC1_BASE + 0x000C))
- #define rVIC1INTENABLE (*(volatile unsigned int *)(VIC1_BASE + 0x0010))
- #define rVIC1INTENCLEAR (*(volatile unsigned int *)(VIC1_BASE + 0x0014))
- #define rVIC1VECTADDR (VIC1_BASE + 0x100)
- #define rVIC1ADDRESS (*(volatile unsigned int *)(VIC1_BASE + 0x0F00))
-
- //VIC2 register
-
- #define rVIC2IRQSTATUS (*(volatile unsigned int *)(VIC2_BASE + 0x0000))
- #define rVIC2FIQSTATUS (*(volatile unsigned int *)(VIC2_BASE + 0x0004))
- #define rVIC2INTSELECT (*(volatile unsigned int *)(VIC2_BASE + 0x000C))
- #define rVIC2INTENABLE (*(volatile unsigned int *)(VIC2_BASE + 0x0010))
- #define rVIC2INTENCLEAR (*(volatile unsigned int *)(VIC2_BASE + 0x0014))
- #define rVIC2VECTADDR (VIC2_BASE + 0x100)
- #define rVIC2ADDRESS (*(volatile unsigned int *)(VIC2_BASE + 0x0F00))
-
- //VIC3 register
-
- #define rVIC3IRQSTATUS (*(volatile unsigned int *)(VIC3_BASE + 0x0000))
- #define rVIC3FIQSTATUS (*(volatile unsigned int *)(VIC3_BASE + 0x0004))
- #define rVIC3INTSELECT (*(volatile unsigned int *)(VIC3_BASE + 0x000C))
- #define rVIC3INTENABLE (*(volatile unsigned int *)(VIC3_BASE + 0x0010))
- #define rVIC3INTENCLEAR (*(volatile unsigned int *)(VIC3_BASE + 0x0014))
- #define rVIC3VECTADDR (VIC3_BASE + 0x100)
- #define rVIC3ADDRESS (*(volatile unsigned int *)(VIC3_BASE + 0x0F00))
-
- //interrupt vector table
-
- #define vector_table_base 0xD0037400
-
- #define reset_vector (vector_table_base + 0x00)
- #define undef_vector (vector_table_base + 0x04)
- #define sotf_interrupt_vector (vector_table_base + 0x08)
- #define prefetch_vector (vector_table_base + 0x0C)
- #define data_vector (vector_table_base + 0x10)
- #define irq_vector (vector_table_base + 0x18)
- #define fiq_vector (vector_table_base + 0x1C)
-
- #define r_reset_vector (*(volatile unsigned int *) reset_vector)
- #define r_undef_vector (*(volatile unsigned int *) undef_vector)
- #define r_sotf_interrupt_vector (*(volatile unsigned int *) sotf_interrupt_vector)
- #define r_prefetch_vector (*(volatile unsigned int *) prefetch_vector)
- #define r_data_vector (*(volatile unsigned int *) data_vector)
- #define r_irq_vector (*(volatile unsigned int *) irq_vector)
- #define r_fiq_vector (*(volatile unsigned int *) fiq_vector)
-
- //interrupt number
-
- #define NUM_TIMER0 (21)
- #define NUM_TIMER1 (22)
- #define NUM_TIMER2 (23)
- #define NUM_TIMER3 (24)
- #define NUM_TIMER4 (25)
- #define NUM_SYSTIMER (26)
- #define NUM_WDT (27)
- #define NUM_RTC_ALARM (28)
- #define NUM_RTC_TICK (29)
-
- //wdt interrupt func
-
- void wdt_interrupt()
- {
- //set WTCON,set Prescaler,Prescaler is set value + 1
- //Prescaler = 65 + 1 = 66,66Mhz / 66 = 1Mhz = 1000000hz
- rWTCON &= ~(0xff << 8);
- rWTCON |= (65<<8);
- //set div is 128,t = 1/(1000000hz /128) = 1.28us
- rWTCON &= ~(3 << 3);
- rWTCON |= (3<<3);
-
- //set WTCON,open interrupt and close reset
- rWTCON |= (1<<2);
- rWTCON &= ~(1);
-
- //set WTDAT,set set the time form firstly open timer to count open(WTCNT)
- rWTDAT = 1000;
- rWTCNT = 1000;
-
- //open wdt
- rWTCON |= (1<<5);
- }
-
- //dealy_time
-
- static void dealy_time()
- {
- volatile unsigned int i = 1000000;
- while(i--);
- }
-
-
- //outer interrupt key func
- static void isr_wdt()
- {
- static int num = 0;
- printf("wdt interrupt,num = %d\n",num++);
- dealy_time();
-
- //clear VIC0ADDR,clear using interrupt process
- rVIC0ADDRESS = 0;
- rVIC1ADDRESS = 0;
- rVIC2ADDRESS = 0;
- rVIC3ADDRESS = 0;
-
- rWTCLRINT = 1;
- }
-
- //inner interrupt func
-
- static void reset_func()
- {
- printf("reset\n");
- }
-
- static void undef_func()
- {
- printf("undef\n");
- }
-
- static void sotf_interrupt_func()
-
- {
- printf("sotf_intrrupt\n");
- }
-
- static void prefetch_func()
- {
- printf("prefetch\n");
- }
-
- static void data_func()
- {
- printf("data\n");
- }
-
- static void fiq_func()
- {
- printf("irq\n");
- }
-
- void IRQ_handler();
-
- static void bind_isr_VICnINTENCLEAR(unsigned long num,void (*handler)())
- {
- if(num <32)
- {
- printf("bind ok\n");
- *((volatile unsigned int *)(rVIC0VECTADDR + 4 * (num))) = (unsigned)handler;
- }
- else if(num < 64)
- {
- *((volatile unsigned int *)(rVIC0VECTADDR + 4 * (num-32))) = (unsigned)handler;
- }
- else if(num < 96)
- {
- *((volatile unsigned int *)(rVIC0VECTADDR + 4 * (num-64))) = (unsigned)handler;
- }
- else
- {
- *((volatile unsigned int *)(rVIC0VECTADDR + 4 * (num-96))) = (unsigned)handler;
- }
- }
-
- static void enable_interrupt(unsigned long num)
- {
- unsigned long tmp;
-
- if(num < 32)
- {
- tmp = rVIC0INTENABLE;
- tmp |= (1<<num);
- rVIC0INTENABLE = tmp;
- }
- else if(num < 64)
- {
- tmp = rVIC0INTENABLE;
- tmp |= (1<<(num-32));
- rVIC1INTENABLE = tmp;
- }
- else if(num < 96)
- {
- tmp = rVIC0INTENABLE;
- tmp |= (1<<(num-64));
- rVIC2INTENABLE = tmp;
- }
- else if(num < 200)
- {
- tmp = rVIC0INTENABLE;
- tmp |= (1<<(num-96));
- rVIC3INTENABLE = tmp;
- }
- else
- {
- rVIC0INTENABLE = 0xffffffff;
- rVIC1INTENABLE = 0xffffffff;
- rVIC2INTENABLE = 0xffffffff;
- rVIC3INTENABLE = 0xffffffff;
- }
- }
-
- void init_inner_interrupt()
- {
- //bind interrupt process on interrupt vector table
- r_reset_vector = (unsigned int)reset_func;
- r_undef_vector = (unsigned int)undef_func;
- r_sotf_interrupt_vector = (unsigned int)sotf_interrupt_func;
- r_prefetch_vector = (unsigned int)prefetch_func;
- r_data_vector = (unsigned int)data_func;
- r_irq_vector = (unsigned int)IRQ_handler;
- r_fiq_vector = (unsigned int)fiq_func;
-
- //select interrupt mode(irq)
- rVIC0INTSELECT = 0x0;
- rVIC1INTSELECT = 0x0;
- rVIC2INTSELECT = 0x0;
- rVIC3INTSELECT = 0x0;
-
- //diasble interrupt
- rVIC0INTENCLEAR = 0xffffffff;
- rVIC1INTENCLEAR = 0xffffffff;
- rVIC2INTENCLEAR = 0xffffffff;
- rVIC3INTENCLEAR = 0xffffffff;
-
- //clear interrupt process address
- rVIC0ADDRESS = 0;
- rVIC1ADDRESS = 0;
- rVIC2ADDRESS = 0;
- rVIC3ADDRESS = 0;
-
- //bind isr process on VICnINTENCLEAR
- bind_isr_VICnINTENCLEAR(NUM_WDT,isr_wdt);
-
- //enable interrupt
- enable_interrupt(NUM_WDT);
- }
-
- //judge inner interrupt ,get interrupt occure in which VICnVECTADDR
- void irq_handler()
- {
- volatile unsigned int n = 0;
- void (*isr)(void) = NULL;
- for(n = 0;n <4;n++)
- {
- if(n == 0 && rVIC0IRQSTATUS != 0)
- {
- isr = (void (*)(void))rVIC0ADDRESS;
- }
- else if(n == 1 && rVIC1IRQSTATUS != 0)
- {
- isr = (void (*)(void))rVIC1ADDRESS;
- }
- else if(n == 2 && rVIC2IRQSTATUS != 0)
- {
- isr = (void (*)(void))rVIC2ADDRESS;
- }
- else if(n == 3 && rVIC3IRQSTATUS != 0)
- {
- isr = (void (*)(void))rVIC3ADDRESS;
- }
- (*isr)();
- }
- }
link.lds
- SECTIONS
- {
- . = 0xd0020010;
-
- .text :
- {
- start.o
- *(.text)
- }
-
- .data :
- {
- *(.data)
- }
-
- .bss :
- {
- *(.bss)
- }
- }
Makefile
- CC = arm-linux-gcc
- LD = arm-linux-ld
- OBJCOPY = arm-linux-objcopy
- OBJDUMP = arm-linux-objdump
-
- INCDIR := $(shell pwd)
-
- #预处理器的flag,flag就是编译器可选的选项
- CPPFLAGS := -nostdlib -nostdinc -I$(INCDIR)/include
- #C编译器的flag
- CFLAGS := -Wall -O2 -fno-builtin
-
- export CC LD OBJCOPY OBJDUMP CPPFLAGS CFLAGS
-
- objs := start.o uart_printf.o main.o wdt_interrupt.o
- objs += lib/libc.a
-
- led.bin:$(objs)
- $(LD) -Tlink.lds -o wdt_interrupt.elf $^
- $(OBJCOPY) -O binary wdt_interrupt.elf wdt_interrupt.bin
- $(OBJDUMP) -D wdt_interrupt.elf > wdt_interrupt.dis
- gcc mkv210.c -o mkv210
- ./mkv210 wdt_interrupt.bin sd.bin
-
- lib/libc.a:
- cd lib; make; cd ..
-
- %.o:%.S
- $(CC) $(CPPFLAGS) $(CFLAGS) -o $@ $< -c
-
- %.o:%.c
- $(CC) $(CPPFLAGS) $(CFLAGS) -o $@ $< -c
-
- clean:
- rm *.o *.elf *.bin *.dis mkv210 -f
- cd lib; make clean; cd ..
结果示例:

demo3:
看门狗复位
start.S
- #define WTCON 0xE2700000
- #define SVC_STACK 0xd0037d80
-
- .global _start
- .global IRQ_handler
-
- _start:
- //close watchDog
- ldr r0,=WTCON
- ldr r1,=0x0
- str r1,[r0]
-
- //init SVC stack
- ldr sp,=SVC_STACK
-
- //init icache
- mrc p15,0,r0,c1,c0,0
- bic r0,r0,#(1<<12) //close icache
- orr r0,r0,#(1<<12) //open icache
- mcr p15,0,r0,c1,c0,0
-
- //use func
- bl main
-
- b .
main.c
- #include "uart_printf.h"
- #include "wdt_reset.h"
- #include "stdio.h"
-
- static void dealy_time()
- {
- volatile unsigned int i = 1000000;
- while(i--);
- }
-
- int main()
- {
- //init uart
- init_uart();
- printf("init uart over\n");
-
- //init outer interupt
- static int num = 1;
- printf("init wdt,num = %d\n",num++);
- wdt_reset();
-
- //dealy_time
- while(1)
- {
- dealy_time();
-
- }
-
- return 0;
- }
uart_printf.h
void init_uart();
uart_printf.c
- #define GPA0CON 0xE0200000
-
- #define ULCON0 0xE2900000
- #define UCON0 0xE2900004
- #define UFCON0 0xE2900008
- #define UMCON0 0xE290000C
- #define UTRSTAT0 0xE2900010
- #define UTXH0 0xE2900020
- #define URXH0 0xE2900024
- #define UBRDIV0 0xE2900028
- #define UDIVSLOT0 0xE290002C
-
- #define rGPA0CON (*(volatile unsigned int *)GPA0CON)
- #define rULCON0 (*(volatile unsigned int *)ULCON0)
- #define rUCON0 (*(volatile unsigned int *)UCON0)
- #define rUFCON0 (*(volatile unsigned int *)UFCON0)
- #define rUMCON0 (*(volatile unsigned int *)UMCON0)
- #define rUTRSTAT0 (*(volatile unsigned int *)UTRSTAT0)
- #define rUTXH0 (*(volatile unsigned int *)UTXH0)
- #define rURXH0 (*(volatile unsigned int *)URXH0)
- #define rUBRDIV0 (*(volatile unsigned int *)UBRDIV0)
- #define rUDIVSLOT0 (*(volatile unsigned int *)UDIVSLOT0)
-
- //init uart
- void init_uart()
- {
- //set gpio as uart(rx,tx)
- rGPA0CON &= ~(0xff);
- rGPA0CON |= ((1<<2)|(1<<5));
-
- //set uart base configure(mode)
- rULCON0 = 0x3;
- rUCON0 = 0x5;
- rUMCON0 = 0;
- rUFCON0 = 0;
-
- //set uart baud
- //DIV_VAL = (PCLK / (bps x 16))-1
- //(66000000 /(115200 * 16)) -1 = 34.8
- rUBRDIV0 = 34;
-
- //set uart baud calibration
- //0.8 * 16 = 13,check 210 table
- rUDIVSLOT0 = 0xdfdd;
- }
-
-
- //send data
- void putc(char data)
- {
- while (!(rUTRSTAT0 & (1<<1)));
- rUTXH0 = data;
- }
-
- //receive data
- char getc()
- {
- while (!(rUTRSTAT0 & (1<<0)));
- return (rURXH0 & 0xff);
- }
wdt_reset.h
void wdt_reset();
wdt_reset.c
- #define WTCON 0xE2700000
- #define WTDAT 0xE2700004
- #define WTCNT 0xE2700008
- #define WTCLRIN 0xE270000C
-
- #define rWTCON *((volatile unsigned int *) WTCON)
- #define rWTDAT *((volatile unsigned int *) WTDAT)
- #define rWTCNT *((volatile unsigned int *) WTCNT)
- #define rWTCLRI *((volatile unsigned int *) WTCLRI)
-
- void wdt_reset()
- {
- //set WTCON,set Prescaler,Prescaler is set value + 1
- //Prescaler = 65 + 1 = 66,66Mhz / 66 = 1Mhz = 1000000hz
- rWTCON &= ~(0xff << 8);
- rWTCON |= (65<<8);
- //set div is 128,t = 1/(1000000hz /128) = 1.28us
- rWTCON &= ~(3 << 3);
- rWTCON |= (3<<8);
-
- //set WTCON,close interrupt and open reset
- rWTCON &= ~(1<<2);
- rWTCON |= 1;
-
- //set WTDAT,set set the time form firstly open timer to count open(WTCNT)
- rWTDAT = 1000;
- rWTCNT = 1000;
-
- //open wdt
- rWTCON |= (1<<5);
- }
link.lds
- SECTIONS
- {
- . = 0xd0020010;
-
- .text :
- {
- start.o
- *(.text)
- }
-
- .data :
- {
- *(.data)
- }
-
- .bss :
- {
- *(.bss)
- }
- }
Makefile
- CC = arm-linux-gcc
- LD = arm-linux-ld
- OBJCOPY = arm-linux-objcopy
- OBJDUMP = arm-linux-objdump
-
- INCDIR := $(shell pwd)
-
- #预处理器的flag,flag就是编译器可选的选项
- CPPFLAGS := -nostdlib -nostdinc -I$(INCDIR)/include
- #C编译器的flag
- CFLAGS := -Wall -O2 -fno-builtin
-
- export CC LD OBJCOPY OBJDUMP CPPFLAGS CFLAGS
-
- objs := start.o uart_printf.o main.o wdt_reset.o
- objs += lib/libc.a
-
- led.bin:$(objs)
- $(LD) -Tlink.lds -o wdt_reset.elf $^
- $(OBJCOPY) -O binary wdt_reset.elf wdt_reset.bin
- $(OBJDUMP) -D wdt_reset.elf > wdt_reset.dis
- gcc mkv210.c -o mkv210
- ./mkv210 wdt_reset.bin sd.bin
-
- lib/libc.a:
- cd lib; make; cd ..
-
- %.o:%.S
- $(CC) $(CPPFLAGS) $(CFLAGS) -o $@ $< -c
-
- %.o:%.c
- $(CC) $(CPPFLAGS) $(CFLAGS) -o $@ $< -c
-
- clean:
- rm *.o *.elf *.bin *.dis mkv210 -f
- cd lib; make clean; cd ..
结果示例:

demo4:
中断(alarm)读写RTC
start.S
- #define WTCON 0xE2700000
- #define SVC_STACK 0xd0037d80
- #define IRQ_STACK 0xd0037f80
-
- .global _start
- .global IRQ_handler
-
- _start:
- //close watchDog
- ldr r0,=WTCON
- ldr r1,=0x0
- str r1,[r0]
-
- //init SVC stack
- ldr sp,=SVC_STACK
-
- //init icache
- mrc p15,0,r0,c1,c0,0
- bic r0,r0,#(1<<12) //close icache
- orr r0,r0,#(1<<12) //open icache
- mcr p15,0,r0,c1,c0,0
-
- //use func
- bl main
-
- b .
-
- //all interrupt process:Protect the scene + mian iqr process + return scene
- IRQ_handler:
- //init IRQ_STACK
- ldr sp, =IRQ_STACK
- //protect lr
- sub lr, lr, #4
- //protect r0--r12 that in irq stack
- stmfd sp!, {r0-r12, lr}
- //mian iqr process
- bl irq_handler
- //return scene
- ldmfd sp!, {r0-r12, pc}^
main.c
- #include "uart_printf.h"
- #include "rtc_alarm.h"
- #include "stdio.h"
-
- static void dealy_time()
- {
- volatile unsigned int i,j;
- for (i=0; i<10000; i++)
- for (j=0; j<1000; j++);
- }
-
- int main()
- {
- //init uart
- init_uart();
- printf("init uart over\n");
-
- //init outer interupt
- printf("rtc init\n");
- rtc_alarm();
-
- //set RTC time
- struct rtc_time rtc_write =
- {
- .year = 2023,
- .month = 10,
- .date = 22,
- .hour = 14,
- .minute = 00,
- .second = 00,
- .day = 0,
- };
-
- set_rtc_time(&rtc_write);
-
- //init inner interupt
- printf("init inner\n");
- init_inner_interrupt();
-
- struct rtc_time rtc_read;
-
- //dealy time
- while(1)
- {
- get_rtc_time(&rtc_read);
- printf("rtc time:%d-%d-%d--%d %d:%d:%d\n", rtc_read.year,rtc_read.month,rtc_read.date,rtc_read.day,rtc_read.hour,rtc_read.minute,rtc_read.second);
- dealy_time();
- }
-
- while(1);
- return 0;
- }
uart_printf.h
void init_uart();
uart_printf.c
- #define GPA0CON 0xE0200000
-
- #define ULCON0 0xE2900000
- #define UCON0 0xE2900004
- #define UFCON0 0xE2900008
- #define UMCON0 0xE290000C
- #define UTRSTAT0 0xE2900010
- #define UTXH0 0xE2900020
- #define URXH0 0xE2900024
- #define UBRDIV0 0xE2900028
- #define UDIVSLOT0 0xE290002C
-
- #define rGPA0CON (*(volatile unsigned int *)GPA0CON)
- #define rULCON0 (*(volatile unsigned int *)ULCON0)
- #define rUCON0 (*(volatile unsigned int *)UCON0)
- #define rUFCON0 (*(volatile unsigned int *)UFCON0)
- #define rUMCON0 (*(volatile unsigned int *)UMCON0)
- #define rUTRSTAT0 (*(volatile unsigned int *)UTRSTAT0)
- #define rUTXH0 (*(volatile unsigned int *)UTXH0)
- #define rURXH0 (*(volatile unsigned int *)URXH0)
- #define rUBRDIV0 (*(volatile unsigned int *)UBRDIV0)
- #define rUDIVSLOT0 (*(volatile unsigned int *)UDIVSLOT0)
-
- //init uart
- void init_uart()
- {
- //set gpio as uart(rx,tx)
- rGPA0CON &= ~(0xff);
- rGPA0CON |= ((1<<2)|(1<<5));
-
- //set uart base configure(mode)
- rULCON0 = 0x3;
- rUCON0 = 0x5;
- rUMCON0 = 0;
- rUFCON0 = 0;
-
- //set uart baud
- //DIV_VAL = (PCLK / (bps x 16))-1
- //(66000000 /(115200 * 16)) -1 = 34.8
- rUBRDIV0 = 34;
-
- //set uart baud calibration
- //0.8 * 16 = 13,check 210 table
- rUDIVSLOT0 = 0xdfdd;
- }
-
-
- //send data
- void putc(char data)
- {
- while (!(rUTRSTAT0 & (1<<1)));
- rUTXH0 = data;
- }
-
- //receive data
- char getc()
- {
- while (!(rUTRSTAT0 & (1<<0)));
- return (rURXH0 & 0xff);
- }
rtc_struct.h
- struct rtc_time
- {
- unsigned int year;
- unsigned int month;
- unsigned int date; //几号
- unsigned int hour;
- unsigned int minute;
- unsigned int second;
- unsigned int day; //星期
- };
rtc_alarm.h
- #include "rtc_struct.h"
-
- void rtc_alarm();
-
- void set_rtc_time(struct rtc_time *p);
-
- void get_rtc_time(struct rtc_time *p);
-
- void init_inner_interrupt();
rtc_alarm.c
- #include "stdio.h"
- #include "rtc_struct.h"
-
- //rtc interrupt register
-
- #define RTC_BASE 0xE2800000
-
- #define rINTP (*((volatile unsigned long *)(RTC_BASE + 0x30)))
- #define rRTCCON (*((volatile unsigned long *)(RTC_BASE + 0x40)))
- #define rTICCNT (*((volatile unsigned long *)(RTC_BASE + 0x44)))
- #define rRTCALM (*((volatile unsigned long *)(RTC_BASE + 0x50)))
- #define rALMSEC (*((volatile unsigned long *)(RTC_BASE + 0x54)))
- #define rALMMIN (*((volatile unsigned long *)(RTC_BASE + 0x58)))
- #define rALMHOUR (*((volatile unsigned long *)(RTC_BASE + 0x5c)))
- #define rALMDATE (*((volatile unsigned long *)(RTC_BASE + 0x60)))
- #define rALMMON (*((volatile unsigned long *)(RTC_BASE + 0x64)))
- #define rALMYEAR (*((volatile unsigned long *)(RTC_BASE + 0x68)))
- #define rRTCRST (*((volatile unsigned long *)(RTC_BASE + 0x6c)))
- #define rBCDSEC (*((volatile unsigned long *)(RTC_BASE + 0x70)))
- #define rBCDMIN (*((volatile unsigned long *)(RTC_BASE + 0x74)))
- #define rBCDHOUR (*((volatile unsigned long *)(RTC_BASE + 0x78)))
- #define rBCDDATE (*((volatile unsigned long *)(RTC_BASE + 0x7c)))
- #define rBCDDAY (*((volatile unsigned long *)(RTC_BASE + 0x80)))
- #define rBCDMON (*((volatile unsigned long *)(RTC_BASE + 0x84)))
- #define rBCDYEAR (*((volatile unsigned long *)(RTC_BASE + 0x88)))
- #define rCURTICCNT (*((volatile unsigned long *)(RTC_BASE + 0x90)))
- #define rRTCLVD (*((volatile unsigned long *)(RTC_BASE + 0x94)))
-
- //inner interrupt register
-
- //VIC base address
-
- #define VIC0_BASE 0xF2000000
- #define VIC1_BASE 0xF2100000
- #define VIC2_BASE 0xF2200000
- #define VIC3_BASE 0xF2300000
-
- //VIC0 register
-
- #define rVIC0IRQSTATUS (*(volatile unsigned int *)(VIC0_BASE + 0x0000))
- #define rVIC0FIQSTATUS (*(volatile unsigned int *)(VIC0_BASE + 0x0004))
- #define rVIC0INTSELECT (*(volatile unsigned int *)(VIC0_BASE + 0x000C))
- #define rVIC0INTENABLE (*(volatile unsigned int *)(VIC0_BASE + 0x0010))
- #define rVIC0INTENCLEAR (*(volatile unsigned int *)(VIC0_BASE + 0x0014))
- #define rVIC0VECTADDR (VIC0_BASE + 0x100)
- #define rVIC0ADDRESS (*(volatile unsigned int *)(VIC0_BASE + 0x0F00))
-
- //VIC1 register
-
- #define rVIC1IRQSTATUS (*(volatile unsigned int *)(VIC1_BASE + 0x0000))
- #define rVIC1FIQSTATUS (*(volatile unsigned int *)(VIC1_BASE + 0x0004))
- #define rVIC1INTSELECT (*(volatile unsigned int *)(VIC1_BASE + 0x000C))
- #define rVIC1INTENABLE (*(volatile unsigned int *)(VIC1_BASE + 0x0010))
- #define rVIC1INTENCLEAR (*(volatile unsigned int *)(VIC1_BASE + 0x0014))
- #define rVIC1VECTADDR (VIC1_BASE + 0x100)
- #define rVIC1ADDRESS (*(volatile unsigned int *)(VIC1_BASE + 0x0F00))
-
- //VIC2 register
-
- #define rVIC2IRQSTATUS (*(volatile unsigned int *)(VIC2_BASE + 0x0000))
- #define rVIC2FIQSTATUS (*(volatile unsigned int *)(VIC2_BASE + 0x0004))
- #define rVIC2INTSELECT (*(volatile unsigned int *)(VIC2_BASE + 0x000C))
- #define rVIC2INTENABLE (*(volatile unsigned int *)(VIC2_BASE + 0x0010))
- #define rVIC2INTENCLEAR (*(volatile unsigned int *)(VIC2_BASE + 0x0014))
- #define rVIC2VECTADDR (VIC2_BASE + 0x100)
- #define rVIC2ADDRESS (*(volatile unsigned int *)(VIC2_BASE + 0x0F00))
-
- //VIC3 register
-
- #define rVIC3IRQSTATUS (*(volatile unsigned int *)(VIC3_BASE + 0x0000))
- #define rVIC3FIQSTATUS (*(volatile unsigned int *)(VIC3_BASE + 0x0004))
- #define rVIC3INTSELECT (*(volatile unsigned int *)(VIC3_BASE + 0x000C))
- #define rVIC3INTENABLE (*(volatile unsigned int *)(VIC3_BASE + 0x0010))
- #define rVIC3INTENCLEAR (*(volatile unsigned int *)(VIC3_BASE + 0x0014))
- #define rVIC3VECTADDR (VIC3_BASE + 0x100)
- #define rVIC3ADDRESS (*(volatile unsigned int *)(VIC3_BASE + 0x0F00))
-
- //interrupt vector table
-
- #define vector_table_base 0xD0037400
-
- #define reset_vector (vector_table_base + 0x00)
- #define undef_vector (vector_table_base + 0x04)
- #define sotf_interrupt_vector (vector_table_base + 0x08)
- #define prefetch_vector (vector_table_base + 0x0C)
- #define data_vector (vector_table_base + 0x10)
- #define irq_vector (vector_table_base + 0x18)
- #define fiq_vector (vector_table_base + 0x1C)
-
- #define r_reset_vector (*(volatile unsigned int *) reset_vector)
- #define r_undef_vector (*(volatile unsigned int *) undef_vector)
- #define r_sotf_interrupt_vector (*(volatile unsigned int *) sotf_interrupt_vector)
- #define r_prefetch_vector (*(volatile unsigned int *) prefetch_vector)
- #define r_data_vector (*(volatile unsigned int *) data_vector)
- #define r_irq_vector (*(volatile unsigned int *) irq_vector)
- #define r_fiq_vector (*(volatile unsigned int *) fiq_vector)
-
- //interrupt number
-
- #define NUM_TIMER0 (21)
- #define NUM_TIMER1 (22)
- #define NUM_TIMER2 (23)
- #define NUM_TIMER3 (24)
- #define NUM_TIMER4 (25)
- #define NUM_SYSTIMER (26)
- #define NUM_WDT (27)
- #define NUM_RTC_ALARM (28)
- #define NUM_RTC_TICK (29)
-
- //rtc interrupt func
-
- //rtc func
-
- static void isr_rtc_alarm()
- {
- static int num = 0;
- printf("rtc interrupt, num = %d...",num++);
- //open rtc alarm interrupt
- rINTP |= (1<<1);
-
- //clear VIC0ADDR,clear using interrupt process
- rVIC0ADDRESS = 0;
- rVIC1ADDRESS = 0;
- rVIC2ADDRESS = 0;
- rVIC3ADDRESS = 0;
- }
-
- static unsigned int num_2_bcd(unsigned int num)
- {
- return (((num / 10)<< 4) | (num % 10));
- }
-
- static unsigned int bcd_2_num(unsigned int bcd)
- {
- return ((((bcd & (0xf0)) >> 4) *10) + (bcd & (0x0f)) );
- }
-
- void set_rtc_time(struct rtc_time *p)
- {
- //set RTCCON,open RTC
- rRTCCON |= 1;
-
- //set year month date,hour min,sec,day
- rBCDYEAR = num_2_bcd(p->year - 2000);
- rBCDMON = num_2_bcd(p->month);
- rBCDDATE = num_2_bcd(p->date);
- rBCDHOUR = num_2_bcd(p->hour);
- rBCDMIN = num_2_bcd(p->minute);
- rBCDSEC = num_2_bcd(p->second);
- rBCDDAY = num_2_bcd(p->day);
-
- //set RTCCON,close RTC
- rRTCCON &= ~(1);
- }
-
- void get_rtc_time(struct rtc_time *p)
- {
- //set RTCCON,open RTC
- rRTCCON |= 1;
-
- //get year month date,hour min,sec,day
- p->year = bcd_2_num(rBCDYEAR) + 2000;
- p->month = bcd_2_num(rBCDMON);
- p->date = bcd_2_num(rBCDDATE);
- p->hour = bcd_2_num(rBCDHOUR);
- p->minute = bcd_2_num(rBCDMIN);
- p->second = bcd_2_num(rBCDSEC);
- p->day = bcd_2_num(rBCDDAY);
- //set RTCCON,close RTC
- rRTCCON &= ~(1);
- }
-
- void rtc_alarm()
- {
- //set alarm pre 10 trigger
- rALMSEC = num_2_bcd(10);
- //set sec used
- rRTCALM |= 1<<0;
- //set alarm enable
- rRTCALM |= 1<<6;
- }
-
-
- //inner interrupt func
-
- static void reset_func()
- {
- printf("reset\n");
- }
-
- static void undef_func()
- {
- printf("undef\n");
- }
-
- static void sotf_interrupt_func()
-
- {
- printf("sotf_intrrupt\n");
- }
-
- static void prefetch_func()
- {
- printf("prefetch\n");
- }
-
- static void data_func()
- {
- printf("data\n");
- }
-
- static void fiq_func()
- {
- printf("irq\n");
- }
-
- void IRQ_handler();
-
- static void bind_isr_VICnINTENCLEAR(unsigned long num,void (*handler)())
- {
- if(num <32)
- {
- printf("bind ok\n");
- *((volatile unsigned int *)(rVIC0VECTADDR + 4 * (num))) = (unsigned)handler;
- }
- else if(num < 64)
- {
- *((volatile unsigned int *)(rVIC0VECTADDR + 4 * (num-32))) = (unsigned)handler;
- }
- else if(num < 96)
- {
- *((volatile unsigned int *)(rVIC0VECTADDR + 4 * (num-64))) = (unsigned)handler;
- }
- else
- {
- *((volatile unsigned int *)(rVIC0VECTADDR + 4 * (num-96))) = (unsigned)handler;
- }
- }
-
- static void enable_interrupt(unsigned long num)
- {
- unsigned long tmp;
-
- if(num < 32)
- {
- tmp = rVIC0INTENABLE;
- tmp |= (1<<num);
- rVIC0INTENABLE = tmp;
- }
- else if(num < 64)
- {
- tmp = rVIC0INTENABLE;
- tmp |= (1<<(num-32));
- rVIC1INTENABLE = tmp;
- }
- else if(num < 96)
- {
- tmp = rVIC0INTENABLE;
- tmp |= (1<<(num-64));
- rVIC2INTENABLE = tmp;
- }
- else if(num < 200)
- {
- tmp = rVIC0INTENABLE;
- tmp |= (1<<(num-96));
- rVIC3INTENABLE = tmp;
- }
- else
- {
- rVIC0INTENABLE = 0xffffffff;
- rVIC1INTENABLE = 0xffffffff;
- rVIC2INTENABLE = 0xffffffff;
- rVIC3INTENABLE = 0xffffffff;
- }
- }
-
- void init_inner_interrupt()
- {
- //bind interrupt process on interrupt vector table
- r_reset_vector = (unsigned int)reset_func;
- r_undef_vector = (unsigned int)undef_func;
- r_sotf_interrupt_vector = (unsigned int)sotf_interrupt_func;
- r_prefetch_vector = (unsigned int)prefetch_func;
- r_data_vector = (unsigned int)data_func;
- r_irq_vector = (unsigned int)IRQ_handler;
- r_fiq_vector = (unsigned int)fiq_func;
-
- //select interrupt mode(irq)
- rVIC0INTSELECT = 0x0;
- rVIC1INTSELECT = 0x0;
- rVIC2INTSELECT = 0x0;
- rVIC3INTSELECT = 0x0;
-
- //diasble interrupt
- rVIC0INTENCLEAR = 0xffffffff;
- rVIC1INTENCLEAR = 0xffffffff;
- rVIC2INTENCLEAR = 0xffffffff;
- rVIC3INTENCLEAR = 0xffffffff;
-
- //clear interrupt process address
- rVIC0ADDRESS = 0;
- rVIC1ADDRESS = 0;
- rVIC2ADDRESS = 0;
- rVIC3ADDRESS = 0;
-
- //bind isr process on VICnINTENCLEAR
- bind_isr_VICnINTENCLEAR(NUM_RTC_ALARM,isr_rtc_alarm);
-
- //enable interrupt
- enable_interrupt(NUM_RTC_ALARM);
- }
-
- //judge inner interrupt ,get interrupt occure in which VICnVECTADDR
- void irq_handler()
- {
- volatile unsigned int n = 0;
- void (*isr)(void) = NULL;
- for(n = 0;n <4;n++)
- {
- if(n == 0 && rVIC0IRQSTATUS != 0)
- {
- isr = (void (*)(void))rVIC0ADDRESS;
- }
- else if(n == 1 && rVIC1IRQSTATUS != 0)
- {
- isr = (void (*)(void))rVIC1ADDRESS;
- }
- else if(n == 2 && rVIC2IRQSTATUS != 0)
- {
- isr = (void (*)(void))rVIC2ADDRESS;
- }
- else if(n == 3 && rVIC3IRQSTATUS != 0)
- {
- isr = (void (*)(void))rVIC3ADDRESS;
- }
- (*isr)();
- }
- }
link.lds
- SECTIONS
- {
- . = 0xd0020010;
-
- .text :
- {
- start.o
- *(.text)
- }
-
- .data :
- {
- *(.data)
- }
-
- .bss :
- {
- *(.bss)
- }
- }
Makefile
- CC = arm-linux-gcc
- LD = arm-linux-ld
- OBJCOPY = arm-linux-objcopy
- OBJDUMP = arm-linux-objdump
-
- INCDIR := $(shell pwd)
-
- #预处理器的flag,flag就是编译器可选的选项
- CPPFLAGS := -nostdlib -nostdinc -I$(INCDIR)/include
- #C编译器的flag
- CFLAGS := -Wall -O2 -fno-builtin
-
- export CC LD OBJCOPY OBJDUMP CPPFLAGS CFLAGS
-
- objs := start.o uart_printf.o main.o rtc_alarm.o
- objs += lib/libc.a
-
- led.bin:$(objs)
- $(LD) -Tlink.lds -o rtc_alarm.elf $^
- $(OBJCOPY) -O binary rtc_alarm.elf rtc_alarm.bin
- $(OBJDUMP) -D rtc_alarm.elf > rtc_alarm.dis
- gcc mkv210.c -o mkv210
- ./mkv210 rtc_alarm.bin sd.bin
-
- lib/libc.a:
- cd lib; make; cd ..
-
- %.o:%.S
- $(CC) $(CPPFLAGS) $(CFLAGS) -o $@ $< -c
-
- %.o:%.c
- $(CC) $(CPPFLAGS) $(CFLAGS) -o $@ $< -c
-
- clean:
- rm *.o *.elf *.bin *.dis mkv210 -f
- cd lib; make clean; cd ..
结果示例:
