After lunch, Mao touched his stomach and met you again. Let's finish learning the previous article. If Mao speaks well, today he will be rewarded with Tao Mao to see a set of Big Ears pictures.
Okay. Let's start learning now! This morning in our previous article "Linux arch/arm/mach-s3c2410/include/mach/gpio-nrs.h understanding" introduced a series of macros, but we do not know, why does the Linux kernel do this? This afternoon Mao will lead everyone to look at the linux/arch/arm/plat-s3c24xx/gpio. c inside the application.
By querying the kernel code, Mao found that linux/arch/arm/plat-s3c24xx/gpio. c, mainly defines some Linux I/O port standard configuration and read/write. Includes the following functions:
Void s3c2410_gpio_cfgpin (unsigned int pin, unsigned int function );
Unsigned int s3c2410_gpio_getcfg (unsigned int pin );
Void s3c2410_gpio_pullup (unsigned int pin, unsigned int );
Int s3c2410_gpio_getpull (unsigned int pin );
Void s3c2410_gpio_setpin (unsigned int pin, unsigned int );
Unsigned int s3c2410_gpio_getpin (unsigned int pin );
Unsigned int s3c2410_modify_miscr (unsigned int clear, unsigned int change );
Int s3c2410_gpio_getirq (unsigned int pin );
Mao, the role of the above function, does not need to be explained one by one. You can open gpio. the c file will understand, because these functions are the input and output directions of the I/O port, and the functions for reading, writing, and configuring data.
Next, Mao will only discuss the role of macro definition in the previous article from void s3c2410_gpio_setpin (unsigned int pin, unsigned int.
First, we should first list the source program of this function for everyone.
Void s3c2410_gpio_setpin (unsigned int pin, unsigned int)
{
Void _ iomem * base = S3C24XX_GPIO_BASE (pin); // macro calculation, obtain the base address of the pin.
Unsigned long offs = S3C2410_GPIO_OFFSET (pin); // macro calculation, obtains the offset address of the relative base address of the pin.
Unsigned long flags;
Unsigned long dat;
Local_irq_save (flags); // similar to entering the critical section
Dat = _ raw_readl (base + 0x04); // read I/O port data
Dat & = ~ (1 <offs );
Dat | = to <offs;
_ Raw_writel (dat, base + 0x04); // write I/O port data
Local_irq_restore (flags); // similar to exiting the critical section
}
You may not be able to see anything from the above procedures, but Mao is "Breaking the casserole and asking to the end". Mao enters the two macros: S3C24XX_GPIO_BASE (pin) and S3C2410_GPIO_OFFSET (pin.
These two macros are defined in the arch/arm/mach-s3c2410/include/mach/regs-gpio.h file:
# Define S3C2410_GPIO_BASE (pin )&~ 31)> 1) + S3C24XX_VA_GPIO)
# Define S3C2410_GPIO_OFFSET (pin) & 31)
(S3C24XX_VA_GPIO is a macro that represents the virtual base address of the I/O port. I will not talk about it more here. 1: I am not familiar with the virtual address and the actual physical address. 2: If you want to talk about too many things you need to talk about, it is not easy to make it clear. Please think about it yourself)
Okay, so far we have listed all the things. Then Mao will use an example to link the things mentioned above.
First, let's look at the following C program: s3c2410_gpio_setpin (S3C2410_GPA (0), 1 );
This program is to set the port 0 of port A of S3C2410 to 1. I believe that everyone knows the same thing as Mao.
S3C2410_GPA (0) is Linux arch/arm/mach-s3c2410/include/mach/macro definition in the gpio-nrs.h, enter the function void s3c2410_gpio_setpin (unsigned int pin, unsigned int ); mao found that the parameter S3C2410_GPA (0) is used as the macro S3C2410_GPIO_BASE (pin) and S3C2410_GPIO_OFFSET (pin) parameters.
So far we should be clear, this morning we do on the arch/arm/mach-s3c2410/include/mach/gpio-nrs.h file is used for the two macros.
But why is it defined like this?
Careful gross hair found in arch/arm/mach-s3c2410/include/mach/regs-gpio.h (that is, the file where the macro that defines the base address and offset address is located:
# Define S3C2410_GPA0_ADDR0 (1 <0)
# Define S3C2410_GPA1_ADDR16 (1 <1)
# Define S3C2410_GPA2_ADDR17 (1 <2)
# Define S3C2410_GPA3_ADDR18 (1 <3)
# Define S3C2410_GPA4_ADDR19 (1 <4)
# Define S3C2410_GPA5_ADDR20 (1 <5)
# Define S3C2410_GPA6_ADDR21 (1 <6)
# Define S3C2410_GPA7_ADDR22 (1 <7)
# Define S3C2410_GPA8_ADDR23 (1 <8)
# Define S3C2410_GPA9_ADDR24 (1 <9)
# Define S3C2410_GPA10_ADDR25 (1 <10)
# Define S3C2400_GPA10_SCKE (1 <10)
# Define S3C2410_GPA11_ADDR26 (1 <11)
# Define S3C2400_GPA11_nCAS0 (1 <11)
# Define S3C2410_GPA12_nGCS1 (1 <12)
# Define S3C2400_GPA12_nCAS1 (1 <12)
# Define S3C2410_GPA13_nGCS2 (1 <13)
# Define S3C2400_GPA13_nGCS1 (1 <13)
# Define S3C2410_GPA14_nGCS3 (1 <14)
# Define S3C2400_GPA14_nGCS2 (1 <14)
# Define S3C2410_GPA15_nGCS4 (1 <15)
# Define S3C2400_GPA15_nGCS3 (1 <15)
# Define S3C2410_GPA16_nGCS5 (1 <16)
# Define S3C2400_GPA16_nGCS4 (1 <16)
# Define S3C2410_GPA17_CLE (1 <17)
# Define S3C2400_GPA17_nGCS5 (1 <17)
# Define S3C2410_GPA18_ALE (1 <18)
# Define S3C2410_GPA19_nFWE (1 <19)
# Define S3C2410_GPA20_nFRE (1 <20)
# Define S3C2410_GPA21_nRSTOUT (1 <21)
# Define S3C2410_GPA22_nFCE (1 <22)
What do you see? It doesn't matter if you don't see it. Mao will write the program above and you will know it.
Void s3c2410_gpio_setpin (unsigned int pin, unsigned int)
{
Void _ iomem * base = S3C24XX_GPIO_BASE (pin); // macro calculation, obtain the base address of the pin.
Unsigned long offs = S3C2410_GPIO_OFFSET (pin); // macro calculation, obtains the offset address of the relative base address of the pin.
Unsigned long flags;
Unsigned long dat;
Local_irq_save (flags); // similar to entering the critical section
Dat = _ raw_readl (base + 0x04); // read I/O port data
Dat & = ~ (1 <offs );
Dat | = to <offs;
_ Raw_writel (dat, base + 0x04); // write I/O port data
Local_irq_restore (flags); // similar to exiting the critical section
}
You know, it is actually the bitwise offset address, that is, the specified read/write bit.
Here maybe you still don't quite understand what the relationship with the arch/arm/mach-s3c2410/include/mach/gpio-nrs.h said in the last few days.
Next we will explain: in fact, the number of I/O Ports for each of our I/O ports is 0 to n, which is controlled by four bytes above the physical address (including read/write and configuration ), the four bytes are 32 bits in total, and I/O 0 to 32 correspond to each of the four. So the arch/arm/mach-s3c2410/include/mach/gpio-nrs.h file is implemented from the I/O port A 0 to the I/O port H arranged into A low to high number. This number is used for the following two macros to obtain the relative address relative to the start address of the I/O control register and the offset address in the I/O port register.
# Define S3C2410_GPIO_BASE (pin )&~ 31)> 1) + S3C24XX_VA_GPIO)
# Define S3C2410_GPIO_OFFSET (pin) & 31)
(Pin )&~ 31)> 1) Get the base offset from the starting address 0x56000000 (PORTA is calculated as 0x00, PORTB is calculated as 0x10, and PORTC is calculated as 0x20, so as to match the physical address)
(Pin) & 31) Get the relative bit address in the control register
Now, we have basically finished it. I hope you can understand it. If you have any questions, please leave me a message.