mini2440 uart serial port experiment (fifo mode + interrupt)

Publisher:花海鱼Latest update time:2022-10-17 Source: csdnKeywords:mini2440 Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

This time is an experiment on the FIFO mode of uart0 on S3C2440. The program sets the number of data contained in the input fifo of serial port 0 to trigger a pulse interrupt at the moment when it changes from a state of less than 16 bytes to a state of greater than or equal to 16 bytes. In this interrupt, all the data in the input fifo is written to the output fifo. When the output fifo changes from a non-empty state to an empty state, a pulse interrupt will be triggered. During the interrupt, I let the light flash. Experimental The correct phenomenon is that data is sent from the hyper terminal to the serial port 0 of the 2440. Every time 16 bytes of data are sent, the serial port will print out all 16 bytes. At the same time, because the output fifo becomes empty, the light will flash. The test and experimental phenomena are consistent with what was said above. It should be noted that when writing data to the utxh0 register, you must first check whether the output fifo is full. If it is full, you must wait. Otherwise, the data on the opposite side of the output fifo will be dequeued early, and the dequeued data will be lost. Enter The number of data in the fifo must be read from the corresponding field in the UFSTAT register. How to use the dma mode of uart still needs to be studied.


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 .

bhandle_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 handling 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 controller 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]!=''; 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 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 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< INTPND = 1<}

 

void delay(int n){

int i, j;

for(i=0; 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 *(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, 0n"  

        "orr r1, r1, #0xc0000000n"  

        "mcr p15, 0, r1, c1, c0, 0n"      

    );  

    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 worldrn");

//puts_uart0_fifo("this is a test of uart0rn");

}

return 0;

}

Keywords:mini2440 Reference address:mini2440 uart serial port experiment (fifo mode + interrupt)

Previous article:mini2440 serial port polling experiment
Next article:mini2440 simple lcd display driver

Latest Microcontroller Articles
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号