1. Introduction to gpio
Gpio is a general input and output port. In short, it is some pins that output high and low levels or read the high and low levels of pins through them.
S3C2440 has 130 I/O Ports, divided into 9 groups of A-J: GPa, GPB, gpj, you can set registers to determine a pin for input, output or special functions.
For example, you can set gph6 as the input, output, or serial port.
1. Operate gpio pins through registers
1) gpxcon register
It is used to configure pin functions.
Port A and the port B-J have different functions, each bit in gpacon corresponds to a single pin (23 pins in total)
When a pin is set to 0, the corresponding PIN is output. At this time, the corresponding bit is written to 0 or 1 in gpadat to let the pin output low or high level. When a pin is set to 1, the corresponding PIN is the address line or used for address control. gpadat is not needed at this time.
Gpacon is usually set to full 1 for access to external storage devices
The port B-J is identical in register operations, each two in gpxcon controls a pin, 00 indicates input, 01 indicates output, 10 indicates special function, 11 Reserved
2) gpxdat register
It is used to read and write pins. When the pins are set as inputs, read this register to see whether the levels of the corresponding pins are high or low. When the pins are set as outputs, write the corresponding bit of this register to make the output level of this pin.
3) gpxup register
Gpxup. When a pin is set to 1, the corresponding PIN has no internal pull-up resistance. When the value is set to 1, the corresponding PIN uses the internal pull-up resistance.
When the gpio pin is in the third State (non-high level, but high-resistance state, that is, it is equivalent to not connected to the chip, its level status is determined by the pull-up and drop-down resistors.
2. Use software to access hardware
Three types of operations are available for one pin: output level, detection pin status, and interruption. Operations on a pin are generally implemented through read/write registers.
First we from the light LED, choose from the mini2440 schematic, LED1-4 corresponding to GPB5-8 respectively
If you want to control these LEDs, we first need to set the bit corresponding to the GPB5-8 in the gpbcon register as the output function, then write the corresponding bit of the gpbdat register, so that the four pins output high and low levels
It is generally effective at a low level, that is, when the power is high, the corresponding led goes off, when the power is low, the corresponding LED lights up
When accessing the registers, you can use the S3C2440 Data Manual to find the addresses of the gpbcon and gpbdat registers.
Gpbcon is 0x56000010, gpbdat is 0x56000014
Use the following code to make gpb5 output low and light up led1
# Define gpbcon (* (volatile unsigned long *) 0x56000010) // The volatile modifier ensures that the variable value is not read from the cache or register each time it is removed from the memory
# Define gpbdat (* (volatile unsigned long *) 0x56000014)
# Define gpb5_out (1 <(5*2) // two pins are controlled, so gpb5 is the [11: 10] bits of gpbcon, and 1 is shifted to 10 bits, the value [11: 10] is 01, indicating that gpb5 is the output.
Gpbcon = gpb5_out;
Gpbdat & = ~ (1 <5); // 1 shifts left to 5 digits to take the inverse, so the 5th bits are 0, that is, gpb5 outputs a low level, light up led1
Ii. gpio operation instance
1. Use the assembly code to light up an LED
First look at the source program led_on.s
. Text
. Global _ start
_ Start:
LDR r0, = 0x56000010 @ R0 set to gpbcon register
MoV R1, #0x00000400 @ set gpb5 as the output port, bit [] = 0b01
STR R1, [R0]
LDR r0, = 0x56000014 @ R0 set to gpbdat register
MoV R1, #0x00000000 @ this value is changed to 0x00000020 to extinguish led1
STR R1, [R0] @ gpb5 output 0, led1 light up
Main_loop:
B main_loop @ Infinite Loop
Let's take a look at the makefile of the program.
Led_on.bin: led_on.s
Arm-Linux-gcc-g-c-o led_on.o led_on.s
Arm-Linux-LD-ttext 0x0000000-G led_on.o-O led_on_elf
Arm-Linux-objcopy-O Binary-s led_on_elf led_on.bin
Clean:
Rm-F led_on.bin led_on_elf *. o
Led_on.s generates led_on.bin
Compile the first line
Connect to the second line and specify the starting address of the code segment as 0x00000000
The third line converts the ELF format to the binary format.
Clean is used to clear compiled files
2. Use C code to light up the LEDAssembly readability is worse than C, we use C to implement @********************************** **************************************** * *** @ file: crt0.s @ function: use it to transfer to the C program @********************************** **************************************** ****. text. global _ start_start: LDR r0, = 0x53000000 @ watchdog Register address mov R1, #0x0 STR R1, [R0] @ write 0, prohibit watchdog, otherwise, the CPU will continuously restart the LDR sp, = 1024*4 @ to set the stack. Note: it cannot be greater than 4 K, because the available memory is only 4 K, which is steppingstone, the code in @ NAND Flash will be moved to the internal RAM after the reset. This Ram only has 4 k bl main @ to call the main function halt_loop in the C program: under B halt_loop is led_on_c.c # define gpbcon (* (volatile unsigned long *) 0x56000010) # define gpbdat (* (volatile unsigned long *) 0x56000014)
Int main () {gpbcon = 0x00000400; // set gpb5 as the output port, BITs [11: 10] = 0b01 gpbdat = 0x00000000; // gpb5 outputs 0 and led1 lights up
Return 0 ;}
Makefile
Led_on_c.bin: crt0.s led_on_c.c
Arm-Linux-gcc-g-c-o crt0.o crt0.s
Arm-Linux-gcc-g-c-o led_on_c.o led_on_c.c
Arm-Linux-LD-ttext 0x0000000-G crt0.o led_on_c.o-O led_on_c_elf
Arm-Linux-objcopy-O Binary-s led_on_c_elf led_on_c.bin
Arm-Linux-objdump-D-M arm led_on_c_elf> led_on_c.dis
Clean:
Rm-F led_on_c.dis led_on_c.bin led_on_c_elf *. o
Compile crt0.s and led_on_c.c respectively
Connect the target to led_on_c_elf. The starting address of the code segment is 0x00000000.
Convert ELF format to binary led_on_c.bin
The final conversion result is an assembly code for easy viewing.
3. Test Procedure
Enter the code directory in the previously established compiling environment
# Make
Binfile obtained: Use dnw in win to download to the Development Board, set the serial port baud rate, corresponding port, 8n1, 0x00000000
Switch to nor flash and turn on the power. After the menu appears, select
Then select USB port-transmit/restore and select the compiled binfile.
Then switch to the NAND to start. The effect is as follows: (set led1 and led4 to bright)
4. Use buttons to control LEDs
K1-K6 as corresponding to GPG, we operate K1-K4 using LED1-LED4
@*************************************** ***************************************
@ File: crt0.s @ function: use it to transfer to the C program @********************************** **************************************** ****. text. global _ start_start: LDR r0, = 0x56000010 @ watchdog Register address mov R1, #0x0 STR R1, [R0] @ write 0, prohibit watchdog, otherwise, the CPU will continuously restart the LDR sp, = 1024*4 @ to set the stack. Note: it cannot be greater than 4 K, because the available memory is only 4 K, which is steppingstone, the code in @ NAND Flash will be moved to the internal RAM after the reset. This Ram only has 4 k bl main @ to call the main function halt_loop in the C program: under B halt_loop is the key_led.c file # define gpbcon (* (volatile unsigned long *) 0x56000010) # define gpbdat (* (volatile unsigned long *) 0x56000014)
# Define gpgcon (* (volatile unsigned long *) 0x56000060) # define gpgdat (* (volatile unsigned long *) 0x56000064)
/** LED1-4 corresponds to gpb5, gpb6, gpb7, gpb8 */# define gpb5_out (1 <(5*2) # define gpb6_out (1 <(6*2 )) # define gpb7_out (1 <(7*2) # define gpb8_out (1 <(8*2 ))
/** K1-K4 corresponds to gpg0, gpg3, gpg5, gpg6 */# define gpg7_in ~ (3 <(6*2) # define gpg6_in ~ (3 <(5*2) # define gpg3_in ~ (3 <(3*2) # define gp1__in ~ (3 <(0*2 ))
Int main () {unsigned long dwdat; // four pins corresponding to the LED1-LED4 are set to output gpbcon = gpb5_out | gpb6_out | gpb7_out | gpb8_out;
// The two pins corresponding to the K1-K4 are set to the input gpgcon = gp1__in & gpg3_in & gpg6_in & gpg7_in;
While (1) {// If kN is 0 (indicates pressing), ledn is 0 (indicates lighting) dwdat = gpgdat; // read the GPG pin level status if (dwdat & (1 <0) // K1 does not press gpbdat |=( 1 <5 ); // led1 extinguish else gpbdat & = ~ (1 <5); // led1 light up if (dwdat & (1 <3) // K2 does not press gpbdat |=( 1 <6 ); // led2 extinguish else gpbdat & = ~ (1 <6); // led2 light up if (dwdat & (1 <5) // K3 does not press gpbdat |=( 1 <7 ); // led3 extinguish else gpbdat & = ~ (1 <7); // led3 light up if (dwdat & (1 <6) // K4 does not press gpbdat |=( 1 <8 ); // led4 extinguish else gpbdat & = ~ (1 <8); // led4 light up}
Return 0;} The last is makefile key_led.bin: crt0.s key_led.carm-linux-gcc-g-c-o crt0.o crt0.sarm-Linux-gcc-g-c-o key_led.o key_led.carm-linux-ld-ttext 0x0000000-G crt0.o key_led.o-O key_led_elfarm-linux-objcopy-O Binary-s key_led_elf key_led.binarm-linux-objdump-D-M arm key_led_elf> key_led.disclean: rm-F key_led.dis key_led.bin key_led_elf *. O test results