一、S3C2440中断控制要点
S3C2440A 中的中断控制器可以从60 个中断源接收中断请求。这些中断源由内部外设提供,例如DMA 控制器、UART、IIC 等。在这些中断源中,UARTn、AC97 和外部中断EINTn 对于中断控制器来说是或逻辑。当接收来自内部外设和外部中断请求引脚的多个中断请求时,在仲裁过程后中断控制器请求ARM920T 的FIR 或IRQ 中断。
图1 中断流程图
如果在ARM920T 的CPU 中的程序状态寄存器的F 位置1,CPU 不能接收来自中断控制器的FIR,如果程序状态寄存器的L 位被置1,则CPU 不能接收来自中断控制器的IRQ。所以,通过清0 程序状态寄存器中的F 位和L 位且清0INTMSK 寄存器中的相应位,中断控制器可以接收中断。
二、寄存器设置
SRCPND 0X4A000000 R/W Indicate the interrupt request status.
0 = The interrupt has not been requested.
1 = The interrupt source has asserted。
三、中断程序源代码
start.S
- /*
- *************************************************************************
- *
- * lcl bootloader
- *
- *************************************************************************
- */
- .globl _start
- _start: b start_code
- HandleUndef:
- b HandleUndef @ 0x04: 指未定义指令终止模式的向量地址
- HandleSWI:
- b HandleSWI @ 0x08 指管理模式,通过SWI指令进入
- HandlePerfetchAbort:
- b HandlePerfetchAbort @ 0x0c: 指令预取终止导致的异常的向量地址
- HandleDataAbort:
- b HandleDataAbort @ 0x10: 数据访问终止导致的异常的向量地址
- HandleNotUsed:
- b HandleNotUsed @ 0x14: 保留
- b HandleIRQ @ 0x18: 中断模式的向量地址
- HandleFIQ:
- b HandleFIQ @ 0x1c: 快中断模式的向量地址
- start_code:
- bl clock_init
- bl cpu_init_crit
- msr cpsr_c,#0xd2 @进入中断模式
- ldr sp,=3072 @设置中断模式堆栈指针
- msr cpsr_c,#0xdf @进入系统模式
- msr cpsr_c,#0x5f @开IRQ中断
- /*
- *run in sdram
- */
- ldr sp, =4096
- ldr lr, =halt_loop @返回地址
- ldr pc, = Main
- halt_loop:
- b halt_loop
- HandleIRQ:
- sub lr,lr,#4
- stmdb sp!,{r0-r12,lr} @保存使用到的寄存器至中断堆栈区
- ldr lr,=int_return @设置ISR的返回地址
- ldr pc,=EINT_Handle @调用中断服务函数
- int_return:
- ldmia sp!,{r0-r12,pc}^ @中断返回,恢复寄存器值,^表示将spsr的值复制到cpsr
- clock_init:
- #define pWTCON 0x53000000
- #define CLKDIVN 0x4C000014 /* clock divisor register */
- #define CLK_CTL_BASE 0x4C000000 /* clock base address */
- #define MDIV_405 0x7f << 12 /* MDIV 0x7f*/
- #define PSDIV_405 0x21 /* PDIV SDIV 0x2 0x1 */
- /* turn off the watchdog */
- ldr r0, =pWTCON
- mov r1, #0x0
- str r1, [r0]
- /* FCLK:HCLK:PCLK = 1:4:8 */
- ldr r0, =CLKDIVN
- mov r1, #5 //1:4:8
- str r1, [r0]
- mrc p15, 0, r1, c1, c0, 0 //切换到实时总线HCLK
- orr r1, r1, #0xc0000000
- mcr p15, 0, r1, c1, c0, 0
- mov r1, #CLK_CTL_BASE
- mov r2, #MDIV_405
- add r2, r2, #PSDIV_405
- str r2, [r1, #0x04] /* MPLLCON address Mpll=405MHZ */
- mov pc, lr
- /*
- *MMU and SDRAM initialize
- */
- cpu_init_crit:
- /*
- * flush v4 I/D caches
- */
- mov r0, #0
- mcr p15, 0, r0, c7, c7, 0 /* flush v3/v4 cache */
- mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */
- /*
- * disable MMU stuff and caches
- */
- mrc p15, 0, r0, c1, c0, 0
- bic r0, r0, #0x00002300 @ clear bits 13, 9:8 (--V- --RS)
- bic r0, r0, #0x00000087 @ clear bits 7, 2:0 (B--- -CAM)
- orr r0, r0, #0x00000002 @ set bit 2 (A) Align
- orr r0, r0, #0x00001000 @ set bit 12 (I) I-Cache
- mcr p15, 0, r0, c1, c0, 0
- /*
- * before relocating, we have to setup RAM timing
- * because memory timing is board-dependend, you will
- * find a lowlevel_init.S in your board directory.
- */
- mov ip, lr
- bl memsetup /* memory control configuration */
- mov lr, ip
- mov pc, lr
- memsetup:
- /* memory control configuration */
- /* make r0 relative the current location so that it */
- /* reads SMRDATA out of FLASH rather than memory ! */
- #define MEM_CTL_BASE 0x48000000
- mov r1,#MEM_CTL_BASE
- adr r2,mem_cfg_val
- add r3,r1,#52
- 1:
- ldr r4, [r2], #4
- str r4, [r1], #4
- cmp r1, r3
- bne 1b
- mov pc,lr
- .align 4
- /* the literal pools origin */
- mem_cfg_val:
- .long 0x22011110
- .long 0x00000700
- .long 0x00000700
- .long 0x00000700
- .long 0x00000700
- .long 0x00000700
- .long 0x00000700 @BANK5
- .long 0x00018005
- .long 0x00018005
- .long 0x00ac03f4 @REFRESH // 12MHZ 0x00ac07a3
- .long 0x000000B1
- .long 0x00000030
- .long 0x00000030
def.h
- #ifndef __DEF_H__
- #define __DEF_H__
- #define U32 unsigned int
- #define U16 unsigned short
- #define S32 int
- #define S16 short int
- #define U8 unsigned char
- #define S8 char
- #define __REGb(x) (*(volatile unsigned char *)(x))
- #define __REGw(x) (*(volatile unsigned short *)(x))
- #define __REGi(x) (*(volatile unsigned int *)(x))
- #endif /*__DEF_H__*/
s3c2440_addr.h
- #ifndef _s3c2440_addr_h_
- #define _s3c2440_addr_h_
- #include "def.h"
- /***********uart address*********************/
- #define UART_CTL_BASE 0x50000000
- #define UART0_CTL_BASE UART_CTL_BASE
- #define UART1_CTL_BASE UART_CTL_BASE + 0x4000
- #define UART2_CTL_BASE UART_CTL_BASE + 0x8000
- #define ULCON0 __REGi(UART0_CTL_BASE + 0x00) /* R/W, UART line control register */
- #define UCON0 __REGi(UART0_CTL_BASE + 0x04) /* R/W, UART control register */
- #define UFCON0 __REGi(UART0_CTL_BASE + 0x08) /* R/W, UART FIFO control register */
- #define UMCON0 __REGi(UART0_CTL_BASE + 0x0C) /* R/W, UART modem control register */
- #define UTRSTAT0 __REGi(UART0_CTL_BASE + 0x10) /* R , UART Tx/Rx status register */
- #define UERSTAT0 __REGi(UART0_CTL_BASE + 0x14) /* R , UART Rx error status register */
- #define UFSTAT0 __REGi(UART0_CTL_BASE + 0x18) /* R , UART FIFO status register */
- #define UMSTAT0 __REGi(UART0_CTL_BASE + 0x1C) /* R , UART Modem status register */
- #define UTXH0 __REGb(UART0_CTL_BASE + 0x20) /* W 8bit , UART transmit(little-end) buffer */
- #define URXH0 __REGb(UART0_CTL_BASE + 0x24) /* R 8bit , UART receive(little-end) buffer */
- #define UBRDIV0 __REGi(UART0_CTL_BASE + 0x28) /* R/W, Baud rate divisor register */
- /* ... */
- #define UTRSTAT_TX_EMPTY (1 << 2)
- #define UTRSTAT_RX_READY (1 << 0)
- #define UART_ERR_MASK 0xF
- #define UART_BAUD_RATE 115200
- #define UART_PCLK_405_148 50625000
- #define UART_PCLK UART_PCLK_405_148
- #define UART_BRD ((UART_PCLK / (UART_BAUD_RATE * 16)) - 1)
-
- /***********GPB GPG GPH GPIO address*********************/
- #define GPBCON (*(volatile unsigned long *) 0x56000010)
- #define GPBDAT (*(volatile unsigned long *) 0x56000014)
- #define GPBUP (*(volatile unsigned long *) 0x56000018)
- #define GPGCON (*(volatile unsigned long *) 0x56000060)
- #define GPGDAT (*(volatile unsigned long *) 0x56000064)
- #define GPGUP (*(volatile unsigned long *) 0x56000068)
- #define GPHCON __REGi(0x56000070) //R/W Configures the pins of port H 0x0
- #define GPHDAT __REGi(0x56000074) //R/W The data register for port H Undef.
- #define GPHUP __REGi(0x56000078) //R/W pull-up disable register for port H
- /* .. */
- #define GPX_up 0x00000000 // up
- #define GPX_mask(pin) (~(3<<((pin)*2)))
- #define BIT_mask(pin) (~(1<<(pin)))
-
-
- #define GPH_tx0 (2<<(2*2)) //10 = TXD[0]
- #define GPH_rx0 (2<<(3*2)) //10 = RXD[0]
- #define GPB5_out (1<<(5*2))
- #define GPB6_out (1<<(6*2))
- #define GPB7_out (1<<(7*2))
- #define GPB8_out (1<<(8*2))
- #define GPG0_in (0<<(0*2))
- #define GPG3_in (0<<(3*2))
- #define GPG5_in (0<<(5*2))
- #define GPG6_in (0<<(6*2))
- #define GPG0_eint8 (2<<(0*2))
- #define GPG3_eint11 (2<<(3*2))
- #define GPG5_eint13 (2<<(5*2))
- #define GPG6_eint14 (2<<(6*2))
- /*****************timer register*****************/
- #define TCFG0 (*(volatile unsigned long *) 0x51000000)
- #define TCFG1 (*(volatile unsigned long *) 0x51000004)
- #define TCON (*(volatile unsigned long *) 0x51000008)
- #define TCNTB0 (*(volatile unsigned long *) 0x5100000C)
- #define TCMPB0 (*(volatile unsigned long *) 0x51000010)
- #define TCNTO0 (*(volatile unsigned long *) 0x51000014)
- /* .. */
- #define GPB0_pwm (2<<(0*2))
- /*****************interrupt register*****************/
- #define INT_CTL_BASE 0x4A000000
- #define SRCPND __REGi(INT_CTL_BASE + 0x00)
- #define INTMOD __REGi(INT_CTL_BASE + 0x04)
- #define INTMSK __REGi(INT_CTL_BASE + 0x08)
- #define PRIORITY __REGi(INT_CTL_BASE + 0x0c)
- #define INTPND __REGi(INT_CTL_BASE + 0x10)
- #define INTOFFSET __REGi(INT_CTL_BASE + 0x14)
- #define SUBSRCPND __REGi(INT_CTL_BASE + 0x18)
- #define INTSUBMSK __REGi(INT_CTL_BASE + 0x1c)
- #define EINTMASK __REGi(0x560000A4) /*External interrupt mask register*/
- #define EINTPEND __REGi(0x560000A8) /*External interrupt pending register*/
- /* ... */
- #define INT_ADCTC (1 << 31) /* ADC EOC interrupt */
- #define INT_RTC (1 << 30) /* RTC alarm interrupt */
- #define INT_SPI1 (1 << 29) /* UART1 transmit interrupt */
- #define INT_UART0 (1 << 28) /* UART0 transmit interrupt */
- #define INT_IIC (1 << 27) /* IIC interrupt */
- #define INT_USBH (1 << 26) /* USB host interrupt */
- #define INT_USBD (1 << 25) /* USB device interrupt */
- #define INT_RESERVED24 (1 << 24)
- #define INT_UART1 (1 << 23) /* UART1 receive interrupt */
- #define INT_SPI0 (1 << 22) /* SPI interrupt */
- #define INT_MMC (1 << 21) /* MMC interrupt */
- #define INT_DMA3 (1 << 20) /* DMA channel 3 interrupt */
- #define INT_DMA2 (1 << 19) /* DMA channel 2 interrupt */
- #define INT_DMA1 (1 << 18) /* DMA channel 1 interrupt */
- #define INT_DMA0 (1 << 17) /* DMA channel 0 interrupt */
- #define INT_LCD (1 << 16) /* reserved for future use */
- #define INT_UART2 (1 << 15) /* UART 2 interrupt */
- #define INT_TIMER4 (1 << 14) /* Timer 4 interrupt */
- #define INT_TIMER3 (1 << 13) /* Timer 3 interrupt */
- #define INT_TIMER2 (1 << 12) /* Timer 2 interrupt */
- #define INT_TIMER1 (1 << 11) /* Timer 1 interrupt */
- #define INT_TIMER0 (1 << 10) /* Timer 0 interrupt */
- #define INT_WDT (1 << 9) /* Watch-Dog timer interrupt */
- #define INT_TICK (1 << 8) /* RTC time tick interrupt */
- #define INT_BAT_FLT (1 << 7)
- #define INT_RESERVED6 (1 << 6) /* Reserved for future use */
- #define INT_EINT8_23 (1 << 5) /* External interrupt 8 ~ 23 */
- #define INT_EINT4_7 (1 << 4) /* External interrupt 4 ~ 7 */
- #define INT_EINT3 (1 << 3) /* External interrupt 3 */
- #define INT_EINT2 (1 << 2) /* External interrupt 2 */
- #define INT_EINT1 (1 << 1) /* External interrupt 1 */
- #define INT_EINT0 (1 << 0) /* External interrupt 0 */
- #define INT_ADC (1 << 10)
- #define INT_TC (1 << 9)
- #define INT_ERR2 (1 << 8)
- #define INT_TXD2 (1 << 7)
- #define INT_RXD2 (1 << 6)
- #define INT_ERR1 (1 << 5)
- #define INT_TXD1 (1 << 4)
- #define INT_RXD1 (1 << 3)
- #define INT_ERR0 (1 << 2)
- #define INT_TXD0 (1 << 1)
- #define INT_RXD0 (1 << 0)
- #endif
usrt0_init.h
- #ifndef __UART0_INIT_H__
- #define __UART0_INIT_H__
- void uart0_init();
- void Uart_SendString(char *pt);
- #endif
uart0_init.c
- /*
- * uart0 lib
- */
- #include "s3c2440_addr.h"
- void uart0_init()
- {
- GPHCON &= (GPX_mask(2) & GPX_mask(3));
- GPHCON |= GPH_tx0 | GPH_rx0;
- GPHUP |= 0x0c;
- ULCON0 = (0<< 3) | (0<< 2) | (3<< 0); // 8N1 ;normal mode , no parity , 1stop bit,8bit
- UCON0 = (0<<10) | (1<< 9) | (1<< 6) | (1<< 2) | (1<< 0); // Select PCLK for the UART baud rate,polling mode, [9][6]:1 1
- UFCON0 = 0x00; // disable FIFO
- UMCON0 = 0x00; // disable AFC
- UBRDIV0 = UART_BRD; // baud rate divisior 115200
- }
- static inline void putc(char data)
- {
- while (!(UTRSTAT0 & 0x4)) ; //Wait until THR is empty.
- UTXH0 = data;
- }
- static inline unsigned char getc(void)
- {
- while (!(UTRSTAT0 & (1))) ; //Wait until THx is empty.
- return URXH0;
- }
- void Uart_SendString(char *pt)
- {
- while (*pt)
- putc(*pt++);
- }
mem.lds
- /*
- *lcl bootloader mem.lds
- */
- OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
- OUTPUT_ARCH(arm)
- ENTRY(_start)
- SECTIONS {
- . = 0x00000000;
- . = ALIGN(4);
- .init : AT(0) {start.o}
- . = 0x00000800;
- .text : AT(2048) { *(.text) }
-
- .rodata ALIGN(4) : AT((LOADADDR(.text)+SIZEOF(.text)+3)&~(0x03)) { *(.rodata*) }
- .data ALIGN(4) : AT((LOADADDR(.rodata)+SIZEOF(.rodata)+3)&~(0x03)) { *(.data) }
-
- . = ALIGN(4);
- __bss_start = .;
- .bss :{ *(.bss) *(COMMON)}
- __bss_end = .;
- }
Makefile
- objs := start.o main.o uart0_init.o interrupt.o
- sdram.bin : $(objs)
- arm-linux-ld -Tmem.lds -o sdram_elf $^
- arm-linux-objcopy -O binary -S sdram_elf $@
- arm-linux-objdump -D -m arm sdram_elf > sdram.dis
- arm-linux-objdump -dx sdram_elf > mem_bin.map
- rm -f sdram.dis sdram_elf *.o
- %.o:%.c
- arm-linux-gcc -Wall -c -O2 -o $@ $<
- %.o:%.S
- arm-linux-gcc -Wall -c -O2 -o $@ $<
- clean:
- rm -f sdram.bin mem_bin.map
main.c
- /*
- GPBCON 0x56000010 Port B control
- GPBDAT 0x56000014 Port B data
- GPBUP 0x56000018 Pull-up control B
- LED1 GPB5 LED2 GPB6 LED3 GPB7 LED4 GPB8
- */
- #include "uart0_init.h"
- #include "s3c2440_addr.h"
- #include "interrupt.h"
- void leds_init()
- {
- /*GPBCON &= (GPX_mask(5) & GPX_mask(6) & GPX_mask(7) & GPX_mask(8));
- GPBCON |= (GPB5_out | GPB6_out | GPB7_out | GPB8_out);
- GPBUP = GPX_up;
- GPBDAT |=( 0xf << 5 );*/
- GPBCON = (GPB5_out | GPB6_out | GPB7_out | GPB8_out);
- GPBUP = GPX_up;
- }
- void buttons_eint_init()
- {
- GPGCON &= (GPX_mask(0) & GPX_mask(3) & GPX_mask(5) & GPX_mask(6));
- GPGCON |= (GPG0_eint8 | GPG3_eint11 | GPG5_eint13 | GPG6_eint14);
- }
- int Main()
- {
- unsigned long dwDat;
- leds_init();
- buttons_eint_init();
- uart0_init();
- irq_init();
-
- GPBDAT |=( 0xf << 5 );
-
- Uart_SendString("\r wait interrupt. \r\n");
- while (1)
- {
- GPBDAT |=( 0xf << 5 );
- }
- return 0;
- }
以下为能直接运行的二进制文件,下载到Nand Flash 的 Black0 直接以Nand Flash运行。
阅读(1521) | 评论(0) | 转发(0) |