• S5PV210裸机(五):定时器


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

    1. #define WTCON 0xE2700000
    2. #define SVC_STACK 0xd0037d80
    3. .global _start
    4. .global IRQ_handler
    5. _start:
    6. //close watchDog
    7. ldr r0,=WTCON
    8. ldr r1,=0x0
    9. str r1,[r0]
    10. //init SVC stack
    11. ldr sp,=SVC_STACK
    12. //init icache
    13. mrc p15,0,r0,c1,c0,0
    14. bic r0,r0,#(1<<12) //close icache
    15. orr r0,r0,#(1<<12) //open icache
    16. mcr p15,0,r0,c1,c0,0
    17. //use func
    18. bl main

    main.c 

    1. #include "pwn_buzzer.h"
    2. static void dealy_time()
    3. {
    4. volatile unsigned int i = 900000;
    5. while(i--);
    6. }
    7. int main()
    8. {
    9. pwn_buzzer_timer_init();
    10. while(1)
    11. {
    12. dealy_time();
    13. }
    14. return 0;
    15. }

     pwn_buzzer.h

    void pwn_buzzer_timer_init();

     pwn_buzzer.c

    1. #define GPD0CON 0xE02000A0
    2. #define TCFG0 0xE2500000
    3. #define TCFG1 0xE2500004
    4. #define TCON 0xE2500008
    5. #define TCNTB2 0xE2500024
    6. #define TCMPB2 0xE2500028
    7. #define rGPD0CON (*(volatile unsigned int *) GPD0CON)
    8. #define rTCFG0 (*(volatile unsigned int *) TCFG0)
    9. #define rTCFG1 (*(volatile unsigned int *) TCFG1)
    10. #define rTCON (*(volatile unsigned int *) TCON)
    11. #define rTCNTB0 (*(volatile unsigned int *) TCNTB2)
    12. #define rTCMPB2 (*(volatile unsigned int *) TCMPB2)
    13. void pwn_buzzer_timer_init()
    14. {
    15. //set gpio as buzzer
    16. rGPD0CON &= ~(0x0f << 8);
    17. rGPD0CON |= (2 << 8);
    18. //set Prescaler as 65,real Prescaleris 66,Prescaler is 66Mhz /66 = 1Mhz
    19. rTCFG0 &= ~(0xff<<8);
    20. rTCFG0 = (65<<8);
    21. //set div ,set div is 2 that mean 1/2,so 1Mhz /2 = 500000hz = 2us
    22. rTCFG1 &= ~(0x0f<<8);
    23. rTCFG1 = (1<<8);
    24. //set TCON,set Auto Reload open
    25. rTCON = (1<<15);
    26. //set TCNTB0,set the count of cycle
    27. //rTCNTB0 = time you need / set div
    28. //ex: 1ms / 2us = 500
    29. rTCNTB0 = 500;
    30. //set TCMPB2,set the rate of duty,mean the rate of high and low level on all cycle
    31. rTCMPB2 = 250;
    32. //set TCON,when firstly open timer that you Manual Refresh TCNTB0 to TCNT
    33. rTCON |= (1<<13);
    34. //after Manual Refresh,close Manual Refresh,then always Auto Reload
    35. rTCON &= ~(1<<13);
    36. //set TCON,open timer
    37. rTCON |= (1<<12);
    38. }

    Makefile 

    1. CC = arm-linux-gcc
    2. LD = arm-linux-ld
    3. OBJCOPY = arm-linux-objcopy
    4. OBJDUMP = arm-linux-objdump
    5. #预处理器的flag,flag就是编译器可选的选项
    6. CPPFLAGS := -nostdlib -nostdinc
    7. #C编译器的flag
    8. CFLAGS := -Wall -O2 -fno-builtin
    9. export CC LD OBJCOPY OBJDUMP CPPFLAGS CFLAGS
    10. objs := start.o main.o pwn_buzzer.o
    11. led.bin:$(objs)
    12. $(LD) -Ttext 0x0 -o buzzer.elf $^
    13. $(OBJCOPY) -O binary buzzer.elf buzzer.bin
    14. $(OBJDUMP) -D buzzer.elf > buzzer.dis
    15. gcc mkv210.c -o mkv210
    16. ./mkv210 buzzer.bin sd.bin
    17. %.o:%.S
    18. $(CC) $(CPPFLAGS) $(CFLAGS) -o $@ $< -c
    19. %.o:%.c
    20. $(CC) $(CPPFLAGS) $(CFLAGS) -o $@ $< -c
    21. clean:
    22. rm *.o *.elf *.bin *.dis mkv210 -f

    demo2:

            看门狗中断

    start.S

    1. #define WTCON 0xE2700000
    2. #define SVC_STACK 0xd0037d80
    3. #define IRQ_STACK 0xd0037f80
    4. .global _start
    5. .global IRQ_handler
    6. _start:
    7. //close watchDog
    8. ldr r0,=WTCON
    9. ldr r1,=0x0
    10. str r1,[r0]
    11. //init SVC stack
    12. ldr sp,=SVC_STACK
    13. //init icache
    14. mrc p15,0,r0,c1,c0,0
    15. bic r0,r0,#(1<<12) //close icache
    16. orr r0,r0,#(1<<12) //open icache
    17. mcr p15,0,r0,c1,c0,0
    18. //use func
    19. bl main
    20. b .
    21. //all interrupt process:Protect the scene + mian iqr process + return scene
    22. IRQ_handler:
    23. //init IRQ_STACK
    24. ldr sp, =IRQ_STACK
    25. //protect lr
    26. sub lr, lr, #4
    27. //protect r0--r12 that in irq stack
    28. stmfd sp!, {r0-r12, lr}
    29. //mian iqr process
    30. bl irq_handler
    31. //return scene
    32. ldmfd sp!, {r0-r12, pc}^

    main.c 

    1. #include "uart_printf.h"
    2. #include "wdt_interrupt.h"
    3. #include "stdio.h"
    4. static void dealy_time()
    5. {
    6. volatile unsigned int i = 1000000;
    7. while(i--);
    8. }
    9. int main()
    10. {
    11. //init uart
    12. init_uart();
    13. printf("init uart over\n");
    14. //init outer interupt
    15. printf("init wdt\n");
    16. wdt_interrupt();
    17. //init inner interupt
    18. printf("init inner\n");
    19. init_inner_interrupt();
    20. //dealy time
    21. while(1)
    22. {
    23. printf("..");
    24. dealy_time();
    25. }
    26. return 0;
    27. }

            uart_printf.h 

    void init_uart();

          uart_printf.c

    1. #define GPA0CON 0xE0200000
    2. #define ULCON0 0xE2900000
    3. #define UCON0 0xE2900004
    4. #define UFCON0 0xE2900008
    5. #define UMCON0 0xE290000C
    6. #define UTRSTAT0 0xE2900010
    7. #define UTXH0 0xE2900020
    8. #define URXH0 0xE2900024
    9. #define UBRDIV0 0xE2900028
    10. #define UDIVSLOT0 0xE290002C
    11. #define rGPA0CON (*(volatile unsigned int *)GPA0CON)
    12. #define rULCON0 (*(volatile unsigned int *)ULCON0)
    13. #define rUCON0 (*(volatile unsigned int *)UCON0)
    14. #define rUFCON0 (*(volatile unsigned int *)UFCON0)
    15. #define rUMCON0 (*(volatile unsigned int *)UMCON0)
    16. #define rUTRSTAT0 (*(volatile unsigned int *)UTRSTAT0)
    17. #define rUTXH0 (*(volatile unsigned int *)UTXH0)
    18. #define rURXH0 (*(volatile unsigned int *)URXH0)
    19. #define rUBRDIV0 (*(volatile unsigned int *)UBRDIV0)
    20. #define rUDIVSLOT0 (*(volatile unsigned int *)UDIVSLOT0)
    21. //init uart
    22. void init_uart()
    23. {
    24. //set gpio as uart(rx,tx)
    25. rGPA0CON &= ~(0xff);
    26. rGPA0CON |= ((1<<2)|(1<<5));
    27. //set uart base configure(mode)
    28. rULCON0 = 0x3;
    29. rUCON0 = 0x5;
    30. rUMCON0 = 0;
    31. rUFCON0 = 0;
    32. //set uart baud
    33. //DIV_VAL = (PCLK / (bps x 16))-1
    34. //(66000000 /(115200 * 16)) -1 = 34.8
    35. rUBRDIV0 = 34;
    36. //set uart baud calibration
    37. //0.8 * 16 = 13,check 210 table
    38. rUDIVSLOT0 = 0xdfdd;
    39. }
    40. //send data
    41. void putc(char data)
    42. {
    43. while (!(rUTRSTAT0 & (1<<1)));
    44. rUTXH0 = data;
    45. }
    46. //receive data
    47. char getc()
    48. {
    49. while (!(rUTRSTAT0 & (1<<0)));
    50. return (rURXH0 & 0xff);
    51. }

            wdt_interrupt.h 

    1. void wdt_interrupt();
    2. void init_inner_interrupt()

            wdt_interrupt.c

       

    1. #include "stdio.h"
    2. //watchDog interrupt register
    3. #define WTCON 0xE2700000
    4. #define WTDAT 0xE2700004
    5. #define WTCNT 0xE2700008
    6. #define WTCLRINT 0xE270000C
    7. #define rWTCON *((volatile unsigned int *) WTCON)
    8. #define rWTDAT *((volatile unsigned int *) WTDAT)
    9. #define rWTCNT *((volatile unsigned int *) WTCNT)
    10. #define rWTCLRINT *((volatile unsigned int *) WTCLRINT)
    11. //inner interrupt register
    12. //VIC base address
    13. #define VIC0_BASE 0xF2000000
    14. #define VIC1_BASE 0xF2100000
    15. #define VIC2_BASE 0xF2200000
    16. #define VIC3_BASE 0xF2300000
    17. //VIC0 register
    18. #define rVIC0IRQSTATUS (*(volatile unsigned int *)(VIC0_BASE + 0x0000))
    19. #define rVIC0FIQSTATUS (*(volatile unsigned int *)(VIC0_BASE + 0x0004))
    20. #define rVIC0INTSELECT (*(volatile unsigned int *)(VIC0_BASE + 0x000C))
    21. #define rVIC0INTENABLE (*(volatile unsigned int *)(VIC0_BASE + 0x0010))
    22. #define rVIC0INTENCLEAR (*(volatile unsigned int *)(VIC0_BASE + 0x0014))
    23. #define rVIC0VECTADDR (VIC0_BASE + 0x100)
    24. #define rVIC0ADDRESS (*(volatile unsigned int *)(VIC0_BASE + 0x0F00))
    25. //VIC1 register
    26. #define rVIC1IRQSTATUS (*(volatile unsigned int *)(VIC1_BASE + 0x0000))
    27. #define rVIC1FIQSTATUS (*(volatile unsigned int *)(VIC1_BASE + 0x0004))
    28. #define rVIC1INTSELECT (*(volatile unsigned int *)(VIC1_BASE + 0x000C))
    29. #define rVIC1INTENABLE (*(volatile unsigned int *)(VIC1_BASE + 0x0010))
    30. #define rVIC1INTENCLEAR (*(volatile unsigned int *)(VIC1_BASE + 0x0014))
    31. #define rVIC1VECTADDR (VIC1_BASE + 0x100)
    32. #define rVIC1ADDRESS (*(volatile unsigned int *)(VIC1_BASE + 0x0F00))
    33. //VIC2 register
    34. #define rVIC2IRQSTATUS (*(volatile unsigned int *)(VIC2_BASE + 0x0000))
    35. #define rVIC2FIQSTATUS (*(volatile unsigned int *)(VIC2_BASE + 0x0004))
    36. #define rVIC2INTSELECT (*(volatile unsigned int *)(VIC2_BASE + 0x000C))
    37. #define rVIC2INTENABLE (*(volatile unsigned int *)(VIC2_BASE + 0x0010))
    38. #define rVIC2INTENCLEAR (*(volatile unsigned int *)(VIC2_BASE + 0x0014))
    39. #define rVIC2VECTADDR (VIC2_BASE + 0x100)
    40. #define rVIC2ADDRESS (*(volatile unsigned int *)(VIC2_BASE + 0x0F00))
    41. //VIC3 register
    42. #define rVIC3IRQSTATUS (*(volatile unsigned int *)(VIC3_BASE + 0x0000))
    43. #define rVIC3FIQSTATUS (*(volatile unsigned int *)(VIC3_BASE + 0x0004))
    44. #define rVIC3INTSELECT (*(volatile unsigned int *)(VIC3_BASE + 0x000C))
    45. #define rVIC3INTENABLE (*(volatile unsigned int *)(VIC3_BASE + 0x0010))
    46. #define rVIC3INTENCLEAR (*(volatile unsigned int *)(VIC3_BASE + 0x0014))
    47. #define rVIC3VECTADDR (VIC3_BASE + 0x100)
    48. #define rVIC3ADDRESS (*(volatile unsigned int *)(VIC3_BASE + 0x0F00))
    49. //interrupt vector table
    50. #define vector_table_base 0xD0037400
    51. #define reset_vector (vector_table_base + 0x00)
    52. #define undef_vector (vector_table_base + 0x04)
    53. #define sotf_interrupt_vector (vector_table_base + 0x08)
    54. #define prefetch_vector (vector_table_base + 0x0C)
    55. #define data_vector (vector_table_base + 0x10)
    56. #define irq_vector (vector_table_base + 0x18)
    57. #define fiq_vector (vector_table_base + 0x1C)
    58. #define r_reset_vector (*(volatile unsigned int *) reset_vector)
    59. #define r_undef_vector (*(volatile unsigned int *) undef_vector)
    60. #define r_sotf_interrupt_vector (*(volatile unsigned int *) sotf_interrupt_vector)
    61. #define r_prefetch_vector (*(volatile unsigned int *) prefetch_vector)
    62. #define r_data_vector (*(volatile unsigned int *) data_vector)
    63. #define r_irq_vector (*(volatile unsigned int *) irq_vector)
    64. #define r_fiq_vector (*(volatile unsigned int *) fiq_vector)
    65. //interrupt number
    66. #define NUM_TIMER0 (21)
    67. #define NUM_TIMER1 (22)
    68. #define NUM_TIMER2 (23)
    69. #define NUM_TIMER3 (24)
    70. #define NUM_TIMER4 (25)
    71. #define NUM_SYSTIMER (26)
    72. #define NUM_WDT (27)
    73. #define NUM_RTC_ALARM (28)
    74. #define NUM_RTC_TICK (29)
    75. //wdt interrupt func
    76. void wdt_interrupt()
    77. {
    78. //set WTCON,set Prescaler,Prescaler is set value + 1
    79. //Prescaler = 65 + 1 = 66,66Mhz / 66 = 1Mhz = 1000000hz
    80. rWTCON &= ~(0xff << 8);
    81. rWTCON |= (65<<8);
    82. //set div is 128,t = 1/(1000000hz /128) = 1.28us
    83. rWTCON &= ~(3 << 3);
    84. rWTCON |= (3<<3);
    85. //set WTCON,open interrupt and close reset
    86. rWTCON |= (1<<2);
    87. rWTCON &= ~(1);
    88. //set WTDAT,set set the time form firstly open timer to count open(WTCNT)
    89. rWTDAT = 1000;
    90. rWTCNT = 1000;
    91. //open wdt
    92. rWTCON |= (1<<5);
    93. }
    94. //dealy_time
    95. static void dealy_time()
    96. {
    97. volatile unsigned int i = 1000000;
    98. while(i--);
    99. }
    100. //outer interrupt key func
    101. static void isr_wdt()
    102. {
    103. static int num = 0;
    104. printf("wdt interrupt,num = %d\n",num++);
    105. dealy_time();
    106. //clear VIC0ADDR,clear using interrupt process
    107. rVIC0ADDRESS = 0;
    108. rVIC1ADDRESS = 0;
    109. rVIC2ADDRESS = 0;
    110. rVIC3ADDRESS = 0;
    111. rWTCLRINT = 1;
    112. }
    113. //inner interrupt func
    114. static void reset_func()
    115. {
    116. printf("reset\n");
    117. }
    118. static void undef_func()
    119. {
    120. printf("undef\n");
    121. }
    122. static void sotf_interrupt_func()
    123. {
    124. printf("sotf_intrrupt\n");
    125. }
    126. static void prefetch_func()
    127. {
    128. printf("prefetch\n");
    129. }
    130. static void data_func()
    131. {
    132. printf("data\n");
    133. }
    134. static void fiq_func()
    135. {
    136. printf("irq\n");
    137. }
    138. void IRQ_handler();
    139. static void bind_isr_VICnINTENCLEAR(unsigned long num,void (*handler)())
    140. {
    141. if(num <32)
    142. {
    143. printf("bind ok\n");
    144. *((volatile unsigned int *)(rVIC0VECTADDR + 4 * (num))) = (unsigned)handler;
    145. }
    146. else if(num < 64)
    147. {
    148. *((volatile unsigned int *)(rVIC0VECTADDR + 4 * (num-32))) = (unsigned)handler;
    149. }
    150. else if(num < 96)
    151. {
    152. *((volatile unsigned int *)(rVIC0VECTADDR + 4 * (num-64))) = (unsigned)handler;
    153. }
    154. else
    155. {
    156. *((volatile unsigned int *)(rVIC0VECTADDR + 4 * (num-96))) = (unsigned)handler;
    157. }
    158. }
    159. static void enable_interrupt(unsigned long num)
    160. {
    161. unsigned long tmp;
    162. if(num < 32)
    163. {
    164. tmp = rVIC0INTENABLE;
    165. tmp |= (1<<num);
    166. rVIC0INTENABLE = tmp;
    167. }
    168. else if(num < 64)
    169. {
    170. tmp = rVIC0INTENABLE;
    171. tmp |= (1<<(num-32));
    172. rVIC1INTENABLE = tmp;
    173. }
    174. else if(num < 96)
    175. {
    176. tmp = rVIC0INTENABLE;
    177. tmp |= (1<<(num-64));
    178. rVIC2INTENABLE = tmp;
    179. }
    180. else if(num < 200)
    181. {
    182. tmp = rVIC0INTENABLE;
    183. tmp |= (1<<(num-96));
    184. rVIC3INTENABLE = tmp;
    185. }
    186. else
    187. {
    188. rVIC0INTENABLE = 0xffffffff;
    189. rVIC1INTENABLE = 0xffffffff;
    190. rVIC2INTENABLE = 0xffffffff;
    191. rVIC3INTENABLE = 0xffffffff;
    192. }
    193. }
    194. void init_inner_interrupt()
    195. {
    196. //bind interrupt process on interrupt vector table
    197. r_reset_vector = (unsigned int)reset_func;
    198. r_undef_vector = (unsigned int)undef_func;
    199. r_sotf_interrupt_vector = (unsigned int)sotf_interrupt_func;
    200. r_prefetch_vector = (unsigned int)prefetch_func;
    201. r_data_vector = (unsigned int)data_func;
    202. r_irq_vector = (unsigned int)IRQ_handler;
    203. r_fiq_vector = (unsigned int)fiq_func;
    204. //select interrupt mode(irq)
    205. rVIC0INTSELECT = 0x0;
    206. rVIC1INTSELECT = 0x0;
    207. rVIC2INTSELECT = 0x0;
    208. rVIC3INTSELECT = 0x0;
    209. //diasble interrupt
    210. rVIC0INTENCLEAR = 0xffffffff;
    211. rVIC1INTENCLEAR = 0xffffffff;
    212. rVIC2INTENCLEAR = 0xffffffff;
    213. rVIC3INTENCLEAR = 0xffffffff;
    214. //clear interrupt process address
    215. rVIC0ADDRESS = 0;
    216. rVIC1ADDRESS = 0;
    217. rVIC2ADDRESS = 0;
    218. rVIC3ADDRESS = 0;
    219. //bind isr process on VICnINTENCLEAR
    220. bind_isr_VICnINTENCLEAR(NUM_WDT,isr_wdt);
    221. //enable interrupt
    222. enable_interrupt(NUM_WDT);
    223. }
    224. //judge inner interrupt ,get interrupt occure in which VICnVECTADDR
    225. void irq_handler()
    226. {
    227. volatile unsigned int n = 0;
    228. void (*isr)(void) = NULL;
    229. for(n = 0;n <4;n++)
    230. {
    231. if(n == 0 && rVIC0IRQSTATUS != 0)
    232. {
    233. isr = (void (*)(void))rVIC0ADDRESS;
    234. }
    235. else if(n == 1 && rVIC1IRQSTATUS != 0)
    236. {
    237. isr = (void (*)(void))rVIC1ADDRESS;
    238. }
    239. else if(n == 2 && rVIC2IRQSTATUS != 0)
    240. {
    241. isr = (void (*)(void))rVIC2ADDRESS;
    242. }
    243. else if(n == 3 && rVIC3IRQSTATUS != 0)
    244. {
    245. isr = (void (*)(void))rVIC3ADDRESS;
    246. }
    247. (*isr)();
    248. }
    249. }

            link.lds

    1. SECTIONS
    2. {
    3. . = 0xd0020010;
    4. .text :
    5. {
    6. start.o
    7. *(.text)
    8. }
    9. .data :
    10. {
    11. *(.data)
    12. }
    13. .bss :
    14. {
    15. *(.bss)
    16. }
    17. }

             Makefile

    1. CC = arm-linux-gcc
    2. LD = arm-linux-ld
    3. OBJCOPY = arm-linux-objcopy
    4. OBJDUMP = arm-linux-objdump
    5. INCDIR := $(shell pwd)
    6. #预处理器的flag,flag就是编译器可选的选项
    7. CPPFLAGS := -nostdlib -nostdinc -I$(INCDIR)/include
    8. #C编译器的flag
    9. CFLAGS := -Wall -O2 -fno-builtin
    10. export CC LD OBJCOPY OBJDUMP CPPFLAGS CFLAGS
    11. objs := start.o uart_printf.o main.o wdt_interrupt.o
    12. objs += lib/libc.a
    13. led.bin:$(objs)
    14. $(LD) -Tlink.lds -o wdt_interrupt.elf $^
    15. $(OBJCOPY) -O binary wdt_interrupt.elf wdt_interrupt.bin
    16. $(OBJDUMP) -D wdt_interrupt.elf > wdt_interrupt.dis
    17. gcc mkv210.c -o mkv210
    18. ./mkv210 wdt_interrupt.bin sd.bin
    19. lib/libc.a:
    20. cd lib; make; cd ..
    21. %.o:%.S
    22. $(CC) $(CPPFLAGS) $(CFLAGS) -o $@ $< -c
    23. %.o:%.c
    24. $(CC) $(CPPFLAGS) $(CFLAGS) -o $@ $< -c
    25. clean:
    26. rm *.o *.elf *.bin *.dis mkv210 -f
    27. cd lib; make clean; cd ..

            结果示例:  

    demo3:

            看门狗复位

            start.S

    1. #define WTCON 0xE2700000
    2. #define SVC_STACK 0xd0037d80
    3. .global _start
    4. .global IRQ_handler
    5. _start:
    6. //close watchDog
    7. ldr r0,=WTCON
    8. ldr r1,=0x0
    9. str r1,[r0]
    10. //init SVC stack
    11. ldr sp,=SVC_STACK
    12. //init icache
    13. mrc p15,0,r0,c1,c0,0
    14. bic r0,r0,#(1<<12) //close icache
    15. orr r0,r0,#(1<<12) //open icache
    16. mcr p15,0,r0,c1,c0,0
    17. //use func
    18. bl main
    19. b .

               main.c

    1. #include "uart_printf.h"
    2. #include "wdt_reset.h"
    3. #include "stdio.h"
    4. static void dealy_time()
    5. {
    6. volatile unsigned int i = 1000000;
    7. while(i--);
    8. }
    9. int main()
    10. {
    11. //init uart
    12. init_uart();
    13. printf("init uart over\n");
    14. //init outer interupt
    15. static int num = 1;
    16. printf("init wdt,num = %d\n",num++);
    17. wdt_reset();
    18. //dealy_time
    19. while(1)
    20. {
    21. dealy_time();
    22. }
    23. return 0;
    24. }

              uart_printf.h 

    void init_uart();

             uart_printf.c

    1. #define GPA0CON 0xE0200000
    2. #define ULCON0 0xE2900000
    3. #define UCON0 0xE2900004
    4. #define UFCON0 0xE2900008
    5. #define UMCON0 0xE290000C
    6. #define UTRSTAT0 0xE2900010
    7. #define UTXH0 0xE2900020
    8. #define URXH0 0xE2900024
    9. #define UBRDIV0 0xE2900028
    10. #define UDIVSLOT0 0xE290002C
    11. #define rGPA0CON (*(volatile unsigned int *)GPA0CON)
    12. #define rULCON0 (*(volatile unsigned int *)ULCON0)
    13. #define rUCON0 (*(volatile unsigned int *)UCON0)
    14. #define rUFCON0 (*(volatile unsigned int *)UFCON0)
    15. #define rUMCON0 (*(volatile unsigned int *)UMCON0)
    16. #define rUTRSTAT0 (*(volatile unsigned int *)UTRSTAT0)
    17. #define rUTXH0 (*(volatile unsigned int *)UTXH0)
    18. #define rURXH0 (*(volatile unsigned int *)URXH0)
    19. #define rUBRDIV0 (*(volatile unsigned int *)UBRDIV0)
    20. #define rUDIVSLOT0 (*(volatile unsigned int *)UDIVSLOT0)
    21. //init uart
    22. void init_uart()
    23. {
    24. //set gpio as uart(rx,tx)
    25. rGPA0CON &= ~(0xff);
    26. rGPA0CON |= ((1<<2)|(1<<5));
    27. //set uart base configure(mode)
    28. rULCON0 = 0x3;
    29. rUCON0 = 0x5;
    30. rUMCON0 = 0;
    31. rUFCON0 = 0;
    32. //set uart baud
    33. //DIV_VAL = (PCLK / (bps x 16))-1
    34. //(66000000 /(115200 * 16)) -1 = 34.8
    35. rUBRDIV0 = 34;
    36. //set uart baud calibration
    37. //0.8 * 16 = 13,check 210 table
    38. rUDIVSLOT0 = 0xdfdd;
    39. }
    40. //send data
    41. void putc(char data)
    42. {
    43. while (!(rUTRSTAT0 & (1<<1)));
    44. rUTXH0 = data;
    45. }
    46. //receive data
    47. char getc()
    48. {
    49. while (!(rUTRSTAT0 & (1<<0)));
    50. return (rURXH0 & 0xff);
    51. }

            wdt_reset.h 

    void wdt_reset();

            wdt_reset.c

    1. #define WTCON 0xE2700000
    2. #define WTDAT 0xE2700004
    3. #define WTCNT 0xE2700008
    4. #define WTCLRIN 0xE270000C
    5. #define rWTCON *((volatile unsigned int *) WTCON)
    6. #define rWTDAT *((volatile unsigned int *) WTDAT)
    7. #define rWTCNT *((volatile unsigned int *) WTCNT)
    8. #define rWTCLRI *((volatile unsigned int *) WTCLRI)
    9. void wdt_reset()
    10. {
    11. //set WTCON,set Prescaler,Prescaler is set value + 1
    12. //Prescaler = 65 + 1 = 66,66Mhz / 66 = 1Mhz = 1000000hz
    13. rWTCON &= ~(0xff << 8);
    14. rWTCON |= (65<<8);
    15. //set div is 128,t = 1/(1000000hz /128) = 1.28us
    16. rWTCON &= ~(3 << 3);
    17. rWTCON |= (3<<8);
    18. //set WTCON,close interrupt and open reset
    19. rWTCON &= ~(1<<2);
    20. rWTCON |= 1;
    21. //set WTDAT,set set the time form firstly open timer to count open(WTCNT)
    22. rWTDAT = 1000;
    23. rWTCNT = 1000;
    24. //open wdt
    25. rWTCON |= (1<<5);
    26. }

            link.lds 

    1. SECTIONS
    2. {
    3. . = 0xd0020010;
    4. .text :
    5. {
    6. start.o
    7. *(.text)
    8. }
    9. .data :
    10. {
    11. *(.data)
    12. }
    13. .bss :
    14. {
    15. *(.bss)
    16. }
    17. }

            Makefile 

    1. CC = arm-linux-gcc
    2. LD = arm-linux-ld
    3. OBJCOPY = arm-linux-objcopy
    4. OBJDUMP = arm-linux-objdump
    5. INCDIR := $(shell pwd)
    6. #预处理器的flag,flag就是编译器可选的选项
    7. CPPFLAGS := -nostdlib -nostdinc -I$(INCDIR)/include
    8. #C编译器的flag
    9. CFLAGS := -Wall -O2 -fno-builtin
    10. export CC LD OBJCOPY OBJDUMP CPPFLAGS CFLAGS
    11. objs := start.o uart_printf.o main.o wdt_reset.o
    12. objs += lib/libc.a
    13. led.bin:$(objs)
    14. $(LD) -Tlink.lds -o wdt_reset.elf $^
    15. $(OBJCOPY) -O binary wdt_reset.elf wdt_reset.bin
    16. $(OBJDUMP) -D wdt_reset.elf > wdt_reset.dis
    17. gcc mkv210.c -o mkv210
    18. ./mkv210 wdt_reset.bin sd.bin
    19. lib/libc.a:
    20. cd lib; make; cd ..
    21. %.o:%.S
    22. $(CC) $(CPPFLAGS) $(CFLAGS) -o $@ $< -c
    23. %.o:%.c
    24. $(CC) $(CPPFLAGS) $(CFLAGS) -o $@ $< -c
    25. clean:
    26. rm *.o *.elf *.bin *.dis mkv210 -f
    27. cd lib; make clean; cd ..

            结果示例: 

    demo4:

            中断(alarm)读写RTC

            start.S

    1. #define WTCON 0xE2700000
    2. #define SVC_STACK 0xd0037d80
    3. #define IRQ_STACK 0xd0037f80
    4. .global _start
    5. .global IRQ_handler
    6. _start:
    7. //close watchDog
    8. ldr r0,=WTCON
    9. ldr r1,=0x0
    10. str r1,[r0]
    11. //init SVC stack
    12. ldr sp,=SVC_STACK
    13. //init icache
    14. mrc p15,0,r0,c1,c0,0
    15. bic r0,r0,#(1<<12) //close icache
    16. orr r0,r0,#(1<<12) //open icache
    17. mcr p15,0,r0,c1,c0,0
    18. //use func
    19. bl main
    20. b .
    21. //all interrupt process:Protect the scene + mian iqr process + return scene
    22. IRQ_handler:
    23. //init IRQ_STACK
    24. ldr sp, =IRQ_STACK
    25. //protect lr
    26. sub lr, lr, #4
    27. //protect r0--r12 that in irq stack
    28. stmfd sp!, {r0-r12, lr}
    29. //mian iqr process
    30. bl irq_handler
    31. //return scene
    32. ldmfd sp!, {r0-r12, pc}^

            main.c  

    1. #include "uart_printf.h"
    2. #include "rtc_alarm.h"
    3. #include "stdio.h"
    4. static void dealy_time()
    5. {
    6. volatile unsigned int i,j;
    7. for (i=0; i<10000; i++)
    8. for (j=0; j<1000; j++);
    9. }
    10. int main()
    11. {
    12. //init uart
    13. init_uart();
    14. printf("init uart over\n");
    15. //init outer interupt
    16. printf("rtc init\n");
    17. rtc_alarm();
    18. //set RTC time
    19. struct rtc_time rtc_write =
    20. {
    21. .year = 2023,
    22. .month = 10,
    23. .date = 22,
    24. .hour = 14,
    25. .minute = 00,
    26. .second = 00,
    27. .day = 0,
    28. };
    29. set_rtc_time(&rtc_write);
    30. //init inner interupt
    31. printf("init inner\n");
    32. init_inner_interrupt();
    33. struct rtc_time rtc_read;
    34. //dealy time
    35. while(1)
    36. {
    37. get_rtc_time(&rtc_read);
    38. 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);
    39. dealy_time();
    40. }
    41. while(1);
    42. return 0;
    43. }

            uart_printf.h 

    void init_uart();

             uart_printf.c

    1. #define GPA0CON 0xE0200000
    2. #define ULCON0 0xE2900000
    3. #define UCON0 0xE2900004
    4. #define UFCON0 0xE2900008
    5. #define UMCON0 0xE290000C
    6. #define UTRSTAT0 0xE2900010
    7. #define UTXH0 0xE2900020
    8. #define URXH0 0xE2900024
    9. #define UBRDIV0 0xE2900028
    10. #define UDIVSLOT0 0xE290002C
    11. #define rGPA0CON (*(volatile unsigned int *)GPA0CON)
    12. #define rULCON0 (*(volatile unsigned int *)ULCON0)
    13. #define rUCON0 (*(volatile unsigned int *)UCON0)
    14. #define rUFCON0 (*(volatile unsigned int *)UFCON0)
    15. #define rUMCON0 (*(volatile unsigned int *)UMCON0)
    16. #define rUTRSTAT0 (*(volatile unsigned int *)UTRSTAT0)
    17. #define rUTXH0 (*(volatile unsigned int *)UTXH0)
    18. #define rURXH0 (*(volatile unsigned int *)URXH0)
    19. #define rUBRDIV0 (*(volatile unsigned int *)UBRDIV0)
    20. #define rUDIVSLOT0 (*(volatile unsigned int *)UDIVSLOT0)
    21. //init uart
    22. void init_uart()
    23. {
    24. //set gpio as uart(rx,tx)
    25. rGPA0CON &= ~(0xff);
    26. rGPA0CON |= ((1<<2)|(1<<5));
    27. //set uart base configure(mode)
    28. rULCON0 = 0x3;
    29. rUCON0 = 0x5;
    30. rUMCON0 = 0;
    31. rUFCON0 = 0;
    32. //set uart baud
    33. //DIV_VAL = (PCLK / (bps x 16))-1
    34. //(66000000 /(115200 * 16)) -1 = 34.8
    35. rUBRDIV0 = 34;
    36. //set uart baud calibration
    37. //0.8 * 16 = 13,check 210 table
    38. rUDIVSLOT0 = 0xdfdd;
    39. }
    40. //send data
    41. void putc(char data)
    42. {
    43. while (!(rUTRSTAT0 & (1<<1)));
    44. rUTXH0 = data;
    45. }
    46. //receive data
    47. char getc()
    48. {
    49. while (!(rUTRSTAT0 & (1<<0)));
    50. return (rURXH0 & 0xff);
    51. }

      rtc_struct.h      

    1. struct rtc_time
    2. {
    3. unsigned int year;
    4. unsigned int month;
    5. unsigned int date; //几号
    6. unsigned int hour;
    7. unsigned int minute;
    8. unsigned int second;
    9. unsigned int day; //星期
    10. };

             rtc_alarm.h

    1. #include "rtc_struct.h"
    2. void rtc_alarm();
    3. void set_rtc_time(struct rtc_time *p);
    4. void get_rtc_time(struct rtc_time *p);
    5. void init_inner_interrupt();

            rtc_alarm.c

    1. #include "stdio.h"
    2. #include "rtc_struct.h"
    3. //rtc interrupt register
    4. #define RTC_BASE 0xE2800000
    5. #define rINTP (*((volatile unsigned long *)(RTC_BASE + 0x30)))
    6. #define rRTCCON (*((volatile unsigned long *)(RTC_BASE + 0x40)))
    7. #define rTICCNT (*((volatile unsigned long *)(RTC_BASE + 0x44)))
    8. #define rRTCALM (*((volatile unsigned long *)(RTC_BASE + 0x50)))
    9. #define rALMSEC (*((volatile unsigned long *)(RTC_BASE + 0x54)))
    10. #define rALMMIN (*((volatile unsigned long *)(RTC_BASE + 0x58)))
    11. #define rALMHOUR (*((volatile unsigned long *)(RTC_BASE + 0x5c)))
    12. #define rALMDATE (*((volatile unsigned long *)(RTC_BASE + 0x60)))
    13. #define rALMMON (*((volatile unsigned long *)(RTC_BASE + 0x64)))
    14. #define rALMYEAR (*((volatile unsigned long *)(RTC_BASE + 0x68)))
    15. #define rRTCRST (*((volatile unsigned long *)(RTC_BASE + 0x6c)))
    16. #define rBCDSEC (*((volatile unsigned long *)(RTC_BASE + 0x70)))
    17. #define rBCDMIN (*((volatile unsigned long *)(RTC_BASE + 0x74)))
    18. #define rBCDHOUR (*((volatile unsigned long *)(RTC_BASE + 0x78)))
    19. #define rBCDDATE (*((volatile unsigned long *)(RTC_BASE + 0x7c)))
    20. #define rBCDDAY (*((volatile unsigned long *)(RTC_BASE + 0x80)))
    21. #define rBCDMON (*((volatile unsigned long *)(RTC_BASE + 0x84)))
    22. #define rBCDYEAR (*((volatile unsigned long *)(RTC_BASE + 0x88)))
    23. #define rCURTICCNT (*((volatile unsigned long *)(RTC_BASE + 0x90)))
    24. #define rRTCLVD (*((volatile unsigned long *)(RTC_BASE + 0x94)))
    25. //inner interrupt register
    26. //VIC base address
    27. #define VIC0_BASE 0xF2000000
    28. #define VIC1_BASE 0xF2100000
    29. #define VIC2_BASE 0xF2200000
    30. #define VIC3_BASE 0xF2300000
    31. //VIC0 register
    32. #define rVIC0IRQSTATUS (*(volatile unsigned int *)(VIC0_BASE + 0x0000))
    33. #define rVIC0FIQSTATUS (*(volatile unsigned int *)(VIC0_BASE + 0x0004))
    34. #define rVIC0INTSELECT (*(volatile unsigned int *)(VIC0_BASE + 0x000C))
    35. #define rVIC0INTENABLE (*(volatile unsigned int *)(VIC0_BASE + 0x0010))
    36. #define rVIC0INTENCLEAR (*(volatile unsigned int *)(VIC0_BASE + 0x0014))
    37. #define rVIC0VECTADDR (VIC0_BASE + 0x100)
    38. #define rVIC0ADDRESS (*(volatile unsigned int *)(VIC0_BASE + 0x0F00))
    39. //VIC1 register
    40. #define rVIC1IRQSTATUS (*(volatile unsigned int *)(VIC1_BASE + 0x0000))
    41. #define rVIC1FIQSTATUS (*(volatile unsigned int *)(VIC1_BASE + 0x0004))
    42. #define rVIC1INTSELECT (*(volatile unsigned int *)(VIC1_BASE + 0x000C))
    43. #define rVIC1INTENABLE (*(volatile unsigned int *)(VIC1_BASE + 0x0010))
    44. #define rVIC1INTENCLEAR (*(volatile unsigned int *)(VIC1_BASE + 0x0014))
    45. #define rVIC1VECTADDR (VIC1_BASE + 0x100)
    46. #define rVIC1ADDRESS (*(volatile unsigned int *)(VIC1_BASE + 0x0F00))
    47. //VIC2 register
    48. #define rVIC2IRQSTATUS (*(volatile unsigned int *)(VIC2_BASE + 0x0000))
    49. #define rVIC2FIQSTATUS (*(volatile unsigned int *)(VIC2_BASE + 0x0004))
    50. #define rVIC2INTSELECT (*(volatile unsigned int *)(VIC2_BASE + 0x000C))
    51. #define rVIC2INTENABLE (*(volatile unsigned int *)(VIC2_BASE + 0x0010))
    52. #define rVIC2INTENCLEAR (*(volatile unsigned int *)(VIC2_BASE + 0x0014))
    53. #define rVIC2VECTADDR (VIC2_BASE + 0x100)
    54. #define rVIC2ADDRESS (*(volatile unsigned int *)(VIC2_BASE + 0x0F00))
    55. //VIC3 register
    56. #define rVIC3IRQSTATUS (*(volatile unsigned int *)(VIC3_BASE + 0x0000))
    57. #define rVIC3FIQSTATUS (*(volatile unsigned int *)(VIC3_BASE + 0x0004))
    58. #define rVIC3INTSELECT (*(volatile unsigned int *)(VIC3_BASE + 0x000C))
    59. #define rVIC3INTENABLE (*(volatile unsigned int *)(VIC3_BASE + 0x0010))
    60. #define rVIC3INTENCLEAR (*(volatile unsigned int *)(VIC3_BASE + 0x0014))
    61. #define rVIC3VECTADDR (VIC3_BASE + 0x100)
    62. #define rVIC3ADDRESS (*(volatile unsigned int *)(VIC3_BASE + 0x0F00))
    63. //interrupt vector table
    64. #define vector_table_base 0xD0037400
    65. #define reset_vector (vector_table_base + 0x00)
    66. #define undef_vector (vector_table_base + 0x04)
    67. #define sotf_interrupt_vector (vector_table_base + 0x08)
    68. #define prefetch_vector (vector_table_base + 0x0C)
    69. #define data_vector (vector_table_base + 0x10)
    70. #define irq_vector (vector_table_base + 0x18)
    71. #define fiq_vector (vector_table_base + 0x1C)
    72. #define r_reset_vector (*(volatile unsigned int *) reset_vector)
    73. #define r_undef_vector (*(volatile unsigned int *) undef_vector)
    74. #define r_sotf_interrupt_vector (*(volatile unsigned int *) sotf_interrupt_vector)
    75. #define r_prefetch_vector (*(volatile unsigned int *) prefetch_vector)
    76. #define r_data_vector (*(volatile unsigned int *) data_vector)
    77. #define r_irq_vector (*(volatile unsigned int *) irq_vector)
    78. #define r_fiq_vector (*(volatile unsigned int *) fiq_vector)
    79. //interrupt number
    80. #define NUM_TIMER0 (21)
    81. #define NUM_TIMER1 (22)
    82. #define NUM_TIMER2 (23)
    83. #define NUM_TIMER3 (24)
    84. #define NUM_TIMER4 (25)
    85. #define NUM_SYSTIMER (26)
    86. #define NUM_WDT (27)
    87. #define NUM_RTC_ALARM (28)
    88. #define NUM_RTC_TICK (29)
    89. //rtc interrupt func
    90. //rtc func
    91. static void isr_rtc_alarm()
    92. {
    93. static int num = 0;
    94. printf("rtc interrupt, num = %d...",num++);
    95. //open rtc alarm interrupt
    96. rINTP |= (1<<1);
    97. //clear VIC0ADDR,clear using interrupt process
    98. rVIC0ADDRESS = 0;
    99. rVIC1ADDRESS = 0;
    100. rVIC2ADDRESS = 0;
    101. rVIC3ADDRESS = 0;
    102. }
    103. static unsigned int num_2_bcd(unsigned int num)
    104. {
    105. return (((num / 10)<< 4) | (num % 10));
    106. }
    107. static unsigned int bcd_2_num(unsigned int bcd)
    108. {
    109. return ((((bcd & (0xf0)) >> 4) *10) + (bcd & (0x0f)) );
    110. }
    111. void set_rtc_time(struct rtc_time *p)
    112. {
    113. //set RTCCON,open RTC
    114. rRTCCON |= 1;
    115. //set year month date,hour min,sec,day
    116. rBCDYEAR = num_2_bcd(p->year - 2000);
    117. rBCDMON = num_2_bcd(p->month);
    118. rBCDDATE = num_2_bcd(p->date);
    119. rBCDHOUR = num_2_bcd(p->hour);
    120. rBCDMIN = num_2_bcd(p->minute);
    121. rBCDSEC = num_2_bcd(p->second);
    122. rBCDDAY = num_2_bcd(p->day);
    123. //set RTCCON,close RTC
    124. rRTCCON &= ~(1);
    125. }
    126. void get_rtc_time(struct rtc_time *p)
    127. {
    128. //set RTCCON,open RTC
    129. rRTCCON |= 1;
    130. //get year month date,hour min,sec,day
    131. p->year = bcd_2_num(rBCDYEAR) + 2000;
    132. p->month = bcd_2_num(rBCDMON);
    133. p->date = bcd_2_num(rBCDDATE);
    134. p->hour = bcd_2_num(rBCDHOUR);
    135. p->minute = bcd_2_num(rBCDMIN);
    136. p->second = bcd_2_num(rBCDSEC);
    137. p->day = bcd_2_num(rBCDDAY);
    138. //set RTCCON,close RTC
    139. rRTCCON &= ~(1);
    140. }
    141. void rtc_alarm()
    142. {
    143. //set alarm pre 10 trigger
    144. rALMSEC = num_2_bcd(10);
    145. //set sec used
    146. rRTCALM |= 1<<0;
    147. //set alarm enable
    148. rRTCALM |= 1<<6;
    149. }
    150. //inner interrupt func
    151. static void reset_func()
    152. {
    153. printf("reset\n");
    154. }
    155. static void undef_func()
    156. {
    157. printf("undef\n");
    158. }
    159. static void sotf_interrupt_func()
    160. {
    161. printf("sotf_intrrupt\n");
    162. }
    163. static void prefetch_func()
    164. {
    165. printf("prefetch\n");
    166. }
    167. static void data_func()
    168. {
    169. printf("data\n");
    170. }
    171. static void fiq_func()
    172. {
    173. printf("irq\n");
    174. }
    175. void IRQ_handler();
    176. static void bind_isr_VICnINTENCLEAR(unsigned long num,void (*handler)())
    177. {
    178. if(num <32)
    179. {
    180. printf("bind ok\n");
    181. *((volatile unsigned int *)(rVIC0VECTADDR + 4 * (num))) = (unsigned)handler;
    182. }
    183. else if(num < 64)
    184. {
    185. *((volatile unsigned int *)(rVIC0VECTADDR + 4 * (num-32))) = (unsigned)handler;
    186. }
    187. else if(num < 96)
    188. {
    189. *((volatile unsigned int *)(rVIC0VECTADDR + 4 * (num-64))) = (unsigned)handler;
    190. }
    191. else
    192. {
    193. *((volatile unsigned int *)(rVIC0VECTADDR + 4 * (num-96))) = (unsigned)handler;
    194. }
    195. }
    196. static void enable_interrupt(unsigned long num)
    197. {
    198. unsigned long tmp;
    199. if(num < 32)
    200. {
    201. tmp = rVIC0INTENABLE;
    202. tmp |= (1<<num);
    203. rVIC0INTENABLE = tmp;
    204. }
    205. else if(num < 64)
    206. {
    207. tmp = rVIC0INTENABLE;
    208. tmp |= (1<<(num-32));
    209. rVIC1INTENABLE = tmp;
    210. }
    211. else if(num < 96)
    212. {
    213. tmp = rVIC0INTENABLE;
    214. tmp |= (1<<(num-64));
    215. rVIC2INTENABLE = tmp;
    216. }
    217. else if(num < 200)
    218. {
    219. tmp = rVIC0INTENABLE;
    220. tmp |= (1<<(num-96));
    221. rVIC3INTENABLE = tmp;
    222. }
    223. else
    224. {
    225. rVIC0INTENABLE = 0xffffffff;
    226. rVIC1INTENABLE = 0xffffffff;
    227. rVIC2INTENABLE = 0xffffffff;
    228. rVIC3INTENABLE = 0xffffffff;
    229. }
    230. }
    231. void init_inner_interrupt()
    232. {
    233. //bind interrupt process on interrupt vector table
    234. r_reset_vector = (unsigned int)reset_func;
    235. r_undef_vector = (unsigned int)undef_func;
    236. r_sotf_interrupt_vector = (unsigned int)sotf_interrupt_func;
    237. r_prefetch_vector = (unsigned int)prefetch_func;
    238. r_data_vector = (unsigned int)data_func;
    239. r_irq_vector = (unsigned int)IRQ_handler;
    240. r_fiq_vector = (unsigned int)fiq_func;
    241. //select interrupt mode(irq)
    242. rVIC0INTSELECT = 0x0;
    243. rVIC1INTSELECT = 0x0;
    244. rVIC2INTSELECT = 0x0;
    245. rVIC3INTSELECT = 0x0;
    246. //diasble interrupt
    247. rVIC0INTENCLEAR = 0xffffffff;
    248. rVIC1INTENCLEAR = 0xffffffff;
    249. rVIC2INTENCLEAR = 0xffffffff;
    250. rVIC3INTENCLEAR = 0xffffffff;
    251. //clear interrupt process address
    252. rVIC0ADDRESS = 0;
    253. rVIC1ADDRESS = 0;
    254. rVIC2ADDRESS = 0;
    255. rVIC3ADDRESS = 0;
    256. //bind isr process on VICnINTENCLEAR
    257. bind_isr_VICnINTENCLEAR(NUM_RTC_ALARM,isr_rtc_alarm);
    258. //enable interrupt
    259. enable_interrupt(NUM_RTC_ALARM);
    260. }
    261. //judge inner interrupt ,get interrupt occure in which VICnVECTADDR
    262. void irq_handler()
    263. {
    264. volatile unsigned int n = 0;
    265. void (*isr)(void) = NULL;
    266. for(n = 0;n <4;n++)
    267. {
    268. if(n == 0 && rVIC0IRQSTATUS != 0)
    269. {
    270. isr = (void (*)(void))rVIC0ADDRESS;
    271. }
    272. else if(n == 1 && rVIC1IRQSTATUS != 0)
    273. {
    274. isr = (void (*)(void))rVIC1ADDRESS;
    275. }
    276. else if(n == 2 && rVIC2IRQSTATUS != 0)
    277. {
    278. isr = (void (*)(void))rVIC2ADDRESS;
    279. }
    280. else if(n == 3 && rVIC3IRQSTATUS != 0)
    281. {
    282. isr = (void (*)(void))rVIC3ADDRESS;
    283. }
    284. (*isr)();
    285. }
    286. }

            link.lds 

    1. SECTIONS
    2. {
    3. . = 0xd0020010;
    4. .text :
    5. {
    6. start.o
    7. *(.text)
    8. }
    9. .data :
    10. {
    11. *(.data)
    12. }
    13. .bss :
    14. {
    15. *(.bss)
    16. }
    17. }

            Makefile 

    1. CC = arm-linux-gcc
    2. LD = arm-linux-ld
    3. OBJCOPY = arm-linux-objcopy
    4. OBJDUMP = arm-linux-objdump
    5. INCDIR := $(shell pwd)
    6. #预处理器的flag,flag就是编译器可选的选项
    7. CPPFLAGS := -nostdlib -nostdinc -I$(INCDIR)/include
    8. #C编译器的flag
    9. CFLAGS := -Wall -O2 -fno-builtin
    10. export CC LD OBJCOPY OBJDUMP CPPFLAGS CFLAGS
    11. objs := start.o uart_printf.o main.o rtc_alarm.o
    12. objs += lib/libc.a
    13. led.bin:$(objs)
    14. $(LD) -Tlink.lds -o rtc_alarm.elf $^
    15. $(OBJCOPY) -O binary rtc_alarm.elf rtc_alarm.bin
    16. $(OBJDUMP) -D rtc_alarm.elf > rtc_alarm.dis
    17. gcc mkv210.c -o mkv210
    18. ./mkv210 rtc_alarm.bin sd.bin
    19. lib/libc.a:
    20. cd lib; make; cd ..
    21. %.o:%.S
    22. $(CC) $(CPPFLAGS) $(CFLAGS) -o $@ $< -c
    23. %.o:%.c
    24. $(CC) $(CPPFLAGS) $(CFLAGS) -o $@ $< -c
    25. clean:
    26. rm *.o *.elf *.bin *.dis mkv210 -f
    27. cd lib; make clean; cd ..

    结果示例: 

  • 相关阅读:
    cobol基本语法
    抖音短视频所有问题的详细攻略——今抖云创
    数组扁平化实现
    【JUC】循环屏障CyclicBarrier详解
    latex模板列出所有参考文献并加上超链接(xiaoming et al. 2022; xiaohong et al. 2021)
    【高等数学】五、微分方程
    学校宿舍一键视频对讲
    Git的下载与安装
    关于Git使用:fatal: Could not read from remote repository.的报错问题解决
    【重温设计模式】中介者模式及其Java示例
  • 原文地址:https://blog.csdn.net/tyro_wzp/article/details/133947675