Design and Analysis of BASIC Program for arm9-based on S3C2440
------- Justdo
I have recently learned the design of the basic program of ARM9. I have recorded my experiences and hope to help beginners. To learn how to use the arm program, first go to the structure principle diagram of the corresponding modules in the chip manual and find out the basic principles of the modules used, then, based on the block diagram, find out which registers need to be set, then figure out how to set the corresponding registers based on the time sequence diagram, and then figure out the general process of the program you are writing, finally, you can write a program.
If you have understood the process, your program is basically half successful.
I am using a S3C2440 ARM chip. If you have any questions or omissions, please contact QQ, 843308498.
Source http://download.csdn.net/source/3149713
One led flow lamp Program
Process:
1. Set the port control register to set the corresponding led port to the output mode (gpxcon ).
2. Send data (gpxdat) to the data register corresponding to the port ).
Implementation:
// This macro defines the data that should be sent to make the corresponding LED light
# Define ledbench ON ~ (1 <5)
# Define led2_on ~ (1 <6)
# Define led3_on ~ (1 <7)
# Define led4_on ~ (1 <8)
# Define led0000off (1 <5)
# Define led2_off (1 <6)
# Define led3_off (1 <7)
# Define led4_off (1 <8)
// Led initialization function, which sets gpbcon as the output port and sends data to the port so that all LEDs are in the disabled state.
Void ledinit ()
{
Rgpbcon | = (1 <10) | (1 <12) | (1 <14) | (1 <16 );
Rgpbdat | = (led1_off | led2_off | led3_off | led4_off );
}
// Turn the LED shining function in turn, first light the corresponding led, then delay, and then close
Void ledrun ()
{
Rgpbdat & = ledbench on;
Delay (1000 );
Rgpbdat | = led0000off;
Rgpbdat & = led2_on;
Delay (1000 );
Rgpbdat | = led2_off;
Rgpbdat & = led3_on;
Delay (1000 );
Rgpbdat | = led3_off;
Rgpbdat & = led4_on;
Delay (1000 );
Rgpbdat | = led4_off;
}
Two-key interrupt program
Process:
Interrupt handling process
1. The Interrupt Controller collects interrupt signals from various peripherals and then tells the CPU
2. the CPU saves the running environment of the current program, and then calls the interrupt service program to handle the interruption.
3. In ISR, the interrupt control register is read and the peripheral registers are used to identify the interrupt and process the interrupt accordingly.
4. Clear interruption: Read and Write related interrupt control registers and peripheral related registers are implemented.
5. It is best to restore the environment of the interrupted program and continue execution.
Key interrupt program process:
Initialization
1. Set the port corresponding to the key to interrupt (gpxcon)
2. Set the program interrupt entry
3 clear the External Interrupt pending registers einitpend and pending registers intpnd and srcpnd to prevent original interference
4. Set the level trigger mode (extinitn)
5. Disable the shielding of External Interrupt entmask and intmask
Interrupt program
6. Clear the intpnd and srcpnd registers to prevent repeated responses to the interrupt.
7. determine the corresponding bit of reinitpend to determine which key is interrupted, execute the corresponding program, and clear the corresponding bit of reinitpend to prevent repeated responses.
Program:
Static void _ IRQ keyhander (); // declare the interrupt handler
// Key initialization Function
Void keyinit ()
{
Mmu_init ();
Rgpgcon | = (1 <1 | 1 <7 | 1 <11 | 1 <13); // set the corresponding port of gpgcon to interrupt
Pisr_eint8_23 = (u32) keyhander; // set the interrupt program entry
Reintpend | = (1 <8 | 1 <11 | 1 <13 | 1 <14); // clear the External Interrupt suspend register to prevent interference
Clearpending (bit_eint8_23 );
Reintmask & = ~ (1 <8 | 1 <11 | 1 <13 | 1 <14); // enable the External Interrupt shielding device
// Rextinit1 sets the interrupt trigger mode register, because it is triggered at a low level by default, so you do not need to set
Enableirq (bit_eint8_23); // enable interruption, which is actually to enable the mask
}
// Key response function
Void keyhander ()
{
Clearpending (bit_eint8_23); // The clear interrupt pending register includes srcpnd intpnd
If (reintpend & 1 <8) // determine which key is requested for interruption through the external interrupt suspension register
{
Reintpend | = 1 <8; // clear the External Interrupt suspension register to prevent repeated interruptions
Lightled (1 );
}
If (reintpend & 1 <11)
{
Reintpend | = 1 <11;
Lightled (2 );
}
If (reintpend & 1 <13)
{
Reintpend | = 1 <13;
Lightled (3 );
}
If (reintpend & 1 <14)
{
Reintpend | = 1 <14;
Lightled (4 );
}
}
Three-timer interrupt program
CPU clock setting process
1. Set mpllcon registers and fclk
2. Set the clkdivn register to set the value of fclk: hclk: pclk.
Clock Setting Process
Initialization
1. Set the frequency division value t00000 tcfg1.
2. Set the timer Count value tcntb0
3. Set the interrupt program entry, clear the pending register, and disable the mask shielding.
4. Update the tctnb0 and tcmtb0 values tccon.
5. Clear tccon to 0. Otherwise, the CPU will be updated continuously.
Start Timer
6. Start the timer and tccon.
Interrupt Function
Clear the pending register and execute the response code
Void setsysclk () // fclk = 405 MHz fclk: hclk: pclk =
{
Rmpllcon = 0;
Rmpllcon | = (0x3f <12 | 2 <4 | 2 <0); // set the value of fclk
Rclkdivn | = (1 <2 | 1 <0); // set the ratio of fclk: hclk: pclk
// You do not need to set locktime. If no value is set, the system automatically selects locktime.
}
Void timer0init () // pclk = 50 MHz
{
Rt1_0 = 49;
Rtcfg1 | = 2; // CLK = 62500Hz
// T00000 tcfg1 sets the timer pre-division value and allocation value, and then obtains the timer 0 frequency: fclk/(49 + 1)/16
Rtcntb0 = 62500;
// Tcntb0 sets the counting register of the timer
Clearpending (bit_timer0); // clear counter 0 interrupt suspend register
Pisr_timer0 = (u32) timer0handle;
Enableirq (bit_timer0); // enable the mask to block the timer 0.
Rtcon | = (1 <1); // update the values of tcntb0 and tcmtb0
Rtcon = 0; // clear the value of tcon to 0. Note that this step is very important. If not, the timer will always update the value of tcntb0 and tcmtb0, leading to startup failure.
Rtcon | = (1 <3 | 1 <0); // start the timer 0 and set it to automatic loading.
}
Static void _ IRQ timer0handle ()
{
Clearpending (bit_timer0); // clear the timer0 interrupt suspension register to prevent repeated
Ledrun ();
}
4. Serial sending program
Process:
Initialization
1. Set the corresponding gpio port to the serial output port.
2. Set the serial port data format ulconn
3. Set the receiving and occurrence modes ulconn
4. Set the baud rate to rubrdivn.
Send data
5. The waiting sending buffer is empty. rutrstatn
6. Write utxhn data to the data register
Program:
Void uartinit (INT num, int buad)
{
Int I;
Switch (Num)
{
Case 0:
Rgphcon | = (1 <5 | 1 <7); // set the gph port to the serial port
Rulcon0 = 0x03; // set the data format to 8-Bit Data
Rucon0 = (1 <0 | 1 <2); // set receiving and sending to query mode
Rubrdiv0 = (INT) pclk/(16 * buad)-1); // set the baud rate
Break;
Case 1:
Rgphcon | = (1 <9 | 1 <11 );
Rubrdiv1 = (INT) pclk/(16 * buad)-1 );
Rulcon1 = 0x03;
Rucon1 = (1 <0 | 1 <2 );
Break;
Case 2:
Rgphcon | = (1 <13 | 1 <15 );
Rubrdiv2 = (INT) pclk/(16 * buad)-1 );
Rulcon2 = 0x03;
Rucon2 = (1 <0 | 1 <2 );
Break;
Default:
Break;
}
For (I = 0; I! = 100; ++ I); // delay for the setting to take effect
}
Void uartprintf (char * FMT ,...)
{
Va_list AP;
Char string [256];
// Format an indefinite parameter into a string
Va_start (AP, FMT );
Vsprintf (string, FMT, AP );
Uartsendstring (string );
Va_end (AP );
}
Void uartsendstring (char * Str)
{
While (* Str)
Uart_sendbyte (* STR ++ );
}
Void uartsendbyte (char byte)
{
Switch (whichuart)
{
Case 0:
While (! (Rutrstat0 & 0x02); // The waiting zone is empty.
Wrutxh0 (byte );
Break;
Case 1:
While (! (Rutrstat1 & 0x02 ));
Wrutxh1 (byte );
Break;
Case 2:
While (! (Rutrstat2 & 0x02 ));
Wrutxh2 (byte );
Break;
Default:
Break;
}
}
V. ADC Conversion Program
Process
Initialization
1. Set the conversion channel and frequency adcconn
2. Clear the corresponding interrupt suspension register, set the interrupt Entry Program, and cancel the mask shielding.
Start
3. Set the corresponding bit of adcconn to start the conversion.
Service Interruption
4. Use subsrcpnd to determine if it is a normal ADC conversion.
5. Clear the corresponding bits of subsrcpnd
6. Read the conversion value adcdatn.
Program
Void adcinit ()
{
Int channel = 0, prescaler = 50000000/adcfre-1;
Radccon = (Channel <3) | (prescaler <6) | (1 <14); // set the ADC channel and pre-division Value
Delay (100 );
Pisr_adc = (u32) adchandle; // sets the interrupt vector table.
Clearpending (bit_adc); // clear the pending register
Rsubsrcpnd & = (1 <10); // clear the sub-interrupt suspension register
Enableirq (bit_adc); // enable ADC interruption, which is actually used to disable intmsk's shielding of the ADC.
Rintsubmsk & = (0 <10); // disable the adc_s shielding function of the subinterrupt.
Radccon | = 1; // start Conversion
}
Static void _ IRQ adchandle ()
{
Int adcvalue;
Clearpending (bit_adc );
If (rsubsrcpnd & (1 <10) // determines if there is an interruption caused by normal ADC conversion.
{
Rsubsrcpnd & = (1 <10 );
Adcvalue = (radcdat0 & 0x3ff); // read the conversion value
Uart_printf ("/n ADC convert value is % d/N", adcvalue );
Radccon | = 1; // start Conversion
}
}
6. Touch Screen Program
Process:
Initialization
1. Set the sampling delay and frequency division value adcdly adccon
2. Interrupt settings
3. Set the touch screen ad to the waiting interruption mode adctsc.
Service interruption function
4. Clear related pending registers
5. Set the conversion mode, which is generally continuous X or Y conversion.
6. Start conversion.
7. After the conversion is complete, read the x y coordinate adcdat0 adcdat1.
8. Set the touch screen ad to the pending interruption mode, and set the waiting period adctsc.
9 after the disconnection occurs, set the touch screen to the pending interruption mode, and wait for the next touch to press radctsc
Program
Void touchpendinit ()
{
Adcinit ();
Radctsc = 0xd3; // set it to the pending interruption mode.
Rsubsrcpnd | = (1 <9); // clear the adc_tc pending register
Rintsubmsk & = ~ (1 <9); // adc_tc shielded
}
Void adcinit ()
{
Int channel = 0, prescaler = 50000000/adcfre-1;
Radcdly = 50000; // you need to set the latency of the touch screen conversion. Otherwise, the value is incorrect.
// Radccon = (Channel <3) | (prescaler <6) | (1 <14); // set the ADC channel and pre-division Value
Radccon = (1 <14) | (prescaler <6 );
Delay (100 );
Pisr_adc = (u32) adchandle; // sets the interrupt vector table.
Clearpending (bit_adc); // clear the pending register
Rsubsrcpnd | = (1 <10); // clear the sub-interrupt suspension register
Enableirq (bit_adc); // enable ADC interruption, which is actually used to disable intmsk's shielding of the ADC.
Rintsubmsk & = ~ (1 <10); // disable the adc_s shielding function of the sub-interrupt */
}
Static void _ IRQ adchandle ()
{
Int xadcvalue, yadcvalue;
Clearpending (bit_adc );
If (rsubsrcpnd & (1 <9 ))
{
Rsubsrcpnd | = (1 <9 );
Radctsc | = (1 <2); // sets the conversion mode. X and Y are automatically converted continuously.
Radccon | = 1; // start Conversion
}
If (rsubsrcpnd & (1 <10) // determines if there is an interruption caused by normal ADC conversion.
{
Rsubsrcpnd | = (1 <10 );
Xadcvalue = (radcdat0 & 0x3ff); // read the conversion value
Yadcvalue = (radcdat1 & 0x3ff );
Uart_printf ("/N x = % d, y = % d/N", xadcvalue, yadcvalue );
Radctsc = 0xd3; // set it to the pending interruption mode.
Radctsc | = (1 <8); // detects the disconnection
// Wait for the bounce
While (1)
{
If (rsubsrcpnd & (1 <9 ))
{
Rsubsrcpnd | = (1 <9 );
Radctsc = 0xd3;
Break;
}
}
}
}
7. LCD Program
Process:
Initialization
1. initialize the port and set the corresponding port to the LCD port.
2 Display Mode Initialization, setting frame synchronization signal, line synchronization signal, screen size, pixel display mode, etc.
Initialize a three-frame buffer and set the starting address, stop address, and virtual screen width of the frame buffer.
Start output
4. Start output
5. Write the image data to be displayed to the frame buffer.
Program:
# Define LCD _width 240
# Define LCD _height 320
# Define LCD _pixclock 4
# Define LCD _right_margin 39
# Define LCD _left_margin 16
# Define LCD _hsync_len 5
# Define LCD _upper_margin 1
# Define LCD _lower_margin 5
# Define LCD _vsync_len 1
Static unsigned short lcdbuffer [LCD _width] [LCD _height]; // defines the video memory.
Void lcdportinit ()
{
Rgpccon = 0xaaaa00a8; // set the GPC port to vclk, vline, and vframe VD.
Rgpcup = 0 xFFFF;
Rgpdcon = 0 xaaaaaaaa; // set the GPD port to VD output
Rgpdup = 0 xFFFF; // disable pulling
}
Void lcdinit ()
{
U32 bufferaddr = (u32) lcdbuffer;
Lcdportinit ();
Rlcdcon1 = (LCD _pixclock <8) | (3 <5) | (0xc <1); // sets the vclk clock, and the display mode is TFT, the pixel format is 16 bits.
Rlcdcon2 = (LCD _upper_margin <24) | (LCD _HEIGHT-1) <14) | (LCD _lower_margin <6) | (LCD _vsync_len <0 ); // set the invalid clock, LCD height, invalid clock before the next synchronous signal occurs, and the second width of the synchronous signal.
Rlcdcon3 = (LCD _left_margin <19) | (LCD _WIDTH-1) <8) | (LCD _right_margin <0); // set the invalid clock, LCD width, invalid clock width before the next synchronous line signal occurs
Rlcdcon4 = (LCD _hsync_len <0); // set the clock pulse width of the synchronous line signal.
Rlcdcon5 = (1 <11); // set the pixel format to 5: 6: 5.
Rlcdsaddr1 = (bufferaddr> 22) <21) | (bufferaddr> 1) & 0x1fffff) <0); // set the start address of the video memory.
Rlcdsaddr2 = (bufferaddr + LCD _width * 2)> 1) & 0x1ffff; // sets the end address of the video memory.
Rlcdsaddr3 = LCD _width; // set the virtual screen width to the actual width.
Rlcdcon1 | = 1; // start output
}
Void lcddisplay ()
{
Lcdsubdisplay (0x1f <11) | (0x00 <5) | (0x00); // red
Delay (100000 );
Lcdsubdisplay (0x00 <11) | (0x3f <5) | (0x00); // green
Delay (100000 );
Lcdsubdisplay (0x00 <11) | (0x00 <5) | (0x1f); // blue
Delay (100000 );
}
Void lcdsubdisplay (2010c)
{
Unsigned int X, Y;
For (x = 0; x <LCD _width; ++ X)
For (y = 0; y <LCD _height; ++ y)
Lcdbuffer [x] [Y] = C;
}