S5PV210裸机(五):定时器

news2024/10/7 20:35:34

        本文主要探讨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 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)

//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<<8);

        //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;
}
 
//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 ..

结果示例: 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1121256.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Python 安装CSF(布料模拟滤波)的环境配置

一、环境配置 1.1 下载源码: Github下载CSF库源码 1.2 解压文件如下: 二、安装CSF库 2.1在解压文件中找到python文件夹所在目录 2.2 输入cmd并回车,来打开终端窗口 2.3激活虚拟环境 通过: activate +你的虚拟环境名称。来激活安装CSF库的虚拟环境。【不执行此

k8s镜像加devops

展示 1.配套资料2.devops 3.elk日志收集 4.grafana监控 5.dashboard![在这里插入图片描述](https://img-blog.csdnimg.cn/bf294f9fd98e4c038858a6bf5c34dbdc.png 目的 学习k8s来来回回折腾很久了&#xff0c;光搭个环境就能折腾几天。这次工作需要终于静下心来好好学习了一…

【USMA】N1CTF2022-praymoon

前言 本题主要利用 USMA 解题&#xff0c;当然还有其他做法&#xff0c;暂时不表 程序分析 启动脚本就不看了&#xff0c;该开的保护都开了。看下文件系统初始化脚本&#xff1a; #!/bin/shmkdir /tmp mount -t proc none /proc mount -t sysfs none /sys mount -t devtmpf…

codeforces (C++ Haunted House)

题目&#xff1a; 翻译&#xff1a; 思路&#xff1a; 1、由题目可知&#xff0c;他想让我们判断交换相邻字符位置后将二进制转为十进制后&#xff0c;能否整除2的次方。能整除即输出需要交换的次数&#xff0c;不能则输出-1。&#xff08;例&#xff1a;输入3和010这组数据就…

二分查找:如何快速定位IP对应的省份地址?

文章来源于极客时间前google工程师−王争专栏。 通过IP地址查找IP归属地功能&#xff1a; 这个功能是通过维护一个很大的IP地址库来实现。地址库中包含IP地址范围和归属地的对应关系。 当我们查询202.201.133.13这个IP地址归属地时&#xff0c;在地址库中搜索&#xff0c;这个…

真实感受:是智能家居在选择合适的技术!

科技从来都是为了让我们的生活更加的简单、舒适&#xff0c;而智能家居的智能&#xff0c;体现在如何更更更方便的使用我需要控制的家居。 例如&#xff1a;下班躺在床上想休息&#xff0c;房间和大厅的灯还开着&#xff0c;这时你会选择什么产品躺着解决问题&#xff1f; 红外…

【MySQL】逻辑架构

逻辑架构 逻辑架构剖析服务器处理客户端请求连接层服务层SQL Interface : SQL接口Parser : 解析器Optimizer : 查询优化器Caches&Buffers : 查询缓存组件 引擎层存储层 SQL执行流程MySQL查询流程查询缓存解析器词法分析语法分析 优化器执行器 数据库缓冲池 逻辑架构剖析 服…

云安全—责任共担

0x00 前言 云安全的职责范围实际上一直遵循的是&#xff0c;谁提供谁负责&#xff0c;如果交付给云消费者的时候&#xff0c;交付者使用过程中就要自行负责&#xff0c;也就是我们经常遇到的配置不当等问题&#xff0c;在三层服务模式中&#xff0c;责任互相嵌套&#xff0c;最…

软件测试(五)自动化 selenium

文章目录 自动化测试单元测试&#xff1a;单元测试&#xff1a;UI自动化 selenium工具定义特点&#xff1a;原理&#xff1a;seleniumjava环境搭建SeleniumAPI获取测试结果&#xff1a;添加等待浏览器操作键盘事件鼠标事件多层框架/窗口定位下拉框处理弹窗处理上传文件操作关闭…

10种常用基础模块电路,电子控制不再是难题!

你是否曾经为电子控制中的复杂电路而烦恼&#xff1f; 现在&#xff0c;我将向你展示10个最具实用性和普遍性的模块电路图&#xff0c;让你轻松掌握电子控制的核心技术&#xff01; 这些电路图不仅简单易懂&#xff0c;而且非常具有趣味性&#xff1a; 1、RS232通讯电路&…

Java面试——RPC协议

涉及到分布式方面知识的话&#xff0c;RPC协议是逃不开的&#xff0c;所以在此记录一下RPC协议。 什么是RPC协议 RPC协议&#xff08;Remote Procedure Call&#xff09;远程过程调用&#xff0c;简单的来说&#xff1a;RPC协议是一种通过网络从远程计算机程序获取服务的协议…

【unity小技巧】实现无限滚动视图和类似CSGO的开箱抽奖功能及Content Size Fitter组件的使用介绍

文章目录 一篇一句前言素材一、无限滚动视图1. 绘制视图2. Content Size Fitter是布局控件&#xff08;1&#xff09;在文本框中使用&#xff08;2&#xff09;控制Scroll View(Scroll Rect组件)控件下Content的大小 3. 控制视图无限滚动4. 向右拉无限滚动5. 修复滚动视图一卡一…

julia笔记:字符和字符串

1 字符 Char类型的值代表单个字符 ca #a: ASCII/Unicode U0061 (category Ll: Letter, lowercase)typeof(c) #Char 将 Char 转换为其对应的整数值&#xff0c;即 Unicode 代码 cInt(c) c #97typeof(c) #Int64 将一个整数值&#xff08;Unicaode&#xff09;转回 Char Cha…

杂谈:DC对Verilog和SystemVerilog语言的支持

DC对Verilog和SystemVerilog语言的支持 设计语言用哪种&#xff1f;Design Compiler对二者的支持简单的fsm电路测试测试结果对比写在最后 设计语言用哪种&#xff1f; 直接抛出结论&#xff1a;先有电路&#xff0c;后为描述。设计端而言&#xff0c;没有语言的高低好坏&#…

IMX6ULL板开发——第一个应用程序

实现第一个应用程序&#xff1a;在IMX6ULL开发板上运行程序hello.c #include <stdio.h>/* 执行命令: ./hello weidongshan* argc 2* argv[0] ./hello* argv[1] weidongshan*/int main(int argc, char **argv) {if (argc > 2)printf("Hello, %s!\n", arg…

ASRPRO语音识别模块

ASRPRO语音识别模块 SOFT IIC 与PCA9685模块通信 pca9685 iic通信 地址位 ADDR<<1|0 左移一位 #define I2C_WRITE 0 #define I2C_READ 1 否则通信地址错误 asrpro 通过UART与电脑连接&#xff0c;可以进行简单的交互 将STM32作为接口扩展&#xff0c;通过SPI或I…

【RNA folding】RNA折叠算法与生物物理约束

文章目录 RNA折叠RNA folding representation1 DP for simple folds1.1 Nussinov Algorithm objective1.2 energy constraints1.3 The key idea of the algorithm 2 DP for stacking and complex foldsStochastic context free grammars 来自Manolis Kellis教授&#xff08;MIT…

JavaSE入门---掌握抽象类和接口

文章目录 抽象类什么是抽象类&#xff1f;抽象类语法抽象类特性 接口什么是接口&#xff1f;接口语法接口使用接口特性实现多个接口接口间的继承 抽象类 VS 接口Java中的 Clonable 接口Java中的 Object 类 抽象类 什么是抽象类&#xff1f; 在面向对象的概念中&#xff0c;所…

Linux编译器-gcc/g++使用函数库

【Linux】系列文章目录 【Linux】基础常见指令&#xff1a;http://t.csdn.cn/hwLPb 【Linux】基本权限&#xff1a;http://t.csdn.cn/faFZg 【Linux】软件包管理器yum与环境开发工具vim&#xff1a;http://t.csdn.cn/LEqkm 目录 【Linux】系列文章目录 前言 一、gcc选项总…

【C语言】malloc()函数详解(动态内存开辟函数)

一.malloc()函数简介 我们先来看一下cplusplus.com - The C Resources Network网站上malloc()函数的基本信息&#xff1a; 1.函数功能 可以看到,malloc()函数的功能是:向内存申请一块连续可用的空间,并返回指向块开头的指针. 2.函数参数 该函数有1个参数,是: void* malloc (…