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 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 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< void delay(int n){ int i, j; for(i=0; i } } 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 } } 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; }
Previous article:mini2440 serial port polling experiment
Next article:mini2440 simple lcd display driver
- Popular Resources
- Popular amplifiers
- Learn ARM development(16)
- Learn ARM development(17)
- Learn ARM development(18)
- Embedded system debugging simulation tool
- A small question that has been bothering me recently has finally been solved~~
- Learn ARM development (1)
- Learn ARM development (2)
- Learn ARM development (4)
- Learn ARM development (6)
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- LED chemical incompatibility test to see which chemicals LEDs can be used with
- Application of ARM9 hardware coprocessor on WinCE embedded motherboard
- What are the key points for selecting rotor flowmeter?
- LM317 high power charger circuit
- A brief analysis of Embest's application and development of embedded medical devices
- Single-phase RC protection circuit
- stm32 PVD programmable voltage monitor
- Introduction and measurement of edge trigger and level trigger of 51 single chip microcomputer
- Improved design of Linux system software shell protection technology
- What to do if the ABB robot protection device stops
- Detailed explanation of intelligent car body perception system
- How to solve the problem that the servo drive is not enabled
- Why does the servo drive not power on?
- What point should I connect to when the servo is turned on?
- How to turn on the internal enable of Panasonic servo drive?
- What is the rigidity setting of Panasonic servo drive?
- How to change the inertia ratio of Panasonic servo drive
- What is the inertia ratio of the servo motor?
- Is it better for the motor to have a large or small moment of inertia?
- What is the difference between low inertia and high inertia of servo motors?
- Basics of Model-Based GaN PA Design: GaN Transistor S-Parameters, Linear Stability Analysis, and Resistor Stability
- [GD32L233C-START Review] 11. DAC output voltage value_ADC reads external voltage value
- EEWORLD University ---- Getting started and improving vivado
- (5) Low-power remote data monitoring system based on GD32L233C-START
- DS5 usage error
- PICO online graphical programming website
- Preheating for Double 11, Infineon flagship store’s hot-selling list leaked!
- Understanding of filter capacitors, small capacitors filter high frequencies, and large capacitors filter low frequencies
- Please tell me why this machine often burns the starting resistor at the customer's place
- Several Bluetooth antenna design references