mini2440 uart串口实验(fifo模式+中断)

这次是S3C2440上面的uart0的FIFO模式的实验,程序设置串口0的输入fifo中包含的数据个数在从小于16字节的状态变换为大于等于16字节的状态的瞬间触发一个脉冲中断,在这个中断中,把输入fifo 中的数据全部写入到输出fifo中,在输出fifo 从非空状态变换成空的状态的瞬间会触发一个脉冲中断,在中断中我让灯闪一下,实验的正确现象是从超级终端往2440的串口0发数据,每发16个字节的数据,串口就会把这16个字节全部打印出来,同时由于输出fifo变空,会触发灯闪一下,经过测试,实验现象和上面说的是一致的。要注意在往utxh0寄存器写数据的时候要先检查输出fifo是不是已经满了,如果已经满了就要等待,否则会造成输出fifo对头的数据提前出队,出队的数据就丢掉了,输入fifo中的数据个数要从UFSTAT寄存器里面的相应字段去读,uart的dma模式怎么用的还需要研究一下。


Makefile

uart_interrupt.bin : start.s function.c
	arm-linux-gcc -g -c -o start.o start.s
	arm-linux-gcc -g -c -o function.o function.c
	arm-linux-ld -Ttext 0x30000000 -g start.o function.o -o uart_fifo.elf
	arm-linux-objcopy -O binary -S uart_fifo.elf uart_fifo.bin
	arm-linux-objdump -D -m arm uart_fifo.elf > uart_fifo.dis
clean : 
	rm -f *.o *.bin *.dis *.elf

start.s

.text
.global _start
_start:
	b		reset
	b		.
	b		.
	b		.
	b		.
	b		.
	b		handle_irq
	b		.

reset:
	@shut down the watchdog
	ldr		r0, =0x53000000
	ldr		r1, =0x00000000
	str		r1, [r0]

	@init the stack address
	ldr		r1, =4096
	ldr		r0, =0x40000000
	add		sp, r1, r0

	bl		init_led
	bl		init_clock
	bl		display_led1
	bl		init_sdram
	bl		display_led2

	@reset the stack pointer
	ldr		sp, =0x34000000 @change stack to the end of sdram
	msr		cpsr_c, #0xd2
	ldr		sp, =0x33F00000 @change the stack pointer of irq mode
	msr		cpsr_c, #0xd3 @change cpu back to svc mode


	bl		copy_code2sdram @copy 8KB data from norflash to sdram
	
	ldr		pc, =on_sdram
on_sdram:
	bl		init_uart0
	bl		init_interrupt
	msr		cpsr_c, #0x53 @clear the irq disable bit in cpsr


	bl		main
halt_loop:
	b		halt_loop


handle_irq:
	sub		lr, lr, #4 @set the address(int main function) to return when handle_irq ends
	stmdb	sp!, {r0-r12, lr} 	@save the universal registers and lr_irq to the stack of irq mode
	bl		handle_irq_func		@branch to the irq handleing function achieved in function.c 
	ldmia	sp!, {r0-r12, pc}^	@resume the universal registers and save lr to pc while copying spsr to cpsr

function.c

//gpb registers
#define		GPBCON		(*((volatile unsigned long *)0x56000010))	
#define		GPBDAT		(*((volatile unsigned long *)0x56000014))

//mem controler registers
#define		BWSCON		(*((volatile unsigned long *)0x48000000))
#define		BANKCON0	(*((volatile unsigned long *)0x48000004))
#define		BANKCON1	(*((volatile unsigned long *)0x48000008))
#define		BANKCON2	(*((volatile unsigned long *)0x4800000C))
#define		BANKCON3	(*((volatile unsigned long *)0x48000010))
#define		BANKCON4	(*((volatile unsigned long *)0x48000014))
#define		BANKCON5	(*((volatile unsigned long *)0x48000018))
#define		BANKCON6	(*((volatile unsigned long *)0x4800001C))
#define		BANKCON7	(*((volatile unsigned long *)0x48000020))
#define		REFRESH		(*((volatile unsigned long *)0x48000024))
#define		BANKSIZE	(*((volatile unsigned long *)0x48000028))
#define		MRSRB6		(*((volatile unsigned long *)0x4800002C))
#define		MRSRB7		(*((volatile unsigned long *)0x48000030))

//gpg registers
#define		GPGCON		(*((volatile unsigned long *)0x56000060))

//gph registers
#define		GPHCON		(*((volatile unsigned long *)0x56000070))
#define		GPHUP		(*((volatile unsigned long *)0x56000078))

//interrupt related registers
#define		EINTMASK	(*((volatile unsigned long *)0x560000A4))
#define		INTMSK		(*((volatile unsigned long *)0x4A000008))
#define		INTMOD		(*((volatile unsigned long *)0x4A000004))
#define		INTOFFSET	(*((volatile unsigned long *)0x4A000014))
#define		SRCPND		(*((volatile unsigned long *)0x4A000000))
#define		INTPND		(*((volatile unsigned long *)0x4A000010))
#define		EINTPEND	(*((volatile unsigned long *)0x560000A8))
#define		INTSUBMSK	(*((volatile unsigned long *)0x4A00001C))
#define		SUBSRCPND	(*((volatile unsigned long *)0x4A000018))


//PLL related registers
#define		LOCKTIME	(*((volatile unsigned long *)0x4C000000))
#define		MPLLCON		(*((volatile unsigned long *)0x4C000004))
#define		CLKDIVN		(*((volatile unsigned long *)0x4C000014))

//uart0 related registers
#define		ULCON0		(*((volatile unsigned long *)0x50000000))
#define		UCON0		(*((volatile unsigned long *)0x50000004))
#define		UFCON0		(*((volatile unsigned long *)0x50000008))
#define		UMCON0		(*((volatile unsigned long *)0x5000000C))
#define		UBRDIV0		(*((volatile unsigned long *)0x50000028))
#define		UTRSTAT0	(*((volatile unsigned long *)0x50000010))
#define		URXH0		(*((volatile unsigned char *)0x50000024))
#define		UTXH0		(*((volatile unsigned char *)0x50000020))
#define		UFSTAT0		(*((volatile unsigned long *)0x50000018))


void blink(void);
void display_led(int);

void init_sdram(){
	BWSCON		= 0x22011110;
	BANKCON0	= 0x00000700;
	BANKCON1	= 0x00000700;
	BANKCON2	= 0x00000700;
	BANKCON3	= 0x00000700;
	BANKCON4	= 0x00000700;
	BANKCON5	= 0x00000700;
	BANKCON6	= 0x00018005;
	BANKCON7	= 0x00018005;

	//when hcls is 12MHz
	//REFRESH		= 0x008C07A3;

	//when hckl is 100MHz
	REFRESH		= 0x008C04F4; 

	BANKSIZE	= 0x000000B1;
	MRSRB6		= 0x00000030;
	MRSRB7		= 0x00000030;
}


void init_interrupt(){
	//set the gpio pins of the six keys to interrupt mode 
	GPGCON = (1<<(0*2+1) | 1<<(3*2+1) | 1<<(5*2+1) | 1<<(6*2+1) | 1<<(7*2+1) | 1<<(11*2+1));

	//set EINTMASK register to enable external interrupt
	EINTMASK &= (~(1<<8 | 1<<11 | 1<<13 | 1<<14 | 1<<15 | 1<<19));

	//set INTMSK register to enable eint8_23
	INTMSK &= (~(1<<5));

	//enable uart0 interrupt
	INTMSK &= (~(1<<28));
	//enable rxd0 interrupt and txd0 interrupt
	INTSUBMSK &= (~(0b11));

	//set INTMOD register to set int8_23 to irq mode
	INTMOD &= (~(1<<5));
}


void init_uart0(){
	GPHCON |= ( (1<<5) | (1<<7) );
	GPHCON &= ~( (1<<4) | (1<<6) );
	GPHUP |= ( (1<<2) | (1<<3) );

	ULCON0 = 0x03; //8 data bits, 1 stop bits, no check
	UCON0 = 0X05; //polling mode or interrupt mode
	UCON0 |= (1<<6); //enable rx0 time out interrupt
	UFCON0 = 0b00100001; //enable fifo, set receive fifo trigger to be 16 bytes and set transport fifo trigger to zero 
	UMCON0 = 0x00; //disable AFC
	UBRDIV0 = 0x1A; //bit rate is 115200(pclk is 50MHz)
}

unsigned char getchar_uart0(){
	//while( !(UTRSTAT0&1) );
	return URXH0;
}

void putchar_uart0_fifo(unsigned char ch){
	while( UFSTAT0&(1<<6) ); //wait while transport fifo is full 
	UTXH0 = ch;
}

void puts_uart0_fifo(char *str){
	int i;
	for(i=0; str[i]!='\0'; i++){
		putchar_uart0_fifo(str[i]);
	}
}


void handle_key(){
	int eint_v;

	eint_v = EINTPEND;

	if(eint_v & (1<<8)){
		display_led(1);
		EINTPEND = 1<<8;
		return;		
	}

	if(eint_v & (1<<11)){
		display_led(2);
		EINTPEND = 1<<11;
		return;		
	}

	if(eint_v & (1<<13)){
		display_led(3);
		EINTPEND = 1<<13;
		return;		
	}

	if(eint_v & (1<<14)){
		display_led(4);
		EINTPEND = 1<<14;
		return;		
	}

	if(eint_v & (1<<15)){
		display_led(5);
		EINTPEND = 1<<15;
		return;		
	}

	if(eint_v & (1<<19)){
		display_led(6);
		EINTPEND = 1<<19;
		return;		
	}
}

#define		RX0_FIFO_SIZE	64
#define		TX0_FIFO_SIZE	64
void handle_uart0_interrupt(){
	int i, fifo_count;
	unsigned char ch;

	if(SUBSRCPND & (1<<1)){ //txd0 interrupt will happen when transport fifo is empty
		//do nothing
		if( (UFSTAT0&(0b111111<<8)) == 0 )
			blink();
	}



	if(SUBSRCPND & (1<<0)){ //rxd0 interrupt
		if( UFSTAT0 & (1<<6) ){ //rx0 fifo is full
			for(i=0; i> 0); //get the data length in fifo
			for(i=0; i


你可能感兴趣的:(mini2440)