这次是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<RX0_FIFO_SIZE; i++){
 - ch = URXH0;
 - putchar_uart0_fifo(ch);
 - }
 - }
 - else{ //rx0 fifo is not full
 - //blink();
 - fifo_count = ((UFSTAT0 & (0b111111<<0)) >> 0); //get the data length in fifo
 - for(i=0; i<fifo_count; i++){
 - ch = URXH0;
 - putchar_uart0_fifo(ch);
 - }
 - }
 - }
 - SUBSRCPND = SUBSRCPND;
 - }
 - void handle_irq_func(){
 - int offset_v;
 - offset_v = INTOFFSET;
 - switch(offset_v){
 - case 5: //external interrupt
 - handle_key();
 - break;
 - case 28:
 - handle_uart0_interrupt();
 - break;
 - default:
 - break;
 - }
 - //clear the interrupt
 - SRCPND = 1<<offset_v;
 - INTPND = 1<<offset_v;
 - }
 - void delay(int n){
 - int i, j;
 - for(i=0; i<n; i++){
 - for(j=0; j<1000; j++){}
 - }
 - }
 - void blink(){
 - GPBDAT = 0xffffffff;
 - GPBDAT = 0x00000000;
 - delay(1);
 - GPBDAT = 0xffffffff;
 - delay(1);
 - }
 - void display_led1(){
 - GPBDAT = ~(1<<5);
 - delay(1);
 - }
 - void display_led2(){
 - GPBDAT = ~(3<<5);
 - delay(1);
 - }
 - void display_led3(){
 - GPBDAT = ~(7<<5);
 - delay(1);
 - }
 - void display_led4(){
 - GPBDAT = ~(15<<5);
 - delay(1);
 - }
 - void display_led(int n){
 - GPBDAT = ~(n<<5);
 - }
 - void copy_code2sdram(){
 - int size, i;
 - unsigned char *src, *des;
 - size = 8*1024;
 - des = (unsigned char*)(0x30000000);
 - src = (unsigned char *)(0x00000000);
 - for(i=0; i<size; i++){
 - *(des++) = *(src++);
 - }
 - }
 - void init_led(){
 - GPBCON = 0x00015400;
 - GPBDAT &= ~(0x0f<<5);
 - }
 - //initialize the clock of soc
 - void init_clock(){
 - LOCKTIME = 0xffffffff;
 - CLKDIVN = 0X03; //fclk:hclk:pclk=1:2:4
 - __asm__
 - (
 - "mrc p15, 0, r1, c1, c0, 0\n"
 - "orr r1, r1, #0xc0000000\n"
 - "mcr p15, 0, r1, c1, c0, 0\n"
 - );
 - MPLLCON = (92<<12)|(1<<4)|(2<<0); //fclk=200M, hclk=100M, pclk=50M
 - }
 - /*
 - int main(void){
 - int i;
 - GPBCON = 0x00015400;
 - i = 0;
 - while(1){
 - GPBDAT = ~(1<<(i+5));
 - delay(1);
 - i = (i+1)%4;
 - }
 - return 0;
 - }
 - */
 - int main(void){
 - display_led3();
 - while(1){
 - //waiting for interrupt
 - //puts_uart0_fifo("Hello world\r\n");
 - //puts_uart0_fifo("this is a test of uart0\r\n");
 - }
 - return 0;
 - }
 
                    
                
                
            
        
浙公网安备 33010602011771号