GNU ARM汇编--(十)s3c2440的RTC
来源:互联网 发布:ubuntu 宽带测速 编辑:程序博客网 时间:2024/06/06 13:56
http://blog.csdn.net/dndxhej/article/details/7727489
RTC
概述
在系统电源关掉时RTC可以在备份电池的支持下来工作.RTC可以使用STRB/LDRB指令传输8bit的BCD值到CPU.数据包括秒,分,时,日期,天,月和年.RTC工作在外部32.768KHz的晶振下,而且有报警功能.
属性
BCD:秒,分,时,日期,天,月和年
闰年产生器
报警功能:报警中断 从power-off模式唤醒
独立的电源管脚(RTCVDD)
为RTOS kernel time tick支持毫秒级的tick.
闰年产生器
闰年产生器通过BCDDATA,BCDMON和BCDYEAR来决定每个月最后一天的日期.一个8bit的计数器只能表示两个BCD码,所以无法决定'00'年是否是闰年.举个例子,它不能区分1900和2000.为了解决这个问题,s3c2440的RTC模块在硬件逻辑上支持闰年是2000.1900不是闰年而2000时闰年.因此s3c2440的00表示2000,而不是1900.
READ/WRITE REGISTERS
为了写BCD寄存器,RTCCON寄存器的第0位必须置高.为了显示秒,分,时,日期,月和年,CPU从BCDSEC,BCDMIN,BCDHOUR,BCDDAY,BCDDATE,BCDMON和BCDYEAR寄存器中读数据.然而,在读取多个寄存器时,可能会有1秒的偏移.比如,当user读数据的时候,假设结果是2059(Year),12(Month),31(Date),23(Hour)和59(Minute).当user读BCDSEC寄存器,值的范围是1--59s,到这没有问题,但是,如果这个值是0s,由于刚才提到的那一s的偏移,年月日时分就会变为2060(year),1(Month),1(Date),0(Hour)和0(Minute).在这种情况下,如果BCDSEC是0 user应该重读各个寄存器.
BACKUP BATTERY OPERATION
RTC由备份电池驱动,及时系统电源断了,备份电池可以通过RTCVDD管脚向RTC模块供电.当系统关闭,CPU和RTC逻辑之间的接口是封闭的,备份电池只是驱动晶振电路和BCD计数器来减少电源消耗.
ALARM FUNCTION
在power-off模式或者正常操作模式下,RTC可以在一个指定的时间产生一个报警信号.在正常操作模式下,报警中断(INT_RTC)是激活的.在power-off模式,电源管理唤醒信号(PMWKUP)和INT_RTC都是激活的.RTC报警寄存器(RTCALM)决定是否开启报警状态和报警时间的设置.
TICK TIME INTERRUPT
RTC的tick time用于中断请求.TICNT寄存器有中断使能位和中断的计数值.当tick time中断产生计数值为0.中断的周期:
Period = (n+1)/128 second
n:Tick time count value(1~127)
REAL TIME CLOCK SPECIAL REGISTERS
RTCCON
RTCCON控制4个bits,比如RTCEN控制BCD寄存器的读写使能,CLKSEL,CNTSEL和CLKRST是用于测试的.
RTCEN bit控制CPU与RTC之间的所有接口,所以在系统重启后应该在RTC控制程序中将其设为1来使能数据的读写.在电源关闭前,RTCEN应该清0来防止对RTC寄存器的不经意的写入.
Register Address R/W Description Reset Value
RTCCON 0x57000040(L)/0x57000043(B) R/W RTC control register 0x0
RTCCON Bit Description Initial State
RTCEN [0] RTC控制使能 0
注意:所有的RTC寄存器都要以字节为单位来访问,可以用STRB和LDRB汇编指令或者char类型的指针.
TICNT
Register Address R/W Description Reset Value
TICNT 0x57000044(L)/0x57000047(B) R/W(by byte) Tick time count register 0x0
TICNT BIT Description Initial State
TICK INT ENABLE [7] tick time 中断使能 0
TICK TIME COUNT [6:0] tick time 计数值(1~127) 000000
RTCALM
RTCALM决定alarm使能和alarm时间.在power-off模式下RTCALM寄存器通过INT_RTC和PWMKUP产生报警信号,而在正常模式下只通过INT_RTC.
Register Address R/W Description Reset Value
RTCALM 0x57000050(L)/0x57000053(B) R/W(by type) RTC报警控制寄存器 0x0
RTCALM Bit Description Initial State
ALMEN [6] 报警总开关 0
YEAREN [5] Year报警开关 0
MONREN [4] Month报警开关 0
DATEEN [3] Date报警开关 0
HOUREN [2] Hour报警开关 0
MINEN [1] Minute报警开关 0
SECEN [0] Second报警开关 0
ALMSEC
设置Second报警的具体秒数
ALMMIN
设置Minute报警的具体分钟数
ALMHOUR
设置Hour报警的具体小时数
ALMDATE
设置Date报警的具体日期
ALMMON
设置Mon报警的具体月份
ALMYEAR
设置Year报警的具体年份
BCDSEC BCDMIN BCDHOUR BCDDATE BCDMON BCDYEAR
用BCD码表示的秒 分 时 日期 月份 年
给出报警中断的rtc汇编和c代码如下,在报警中断时是调用PWM的蜂鸣器来做闹钟的:
start.S:
- /*
- watchdog timer with disable reset
- copyleft@ dndxhej@gmail.com
- */
- .equ NOINT, 0xc0
- .equ GPBCON, 0x56000010 @led
- .equ GPBDAT, 0x56000014 @led
- .equ GPBUP, 0x56000018 @led
- .equ GPFCON, 0x56000050 @interrupt config
- .equ EINTMASK, 0x560000a4
- .equ EXTINT0, 0x56000088
- .equ EXTINT1, 0x5600008c
- .equ EXTINT2, 0x56000090
- .equ INTMSK, 0x4A000008
- .equ EINTPEND, 0x560000a8
- .equ SUBSRCPND, 0x4a000018
- .equ INTSUBMSK, 0x4a00001c
- .equ SRCPND, 0X4A000000
- .equ INTPND, 0X4A000010
- .equ GPHCON, 0x56000070
- .equ GPHDAT, 0x56000074
- .equ GPB5_out, (1<<(5*2))
- .equ GPB6_out, (1<<(6*2))
- .equ GPB7_out, (1<<(7*2))
- .equ GPB8_out, (1<<(8*2))
- .equ GPBVALUE, (GPB5_out | GPB6_out | GPB7_out | GPB8_out)
- .equ LOCKTIME, 0x4c000000
- .equ MPLLCON, 0x4c000004
- .equ UPLLCON, 0x4c000008
- .equ M_MDIV, 92
- .equ M_PDIV, 1
- .equ M_SDIV, 1
- .equ U_MDIV, 56
- .equ U_PDIV, 2
- .equ U_SDIV, 2
- .equ CLKDIVN, 0x4c000014
- .equ DIVN_UPLL, 0
- .equ HDIVN, 1
- .equ PDIVN, 1 @FCLK : HCLK : PCLK = 1:2:4
- .equ WTCON, 0x53000000
- .equ Pre_scaler, 249
- .equ wd_timer, 1
- .equ clock_select, 00 @316
- .equ int_gen, 1 @开中断
- .equ reset_enable, 0 @关掉重启信号
- .equ WTDAT,0x53000004
- .equ Count_reload,50000 @定时器定为2S PCLK = 100M PCLK/(Pre_scaler+1)/clock_select = 100M/(249+1)/16=25k 50000/25k=2s
- .equ WTCNT,0x53000008
- .equ Count,50000
- .equ TCFG0,0x51000000
- .equ Prescaler1,0x00 @[15:8]Timer234
- .equ Prescaler0,249 @[7:0]Timer01
- .equ TCFG1,0x51000004
- .equ DMA_MODE,0x0 @[23:20]no dma channal
- .equ MUX0,0x2 @[3:0] 1/8
- @定时器输入时钟周期 = PCLK/(prescaler + 1)/(divider value)
- @clk = 100M/(249+1)/8=25k
- .equ TCON,0x51000008
- .equ DZ_eable,0 @[4]关闭死区的操作
- .equ auto_reload,1 @[3]auto_reload
- .equ inverter,1 @[2]打开电平反转
- .equ man_update,1 @[1]手动更新
- .equ clear_man_update,0
- .equ start,1 @[0]开始
- .equ stop,0 @[0]停止
- .equ TCNTB0,0x5100000c
- .equ TCMPB0,0x51000010
- .equ TCNTO0,0x51000014
- .equ ULCON0, 0x50000000
- .equ IR_MODE, 0x0 @[6]正常模式
- .equ Parity_Mode, 0x0 @[5:3]无校验位
- .equ Num_of_stop_bit, 0x0 @[2]一个停止位
- .equ Word_length, 0b11 @[1:0]8个数据位
- .equ UCON0, 0x50000004
- .equ FCLK_Div, 0 @[15:12] 时钟源选择用PCLK,所以这里用默认值
- .equ Clk_select, 0b00 @[11:10] 时钟源选择使用PCLK
- .equ Tx_Int_Type, 1 @[9] 中断请求类型为Level
- .equ Rx_Int_Type, 0 @1 @[8] 中断请求类型为Level
- .equ Rx_Timeout, 0 @[7]
- .equ Rx_Error_Stat_Int, 1 @[6]
- .equ Loopback_Mode, 0 @[5] 正常模式
- .equ Break_Sig, 0 @[4] 不发送终止信号
- .equ Tx_Mode, 0b01 @[3:2] 中断请求或轮循模式
- .equ Rx_Mode, 0b01 @[1:0] 中断请求或轮循模式
- .equ UFCON0, 0x50000008
- .equ Tx_FIFO_Trig_Level, 0b00 @[7:6]
- .equ Rx_FIFO_Trig_Level, 0b00 @[5:4]
- .equ Tx_FIFO_Reset, 0b0 @[2]
- .equ Rx_FIFO_Reset, 0b0 @[1]
- .equ FIFO_Enable, 0b0 @[0] 非FIFO模式
- .equ UMCON0, 0x5000000C @这个寄存器可以不管的
- .equ UTRSTAT0, 0x50000010
- .equ UERSTAT0, 0x50000014
- .equ UFSTAT0, 0x50000018
- .equ UMSTAT0, 0x5000001C
- .equ UTXH0, 0x50000020 @(L 小端)
- .equ URXH0, 0x50000024 @(L 小端)
- .equ UBRDIV0, 0x50000028
- .equ UBRDIV, 0x35 @PCLK=400M/4=100M UBRDIV = (int)(100M/115200/16) - 1 = 53 = 0x35
- .equ BCDMIN,0x57000074
- .equ BCDSEC,0x57000070
- //.global Buzzer_Freq_Set
- .global _start
- _start: b reset
- ldr pc, _undefined_instruction
- ldr pc, _software_interrupt
- ldr pc, _prefetch_abort
- ldr pc, _data_abort
- ldr pc, _not_used
- @b irq
- ldr pc, _irq
- ldr pc, _fiq
- _undefined_instruction: .word undefined_instruction
- _software_interrupt: .word software_interrupt
- _prefetch_abort: .word prefetch_abort
- _data_abort: .word data_abort
- _not_used: .word not_used
- _irq: .word irq
- _fiq: .word fiq
- .balignl 16,0xdeadbeef
- reset:
- ldr r3, =WTCON
- mov r4, #0x0
- str r4, [r3] @ disable watchdog
- ldr r0, =GPBCON
- ldr r1, =0x15400 @这个时候暂不配置GPB0为TOUT0
- str r1, [r0]
- ldr r2, =GPBDAT
- ldr r1, =0x160
- str r1, [r2]
- bl clock_setup
- bl uart_init
- bl delay
- msr cpsr_c, #0xd2 @进入中断模式
- ldr sp, =3072 @中断模式的栈指针定义
- msr cpsr_c, #0xd3 @进入系统模式
- ldr sp, =4096 @设置系统模式的栈指针
- @--------------------------------------------
- ldr r0, =GPBUP
- ldr r1, =0x03f0
- str r1, [r0]
- ldr r0, =GPFCON
- ldr r1, =0x2ea@0x2
- str r1, [r0]
- ldr r0, =EXTINT0
- @ldr r1, =0x8f888@0x0@0x8f888 @~(7|(7<<4)|(7<<8)|(7<<16)) //低电平触发中断
- ldr r1, =0xafaaa@0x0@0x8f888 //下降沿触发中断
- str r1, [r0]
- ldr r0, =EINTPEND
- ldr r1, =0xf0@0b10000
- str r1, [r0]
- ldr r0, =EINTMASK
- ldr r1, =0x00@0b00000
- str r1, [r0]
- ldr r0, =SRCPND
- ldr r1, =0x3ff | (1<<30) @0x1@0b11111
- str r1, [r0]
- ldr r0, =SUBSRCPND
- ldr r1, =0x1<<13
- str r1, [r0]
- ldr r0, =INTPND
- ldr r1, =0x3ff | (1<<30) @0x1@0b11111
- str r1, [r0]
- ldr r0, =INTSUBMSK
- ldr r1, =0x0<<13
- str r1, [r0]
- ldr r0, =INTMSK
- ldr r1, =0x1ffff000@0b00000
- str r1, [r0]
- MRS r1, cpsr
- BIC r1, r1, #0x80
- MSR cpsr_c, r1
- bl main
- irq:
- sub lr,lr,#4
- stmfd sp!,{r0-r12,lr}
- bl irq_isr
- ldmfd sp!,{r0-r12,pc}^
- irq_isr:
- ldr r2, =GPBDAT
- ldr r1, =0x0e0
- str r1, [r2]
- ldr r3,=0xffffff
- delay2:
- sub r3,r3,#1
- cmp r3,#0x0
- bne delay2
- //这上面的延时必须要,否则蜂鸣器的声音有问题
- ldr r0,=EINTPEND
- ldr r1,=0xf0
- str r1,[r0]
- ldr r0, =SRCPND
- ldr r1, =0x3ff | (1<<30) @0b11111
- str r1, [r0]
- ldr r0, =SUBSRCPND
- ldr r1, =0x1<<13
- str r1, [r0]
- ldr r0, =INTPND
- ldr r1, =0x3ff | (1<<30) @0b11111
- str r1, [r0]
- ldr r2, =GPBCON
- ldr r1,[r2]
- ldr r1,[r1]
- //ldr r1, =0x15400
- bic r1,r1,#0x3
- orr r1,r1,#0x2
- str r1,[r2]
- ldr r2, =GPBDAT
- ldr r1, =0x1a0
- str r1, [r2]
- ldr r1,=TCFG0
- ldr r2,=(Prescaler0<<0)
- str r2, [r1]
- ldr r1,=TCFG1
- ldr r2,=(DMA_MODE<<20) | (MUX0<<0)
- str r2, [r1]
- // ldr r3,[r0]
- // str r3,[r2]
- //mov r2, r0
- ldr r1,=TCNTB0
- ldr r2,=10
- str r2, [r1] //r0就是c调用汇编的传递参数
- //mov r0,r0,LSR #2
- ldr r1,=TCMPB0
- ldr r2,=2
- str r2, [r1]
- ldr r1,=TCON
- ldr r2,=(DZ_eable<<4) | (auto_reload<<3) | (inverter<<2) | (man_update<<1) | (start<<0)
- str r2, [r1]
- ldr r1,=TCON
- ldr r2,=(DZ_eable<<4) | (auto_reload<<3) | (inverter<<2) | (clear_man_update<<1) | (start<<0)
- str r2, [r1]
- ldr r2, =GPBDAT
- ldr r1, =0x1a0
- str r1, [r2]
- mov pc,lr
- delay:
- ldr r3,=0xffffff
- delay1:
- sub r3,r3,#1
- cmp r3,#0x0
- bne delay1
- mov pc,lr
- clock_setup:
- ldr r0,=LOCKTIME
- ldr r1,=0xffffffff
- str r1, [r0]
- ldr r0,=CLKDIVN
- ldr r1,=(DIVN_UPLL<<3) | (HDIVN<<1) | (PDIVN<<0)
- str r1, [r0]
- ldr r0,=UPLLCON
- ldr r1,=(U_MDIV<<12) | (U_PDIV<<4) | (U_SDIV<<0) @Fin=12M UPLL=48M
- str r1, [r0]
- nop
- nop
- nop
- nop
- nop
- nop
- nop
- ldr r0,=MPLLCON
- ldr r1,=(M_MDIV<<12) | (M_PDIV<<4) | (M_SDIV<<0) @Fin=12M FCLK=400M
- str r1, [r0]
- mov pc,lr
- uart_init:
- ldr r0,=GPHCON
- ldr r1,=0x2aaaa @配置GPIO复用规则为串口
- str r1, [r0]
- ldr r0,=ULCON0
- ldr r1,=(IR_MODE<<6) | (Parity_Mode<<3) | (Num_of_stop_bit<<2) | (Word_length<<0) @
- str r1, [r0]
- ldr r0,=UCON0
- ldr r1,=(FCLK_Div<<12) | (Clk_select<<10) | (Tx_Int_Type<<9) | (Rx_Int_Type<<8) | (Rx_Timeout<<7) | (Rx_Error_Stat_Int<<6) |(Loopback_Mode<<5) | (Break_Sig<<4) | (Tx_Mode<<2) | (Rx_Mode<<0)
- str r1, [r0]
- ldr r0,=UFCON0
- ldr r1,=(Tx_FIFO_Trig_Level<<6) | (Rx_FIFO_Trig_Level<<4) | (Tx_FIFO_Reset<<2) | (Rx_FIFO_Reset<<1) | (FIFO_Enable<<0) @
- str r1, [r0]
- ldr r0,=UBRDIV0
- ldr r1,=(UBRDIV<<0)
- str r1, [r0]
- mov pc,lr
- /*
- Buzzer_Freq_Set:
- //ldr r0, =GPBCON
- //ldr r1, =0x15400 @这个时候暂不配置GPB0为TOUT0,这时候只是配置GPB0为TOUT0
- //str r1, [r0]
- ldr r2, =GPBCON
- ldr r1,[r2]
- ldr r1,[r1]
- //ldr r1, =0x15400
- bic r1,r1,#0x3
- orr r1,r1,#0x2
- str r1,[r2]
- ldr r2, =GPBDAT
- ldr r1, =0x1a0
- str r1, [r2]
- ldr r1,=TCFG0
- ldr r2,=(Prescaler0<<0)
- str r2, [r1]
- ldr r1,=TCFG1
- ldr r2,=(DMA_MODE<<20) | (MUX0<<0)
- str r2, [r1]
- // ldr r3,[r0]
- // str r3,[r2]
- //mov r2, r0
- ldr r1,=TCNTB0
- ldr r2,=10
- str r2, [r1] //r0就是c调用汇编的传递参数
- //mov r0,r0,LSR #2
- ldr r1,=TCMPB0
- ldr r2,=2
- str r2, [r1]
- ldr r1,=TCON
- ldr r2,=(DZ_eable<<4) | (auto_reload<<3) | (inverter<<2) | (man_update<<1) | (start<<0)
- str r2, [r1]
- ldr r1,=TCON
- ldr r2,=(DZ_eable<<4) | (auto_reload<<3) | (inverter<<2) | (clear_man_update<<1) | (start<<0)
- str r2, [r1]
- ldr r2, =GPBDAT
- ldr r1, =0x1a0
- str r1, [r2]
- mov pc,lr
- */
- main:
- ldr r2, =GPBDAT
- ldr r1, =0x1a0
- str r1, [r2]
- bl delay
- //ldr r1,=TCON
- //ldr r2,=(DZ_eable<<4) | (auto_reload<<3) | (inverter<<2) | (man_update<<1) | (stop<<0)
- //str r2, [r1]
- /*
- ldr r2, =GPBCON
- ldr r1,[r2]
- ldr r1,[r1]
- //ldr r1, =0x15400
- bic r1,r1,#0x3
- orr r1,r1,#0x2
- str r1,[r2]
- ldr r0,=TCFG0
- ldr r1,=(Prescaler0<<0)
- str r1, [r0]
- ldr r0,=TCFG1
- ldr r1,=(DMA_MODE<<20) | (MUX0<<0)
- str r1, [r0]
- ldr r0,=TCNTB0
- ldr r1,=10
- str r1, [r0]
- ldr r0,=TCMPB0
- ldr r1,=2
- str r1, [r0]
- ldr r0,=TCON
- ldr r1,=(DZ_eable<<4) | (auto_reload<<3) | (inverter<<2) | (man_update<<1) | (start<<0)
- str r1, [r0]
- ldr r0,=TCON
- ldr r1,=(DZ_eable<<4) | (auto_reload<<3) | (inverter<<2) | (clear_man_update<<1) | (start<<0)
- str r1, [r0]
- */
- ldr lr, =loop
- // ldr pc, _rtc_uart_test
- //_rtc_uart_test: .word rtc_uart_test
- bl rtc_uart_test
- ldr r2, =GPBDAT
- ldr r1, =0x1c0
- str r1, [r2]
- bl delay
- loop:
- ldr r2, =BCDSEC @BCDMIN
- ldr r1,[r2]
- cmp r1, #0x06
- bleq ledon
- b loop @ 死循环
- ledon:
- ldr r2, =GPBDAT
- ldr r1, =0x160
- str r1, [r2]
- ldr r3,=0xffffff
- delay3:
- sub r3,r3,#1
- cmp r3,#0x0
- bne delay3
- mov pc,lr
- undefined_instruction:
- nop
- software_interrupt:
- nop
- prefetch_abort:
- nop
- data_abort:
- nop
- not_used:
- nop
- fiq:
- nop
/*watchdog timer with disable resetcopyleft@ dndxhej@gmail.com*/.equ NOINT, 0xc0.equ GPBCON,0x56000010 @led.equGPBDAT,0x56000014 @led.equ GPBUP, 0x56000018 @led.equ GPFCON, 0x56000050 @interrupt config.equEINTMASK, 0x560000a4.equ EXTINT0, 0x56000088.equ EXTINT1, 0x5600008c.equ EXTINT2, 0x56000090.equINTMSK, 0x4A000008.equ EINTPEND, 0x560000a8.equSUBSRCPND, 0x4a000018 .equINTSUBMSK, 0x4a00001c.equ SRCPND, 0X4A000000.equ INTPND, 0X4A000010.equGPHCON,0x56000070.equGPHDAT,0x56000074.equ GPB5_out, (1<<(5*2)) .equ GPB6_out, (1<<(6*2)) .equ GPB7_out, (1<<(7*2)) .equ GPB8_out, (1<<(8*2)) .equ GPBVALUE, (GPB5_out | GPB6_out | GPB7_out | GPB8_out) .equLOCKTIME, 0x4c000000.equMPLLCON, 0x4c000004.equUPLLCON, 0x4c000008.equM_MDIV, 92.equ M_PDIV, 1.equM_SDIV, 1.equU_MDIV, 56.equ U_PDIV, 2.equU_SDIV, 2.equCLKDIVN, 0x4c000014.equDIVN_UPLL, 0.equHDIVN,1.equPDIVN,1 @FCLK : HCLK : PCLK = 1:2:4.equ WTCON, 0x53000000.equ Pre_scaler, 249.equ wd_timer, 1.equ clock_select, 00 @316.equ int_gen, 1 @开中断.equ reset_enable, 0 @关掉重启信号.equ WTDAT,0x53000004.equ Count_reload,50000 @定时器定为2S PCLK = 100M PCLK/(Pre_scaler+1)/clock_select = 100M/(249+1)/16=25k 50000/25k=2s.equ WTCNT,0x53000008.equ Count,50000.equTCFG0,0x51000000.equPrescaler1,0x00 @[15:8]Timer234.equPrescaler0,249 @[7:0]Timer01.equTCFG1,0x51000004.equDMA_MODE,0x0 @[23:20]no dma channal.equMUX0,0x2 @[3:0] 1/8@定时器输入时钟周期 = PCLK/(prescaler + 1)/(divider value)@clk = 100M/(249+1)/8=25k.equTCON,0x51000008.equDZ_eable,0 @[4]关闭死区的操作.equauto_reload,1 @[3]auto_reload.equinverter,1@[2]打开电平反转.equman_update,1 @[1]手动更新.equ clear_man_update,0.equstart,1@[0]开始.equstop,0@[0]停止.equTCNTB0,0x5100000c .equTCMPB0,0x51000010.equTCNTO0,0x51000014.equ ULCON0, 0x50000000.equ IR_MODE, 0x0 @[6]正常模式.equ Parity_Mode, 0x0 @[5:3]无校验位.equ Num_of_stop_bit, 0x0 @[2]一个停止位.equ Word_length, 0b11 @[1:0]8个数据位.equ UCON0, 0x50000004.equ FCLK_Div, 0 @[15:12] 时钟源选择用PCLK,所以这里用默认值.equ Clk_select, 0b00 @[11:10] 时钟源选择使用PCLK.equ Tx_Int_Type, 1 @[9] 中断请求类型为Level.equ Rx_Int_Type, 0 @1 @[8] 中断请求类型为Level.equ Rx_Timeout, 0 @[7].equ Rx_Error_Stat_Int, 1 @[6].equ Loopback_Mode, 0 @[5] 正常模式.equ Break_Sig, 0 @[4] 不发送终止信号.equ Tx_Mode, 0b01 @[3:2] 中断请求或轮循模式.equ Rx_Mode, 0b01 @[1:0] 中断请求或轮循模式.equ UFCON0, 0x50000008.equ Tx_FIFO_Trig_Level, 0b00 @[7:6].equ Rx_FIFO_Trig_Level, 0b00 @[5:4].equ Tx_FIFO_Reset, 0b0 @[2].equ Rx_FIFO_Reset, 0b0 @[1].equ FIFO_Enable, 0b0 @[0] 非FIFO模式.equ UMCON0, 0x5000000C @这个寄存器可以不管的.equ UTRSTAT0, 0x50000010.equ UERSTAT0, 0x50000014.equ UFSTAT0, 0x50000018.equ UMSTAT0, 0x5000001C.equ UTXH0, 0x50000020 @(L 小端).equ URXH0, 0x50000024 @(L 小端).equ UBRDIV0, 0x50000028.equ UBRDIV,0x35 @PCLK=400M/4=100M UBRDIV = (int)(100M/115200/16) - 1 = 53 = 0x35.equBCDMIN,0x57000074.equBCDSEC,0x57000070//.global Buzzer_Freq_Set.global _start_start:bresetldr pc, _undefined_instructionldr pc, _software_interruptldrpc, _prefetch_abortldrpc, _data_abortldrpc, _not_used@birqldr pc, _irqldr pc, _fiq_undefined_instruction:.word undefined_instruction_software_interrupt:.word software_interrupt_prefetch_abort:.word prefetch_abort_data_abort:.word data_abort_not_used:.word not_used_irq:.word irq_fiq:.word fiq.balignl 16,0xdeadbeefreset:ldr r3, =WTCONmovr4, #0x0 strr4, [r3]@ disable watchdog ldrr0, =GPBCONldrr1, =0x15400 @这个时候暂不配置GPB0为TOUT0strr1, [r0]ldrr2, =GPBDATldrr1, =0x160strr1, [r2]bl clock_setupbl uart_initbl delay msr cpsr_c, #0xd2 @进入中断模式 ldr sp, =3072 @中断模式的栈指针定义 msr cpsr_c, #0xd3 @进入系统模式 ldr sp, =4096 @设置系统模式的栈指针@--------------------------------------------ldrr0, =GPBUPldrr1, =0x03f0 strr1, [r0] ldrr0, =GPFCONldrr1, =0x2ea@0x2 strr1, [r0] ldrr0, =EXTINT0@ldrr1, =0x8f888@0x0@0x8f888 @~(7|(7<<4)|(7<<8)|(7<<16)) //低电平触发中断ldrr1, =0xafaaa@0x0@0x8f888 //下降沿触发中断strr1, [r0] ldrr0, =EINTPENDldrr1, =0xf0@0b10000strr1, [r0] ldrr0, =EINTMASKldrr1, =0x00@0b00000strr1, [r0] ldrr0, =SRCPNDldrr1, =0x3ff | (1<<30) @0x1@0b11111strr1, [r0] ldrr0, =SUBSRCPNDldrr1, =0x1<<13strr1, [r0] ldrr0, =INTPNDldrr1, =0x3ff | (1<<30) @0x1@0b11111strr1, [r0] ldrr0, =INTSUBMSKldrr1, =0x0<<13strr1, [r0] ldrr0, =INTMSKldrr1, =0x1ffff000@0b00000strr1, [r0] MRS r1, cpsrBIC r1, r1, #0x80MSR cpsr_c, r1bl mainirq:sub lr,lr,#4stmfdsp!,{r0-r12,lr}bl irq_isrldmfd sp!,{r0-r12,pc}^ irq_isr:ldrr2, =GPBDATldrr1, =0x0e0strr1, [r2]ldr r3,=0xffffffdelay2:sub r3,r3,#1cmp r3,#0x0bne delay2//这上面的延时必须要,否则蜂鸣器的声音有问题 ldr r0,=EINTPEND ldr r1,=0xf0 str r1,[r0] ldrr0, =SRCPNDldrr1, =0x3ff | (1<<30) @0b11111strr1, [r0] ldrr0, =SUBSRCPNDldrr1, =0x1<<13strr1, [r0] ldrr0, =INTPNDldrr1, =0x3ff | (1<<30) @0b11111strr1, [r0] ldrr2, =GPBCONldrr1,[r2]ldrr1,[r1]//ldrr1, =0x15400bicr1,r1,#0x3orrr1,r1,#0x2strr1,[r2]ldrr2, =GPBDATldrr1, =0x1a0strr1, [r2]ldr r1,=TCFG0ldr r2,=(Prescaler0<<0)str r2, [r1]ldr r1,=TCFG1ldr r2,=(DMA_MODE<<20) | (MUX0<<0)str r2, [r1]//ldrr3,[r0]//strr3,[r2]//mov r2, r0ldr r1,=TCNTB0ldr r2,=10str r2, [r1] //r0就是c调用汇编的传递参数//mov r0,r0,LSR #2ldr r1,=TCMPB0ldr r2,=2str r2, [r1]ldr r1,=TCONldr r2,=(DZ_eable<<4) | (auto_reload<<3) | (inverter<<2) | (man_update<<1) | (start<<0)str r2, [r1]ldr r1,=TCONldr r2,=(DZ_eable<<4) | (auto_reload<<3) | (inverter<<2) | (clear_man_update<<1) | (start<<0)str r2, [r1]ldrr2, =GPBDATldrr1, =0x1a0strr1, [r2]mov pc,lrdelay:ldr r3,=0xffffffdelay1:sub r3,r3,#1cmp r3,#0x0bne delay1mov pc,lrclock_setup:ldr r0,=LOCKTIMEldr r1,=0xffffffffstr r1, [r0]ldr r0,=CLKDIVNldr r1,=(DIVN_UPLL<<3) | (HDIVN<<1) | (PDIVN<<0)str r1, [r0]ldr r0,=UPLLCONldr r1,=(U_MDIV<<12) | (U_PDIV<<4) | (U_SDIV<<0) @Fin=12M UPLL=48Mstr r1, [r0]nopnopnopnopnopnopnopldr r0,=MPLLCONldr r1,=(M_MDIV<<12) | (M_PDIV<<4) | (M_SDIV<<0) @Fin=12M FCLK=400Mstr r1, [r0]mov pc,lruart_init:ldr r0,=GPHCONldr r1,=0x2aaaa @配置GPIO复用规则为串口str r1, [r0]ldr r0,=ULCON0ldr r1,=(IR_MODE<<6) | (Parity_Mode<<3) | (Num_of_stop_bit<<2) | (Word_length<<0) @str r1, [r0]ldr r0,=UCON0ldr r1,=(FCLK_Div<<12) | (Clk_select<<10) | (Tx_Int_Type<<9) | (Rx_Int_Type<<8) | (Rx_Timeout<<7) | (Rx_Error_Stat_Int<<6) |(Loopback_Mode<<5) | (Break_Sig<<4) | (Tx_Mode<<2) | (Rx_Mode<<0)str r1, [r0]ldr r0,=UFCON0ldr r1,=(Tx_FIFO_Trig_Level<<6) | (Rx_FIFO_Trig_Level<<4) | (Tx_FIFO_Reset<<2) | (Rx_FIFO_Reset<<1) | (FIFO_Enable<<0) @str r1, [r0]ldr r0,=UBRDIV0ldr r1,=(UBRDIV<<0)str r1, [r0] mov pc,lr/*Buzzer_Freq_Set://ldrr0, =GPBCON//ldrr1, =0x15400 @这个时候暂不配置GPB0为TOUT0,这时候只是配置GPB0为TOUT0//strr1, [r0]ldrr2, =GPBCONldrr1,[r2]ldrr1,[r1]//ldrr1, =0x15400bicr1,r1,#0x3orrr1,r1,#0x2strr1,[r2]ldrr2, =GPBDATldrr1, =0x1a0strr1, [r2]ldr r1,=TCFG0ldr r2,=(Prescaler0<<0)str r2, [r1]ldr r1,=TCFG1ldr r2,=(DMA_MODE<<20) | (MUX0<<0)str r2, [r1]//ldrr3,[r0]//strr3,[r2]//mov r2, r0ldr r1,=TCNTB0ldr r2,=10str r2, [r1] //r0就是c调用汇编的传递参数//mov r0,r0,LSR #2ldr r1,=TCMPB0ldr r2,=2str r2, [r1]ldr r1,=TCONldr r2,=(DZ_eable<<4) | (auto_reload<<3) | (inverter<<2) | (man_update<<1) | (start<<0)str r2, [r1]ldr r1,=TCONldr r2,=(DZ_eable<<4) | (auto_reload<<3) | (inverter<<2) | (clear_man_update<<1) | (start<<0)str r2, [r1]ldrr2, =GPBDATldrr1, =0x1a0strr1, [r2]movpc,lr*/main:ldrr2, =GPBDATldrr1, =0x1a0strr1, [r2]bl delay//ldr r1,=TCON//ldr r2,=(DZ_eable<<4) | (auto_reload<<3) | (inverter<<2) | (man_update<<1) | (stop<<0)//str r2, [r1]/*ldrr2, =GPBCONldrr1,[r2]ldrr1,[r1]//ldrr1, =0x15400bicr1,r1,#0x3orrr1,r1,#0x2strr1,[r2]ldr r0,=TCFG0ldr r1,=(Prescaler0<<0)str r1, [r0]ldr r0,=TCFG1ldr r1,=(DMA_MODE<<20) | (MUX0<<0)str r1, [r0]ldr r0,=TCNTB0ldr r1,=10str r1, [r0]ldr r0,=TCMPB0ldr r1,=2str r1, [r0]ldr r0,=TCONldr r1,=(DZ_eable<<4) | (auto_reload<<3) | (inverter<<2) | (man_update<<1) | (start<<0)str r1, [r0]ldr r0,=TCONldr r1,=(DZ_eable<<4) | (auto_reload<<3) | (inverter<<2) | (clear_man_update<<1) | (start<<0)str r1, [r0]*/ ldr lr, =loop //ldrpc, _rtc_uart_test//_rtc_uart_test:.word rtc_uart_testbl rtc_uart_testldrr2, =GPBDATldrr1, =0x1c0strr1, [r2]bl delayloop:ldr r2, =BCDSEC @BCDMINldr r1,[r2]cmp r1, #0x06 bleq ledon b loop @ 死循环ledon:ldrr2, =GPBDATldrr1, =0x160strr1, [r2]ldr r3,=0xffffffdelay3:sub r3,r3,#1cmp r3,#0x0bne delay3mov pc,lrundefined_instruction:nopsoftware_interrupt:nopprefetch_abort:nopdata_abort:nopnot_used:nopfiq:nop
rtc_uart_test.s:
- #include <stdarg.h>
- #include <string.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <ctype.h>
- #include "rtc_uart_test.h"
- extern void Buzzer_Freq_Set(int freq);
- //extern void Buzzer_Freq_Set( void );
- char uart_GetByte(void)
- {
- while(!(rUTRSTAT0 & 0x1)); //Wait until THR is empty.
- return RdURXH0();
- }
- void uart_GetString(char *pt)
- {
- while(*pt)
- uart_GetByte();
- }
- void uart_SendByte(int data)
- {
- if(data=='\n')
- {
- while(!(rUTRSTAT0 & 0x2));
- WrUTXH0('\r');
- }
- while(!(rUTRSTAT0 & 0x2)); //Wait until THR is empty.
- WrUTXH0(data);
- }
- //====================================================================
- void uart_SendString(char *pt)
- {
- while(*pt)
- uart_SendByte(*pt++);
- }
- void uart_Printf(char *fmt,...)
- {
- va_list ap;
- char string[256];
- va_start(ap,fmt);
- //vsprintf(string,fmt,ap);
- uart_SendString(string);
- va_end(ap);
- }
- void uart_test(void)
- {
- char str[20] = "\nhello world\n";
- int a = 97;
- //while(1)
- // uart_SendByte(a);
- uart_SendString(str);
- char s = uart_GetByte();
- //if(s == 'a')
- if(s == 97)
- rGPBDAT = 0x1c0;
- //uart_SendByte(a);
- //uart_SendByte(97);
- //uart_SendByte('a');
- uart_SendByte((int)s);
- uart_SendByte((int)'s');
- }
- void rtc_uart_test(void)
- {
- rRTCCON = 0x1;
- rTICNT = 0x0;
- rRTCALM = 0x42;
- rBCDYEAR = 0x10 ;
- rBCDMON = 0x11 ;
- rBCDDATE = 0x07 ;
- rBCDDAY = 0x05 ;
- rBCDHOUR = 0x12 ;
- rBCDMIN = 0x03 ;
- rBCDSEC = 0x00 ;
- rALMMIN = 0x04;
- uart_SendString("begin\n");
- //uart_Printf("year:%d\n",rBCDYEAR);
- }
- void pwm_uart_test(void)
- {
- int freq = 10;
- int i;
- for(i=0; i<100;i++)
- uart_SendString("app\n");
- //Buzzer_Freq_Set( freq ) ;
- //Buzzer_Freq_Set( ) ;
- //uart_test();
- uart_SendString("start\n");
- /*
- int i;
- for(i=0;i<1000;i++)
- uart_SendString("wait\n");
- while( 1 )
- {
- char key = uart_GetByte();
- uart_SendByte(key);
- if( key == 'a' || key == 'A' )
- {
- if( freq < 2000 ) //lci 20000
- freq += 10 ;
- uart_SendByte('a');
- Buzzer_Freq_Set( freq ) ;
- }
- if( key == 'b' || key == 'B' )
- {
- if( freq > 11 )
- freq -= 10 ;
- uart_SendByte('b');
- Buzzer_Freq_Set( freq ) ;
- }
- //uart_SendString( "\tFreq = %d\n", freq ) ;
- //if( key == ESC_KEY )
- //{
- // Buzzer_Stop() ;
- // return ;
- //}
- }
- */
- }
#include <stdarg.h>#include <string.h>#include <stdlib.h>#include <stdio.h>#include <ctype.h>#include "rtc_uart_test.h"extern void Buzzer_Freq_Set(int freq);//extern void Buzzer_Freq_Set( void );char uart_GetByte(void){while(!(rUTRSTAT0 & 0x1)); //Wait until THR is empty.return RdURXH0();}void uart_GetString(char *pt){while(*pt)uart_GetByte();}void uart_SendByte(int data){if(data=='\n'){while(!(rUTRSTAT0 & 0x2));WrUTXH0('\r');}while(!(rUTRSTAT0 & 0x2)); //Wait until THR is empty.WrUTXH0(data);} //====================================================================void uart_SendString(char *pt){while(*pt) uart_SendByte(*pt++);}void uart_Printf(char *fmt,...){va_list ap;char string[256];va_start(ap,fmt);//vsprintf(string,fmt,ap);uart_SendString(string);va_end(ap);}void uart_test(void){char str[20] = "\nhello world\n";int a = 97;//while(1)//uart_SendByte(a);uart_SendString(str);char s = uart_GetByte();//if(s == 'a')if(s == 97)rGPBDAT = 0x1c0;//uart_SendByte(a);//uart_SendByte(97);//uart_SendByte('a');uart_SendByte((int)s);uart_SendByte((int)'s');}void rtc_uart_test(void){rRTCCON = 0x1;rTICNT = 0x0;rRTCALM = 0x42;rBCDYEAR = 0x10 ;rBCDMON = 0x11 ;rBCDDATE = 0x07 ;rBCDDAY = 0x05 ;rBCDHOUR = 0x12 ;rBCDMIN = 0x03 ;rBCDSEC = 0x00 ;rALMMIN = 0x04;uart_SendString("begin\n");//uart_Printf("year:%d\n",rBCDYEAR);}void pwm_uart_test(void){int freq = 10;int i;for(i=0; i<100;i++)uart_SendString("app\n");//Buzzer_Freq_Set( freq ) ;//Buzzer_Freq_Set( ) ;//uart_test();uart_SendString("start\n");/*int i;for(i=0;i<1000;i++)uart_SendString("wait\n"); while( 1 ) {char key = uart_GetByte();uart_SendByte(key);if( key == 'a' || key == 'A' ){if( freq < 2000 ) //lci 20000freq += 10 ;uart_SendByte('a');Buzzer_Freq_Set( freq ) ;}if( key == 'b' || key == 'B' ){if( freq > 11 )freq -= 10 ;uart_SendByte('b');Buzzer_Freq_Set( freq ) ;}//uart_SendString( "\tFreq = %d\n", freq ) ;//if( key == ESC_KEY )//{//Buzzer_Stop() ;//return ;//}}*/}
在调这个过程中,因为RTCCON中的CLKRST最初被我置为1,导致时间根本不走,为了查这个问题,专门通过led显示来判断这个时间是不是不走:
ldr r2, =BCDSEC @BCDMIN
ldr r1,[r2]
cmp r1, #0x06
bleq ledon
通过这里的判断,可以明确时间有被设进去,可是时间不走.经过google,才确定是寄存器的设置问题.
到此,rtc的闹钟也实现了功能.明天就用这个做闹钟吧~~
- GNU ARM汇编--(十)s3c2440的RTC
- GNU ARM汇编--(十)s3c2440的RTC
- GNU ARM汇编--(十)s3c2440的RTC
- GNU ARM汇编--(八)s3c2440的watchdog
- GNU ARM汇编--(九)s3c2440的PWM
- GNU ARM汇编--(八)s3c2440的watchdog
- GNU ARM汇编--(九)s3c2440的PWM
- GNU ARM汇编--(八)s3c2440的watchdog
- GNU ARM汇编--(六)s3c2440的时钟控制
- GNU ARM汇编--(七)s3c2440的串口控制
- GNU ARM汇编--(六)s3c2440的时钟控制
- GNU ARM汇编--(七)s3c2440的串口控制
- GNU ARM汇编--(六)s3c2440的时钟控制
- GNU ARM汇编--(七)s3c2440的串口控制
- GNU ARM汇编--(二十)总结
- ARM汇编和Gnu汇编的转换
- ARM汇编和Gnu汇编的转换
- GNU GAS (GNU ARM汇编)
- COCOS2D-X 3.0RC开发指南:WINDOWS下ANDROID环境搭建
- OC中的类别(category)
- Android Paint和Color类
- 统计二叉树中叶子节点的个数
- java 面试中经常被问到的面试题
- GNU ARM汇编--(十)s3c2440的RTC
- Java Web中文乱码问题
- C++学习笔记4--静态属性 静态方法 虚方法 抽象方法 多态性 析构函数 运算符重载 多继承 虚继承
- GNU ARM 汇编快速入门
- MySQL存储过程中的IN,OUT,INOUT类型 用法
- 嵌入式Web服务器BOA和CGI编程开发
- 一起来写2048(160行python代码)
- “SpringBoard 无法启动应用程序 错误-3″的解决办法
- UIImageView响应点击事件