Since I didn't understand the address allocation of IMX257 yesterday, I could only use the s3c24xx driver to understand the working principles of ioremap and other IO ports.
However, after a careful review of the IMX257 chip last night, I read the chip information of IMX257 again this morning and finally succeeded in understanding it. The following is the meaning for everyone.
We use ERR_LED here, which is GPIO3_23 pin
1. IMX257 chip data analysis
1. Determine the base address of the relevant register
Determine the IOMUX address
Address of GPIO3
2. Determine the offset address of the relevant register
IOMUX related mode configuration register, configured as ALT5 mode
Offset address:
Register Description:
The next step is to configure the GPIO related information, pull-up, CMOS input and output, etc.
Offset address:
Register Description:
Here is some information about the ERR_LED pin
GPIO register offset address
Because each GPIO has a maximum of 32 bits, each bit of the DR register above just represents the level of a single pin.
2. IMX257 Code Analysis
1. Define some registers
//Register base address; static unsigned long mem_iomux; static unsigned long mem_gpio3; static unsigned long base_iomux; //iomux base address 0X 43FA C000 - 0X 43FA FFFF static unsigned long base_gpio3; //gpio3 0X 53FA 4000 - 0X 53FA 7FFF //MUX_CTL mode selection configuration register #define MUX_CTL (*(volatile unsigned long *)(base_iomux + 0x0060)) //PAD_CTL GPIO common function settings #define PAD_CTL (*(volatile unsigned long *)(base_iomux + 0x0270)) //GPIO DR data register DR #define DR_GPIO3 (*(volatile unsigned long *)(base_gpio3 + 0x0000)) //GPIO GDIR direction control register GDIR #define GDIR_GPIO3 (*(volatile unsigned long *)(base_gpio3 + 0x0004)) |
As shown in the figure:
2. Initialize registers in the init function and make corresponding configurations
IO port application:
Configure pin to ALT5 GPIO mode
The level of the configuration pin, 1.8v, CMOS output, is configured to 0
Configure the port pin as output mode and initialize the level
Print the address information of each register
The LED light flashes at 1 second intervals
3. Release the IO port in the exit function
4. Compile and test
hardware:
As shown in the figure, the ERR_LED lights up.
ERR_LED is off
OK, we are done:
Attached is the driver code:
1 #include
2 #include
3 #include
4 #include
5 #include
6 #include
7 #include
8 #include
9 #include
10 #include
11 #include
12 #include
13 #include
14
15 #define Driver_NAME "err_led_dev"
16 #define DEVICE_NAME "err_led_dev"
17
18 static int major = 0;
19
20 //auto to create device node
21 static struct class *drv_class = NULL;
22 static struct class_device *drv_class_dev = NULL;
23
24 //Register base address;
25 static unsigned long mem_iomux;
26 static unsigned long mem_gpio3;
27 static unsigned long base_iomux; //iomux base address 0X 43FA C000 - 0X 43FA FFFF
28 static unsigned long base_gpio3; //gpio3 0X 53FA 4000 - 0X 53FA 7FFF
29 //MUX_CTL mode selection configuration register
30 #define MUX_CTL (*(volatile unsigned long *)(base_iomux + 0x0060))
31 //PAD_CTL GPIO common function settings
32 #define PAD_CTL (*(volatile unsigned long *)(base_iomux + 0x0270))
33 //GPIO DR data register DR
34 #define DR_GPIO3 (*(volatile unsigned long *)(base_gpio3 + 0x0000))
35 // GPIO GDIR direction control register GDIR
36 #define GDIR_GPIO3 (*(volatile unsigned long *)(base_gpio3 + 0x0004))
37
38
39 static int key_open(struct inode *inode, struct file *file)
40 {
41 printk("<0>function open!nn");
42 return 0;
43 }
44
45 static int key_read(struct file *filp, char __user *buff, size_t count, loff_t *offp)
46 {
47 return 0;
48 }
49
50 static ssize_t key_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos)
51 {
52 printk("<0>function write!nn");
53 return 1;
54 }
55
56 static int key_release(struct inode *inode, struct file *filp)
57 {
58 printk("<0>function write!nn");
59 return 0;
60 }
61
62 static int key_ioctl(struct inode *inode,struct file *flip,unsigned int command,unsigned long arg)
63 {
64 printk("<0>function ioctl!nn");
65 return 0;
66 }
67 static struct file_operations key_fops = {
68 .owner = THIS_MODULE, /* This is a macro that pushes to the __this_module variable that is automatically created when compiling the module*/
69 .open = key_open,
70 .read = key_read,
71 .write = key_write,
72 .release= key_release,
73 .ioctl = key_ioctl,
74 };
75
76 void gpio_addr(void){
77 printk("<0>addr base_iomux : %x n",base_iomux);
78 printk("<0>addr base_gpio3 : %x n",base_gpio3);
79 printk("<0>addr MUX_CTL : %x n",&MUX_CTL);
80 printk("<0>addr PAD_CTL : %x n",&PAD_CTL);
81 printk("<0>addr GDIR_GPIO3 : %x n",&GDIR_GPIO3);
82 printk("<0>addr DR_GPIO3 : %x n",&DR_GPIO3);
83 }
84
85 void led_on_off(void){
86 ssleep(1);
87 DR_GPIO3 |= (0x01 << 23); //Set GPIO2_23 to 1
88 ssleep(1);
89 DR_GPIO3 &= ~(0x01 << 23); // Clear GPIO2_23
90 ssleep(1);
91 DR_GPIO3 |= (0x01 << 23); //Set GPIO2_23 to 1
92 ssleep(1);
93 DR_GPIO3 &= ~(0x01 << 23); // Clear GPIO2_23
94 ssleep(1);
95 DR_GPIO3 |= (0x01 << 23); //Set GPIO2_23 to 1
96 ssleep(1);
97 DR_GPIO3 &= ~(0x01 << 23); // Clear GPIO2_23
98 ssleep(1);
99 DR_GPIO3 |= (0x01 << 23); //Set GPIO2_23 to 1
100 ssleep(1);
101 DR_GPIO3 &= ~(0x01 << 23); //Clear GPIO2_23
102 ssleep(1);
103 DR_GPIO3 |= (0x01 << 23); //Set GPIO2_23 to 1
104 }
105
106 static int __init key_irq_init(void)
107 {
108 printk("<0>nHello,this is %s module!nn",Driver_NAME);
109 //register and mknod
110 major = register_chrdev(0,Driver_NAME,&key_fops);
111 drv_class = class_create(THIS_MODULE,Driver_NAME);
112 drv_class_dev = device_create(drv_class,NULL,MKDEV(major,0),NULL,DEVICE_NAME); /*/dev/key_query*/
113
114 //IO port application ioremap can directly access these addresses through pointers
115 base_iomux = ioremap(0x43FAC000,0xFFF);
116 base_gpio3 = ioremap(0x53FA4000,0xFFF);
117
118 //MUX_CTL
119 MUX_CTL &= ~(0x07 << 0);
120 MUX_CTL |= (0X05 << 0); //Set to ALT5 GPIO3_23 ERR_LED
121 //PAD_CTL
122 PAD_CTL &= ~(0x01<<13 | 0x01<<3 | 0x03<<1 | 0x01<<0); //1.8v does not require pull-up or pull-down CMOS output slew rate
123 //GDIR_GPIO3 is configured as output mode
124 GDIR_GPIO3 &= ~(0x01 << 23);
125 GDIR_GPIO3 |= (0x01 << 23); //Configure to output mode
126
127 //DR_GPIO3 is configured as output 0 to light up ERR_LED
128 DR_GPIO3 &= ~(0x01 << 23); // Clear GPIO2_23
129 DR_GPIO3 &= ~(0x01 << 23); // Clear GPIO2_23
130 gpio_addr();
131 led_on_off();
132 return 0;
133 }
134
135 static void __exit key_irq_exit(void)
136 {
137 gpio_addr();
138 printk("<0>nGoodbye,%s!nn",Driver_NAME);
139 led_on_off();
140
141 unregister_chrdev(major,Driver_NAME);
142 device_unregister(drv_class_dev);
143 class_destroy(drv_class);
144
145 //Release IO port
146 iounmap(base_iomux);
147 iounmap(base_gpio3);
148 }
149
150
151 /* These two lines specify the driver's initialization function and uninstallation function*/
152 module_init(key_irq_init);
153 module_exit(key_irq_exit);
154
155 /* Describes some information about the driver, not required*/
156 MODULE_AUTHOR("Lover Cher");
157 MODULE_VERSION("0.1.0");
158 MODULE_DESCRIPTION("IMX257 key Driver");
159 MODULE_LICENSE("GPL");
Previous article:IMX257 BEEP driver implementation
Next article:IMX257 Linux memory space memory allocation
Recommended ReadingLatest update time:2024-11-15 01:42
- 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
- CGD and Qorvo to jointly revolutionize motor control solutions
- CGD and Qorvo to jointly revolutionize motor control solutions
- Keysight Technologies FieldFox handheld analyzer with VDI spread spectrum module to achieve millimeter wave analysis function
- Infineon's PASCO2V15 XENSIV PAS CO2 5V Sensor Now Available at Mouser for Accurate CO2 Level Measurement
- Advanced gameplay, Harting takes your PCB board connection to a new level!
- Advanced gameplay, Harting takes your PCB board connection to a new level!
- A new chapter in Great Wall Motors R&D: solid-state battery technology leads the future
- Naxin Micro provides full-scenario GaN driver IC solutions
- Interpreting Huawei’s new solid-state battery patent, will it challenge CATL in 2030?
- Are pure electric/plug-in hybrid vehicles going crazy? A Chinese company has launched the world's first -40℃ dischargeable hybrid battery that is not afraid of cold
- Request: DC-DC small package chip similar to LM2596
- What is the reason! Another wind turbine fire accident! And caused a ground wildfire
- 【Iprober 520 current probe】Practical use in motor control
- Can you please help me find out where is the problem with the program?
- How to add c files in esp32 idf components to compile
- Have you noticed the LPDSP32 audio codec inside RSL10? Does your project use this resource?
- Will the push-pull circuit be straight through?
- EEWORLD University - Industrial Internet of Things using CC1310 sub-1 GHz wireless MCU
- A simple way to distinguish between broadband FM and narrowband FM
- Wireless Connectivity Technology Selection Guide