GPIO LED AND KEY:
part1:gpio leds and gpio btns combination. (include 1~4)
part2:use gpio btns interrupt to trigger led on and off. (include 5, 6, 7)
part3:some useful tips. (include 8)
my vivado & sdk projects ( ready to download):
1.custom_ip ( only led exists)
2.custom_ip ( led with key)
3.custom_ip (led key and interrupts)
my driver package ( ready to download):
gpio_driver.tar.bz2
(1)Block Design:
(2)Constraints:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40set_property PACKAGE_PIN T22 [get_ports {leds_8bits_tri_o[0]}] set_property IOSTANDARD LVCMOS33 [get_ports {leds_8bits_tri_o[0]}] set_property PACKAGE_PIN T21 [get_ports {leds_8bits_tri_o[1]}] set_property IOSTANDARD LVCMOS33 [get_ports {leds_8bits_tri_o[1]}] set_property PACKAGE_PIN U22 [get_ports {leds_8bits_tri_o[2]}] set_property IOSTANDARD LVCMOS33 [get_ports {leds_8bits_tri_o[2]}] set_property PACKAGE_PIN U21 [get_ports {leds_8bits_tri_o[3]}] set_property IOSTANDARD LVCMOS33 [get_ports {leds_8bits_tri_o[3]}] set_property PACKAGE_PIN V22 [get_ports {leds_8bits_tri_o[4]}] set_property IOSTANDARD LVCMOS33 [get_ports {leds_8bits_tri_o[4]}] set_property PACKAGE_PIN W22 [get_ports {leds_8bits_tri_o[5]}] set_property IOSTANDARD LVCMOS33 [get_ports {leds_8bits_tri_o[5]}] set_property PACKAGE_PIN U19 [get_ports {leds_8bits_tri_o[6]}] set_property IOSTANDARD LVCMOS33 [get_ports {leds_8bits_tri_o[6]}] set_property PACKAGE_PIN U14 [get_ports {leds_8bits_tri_o[7]}] set_property IOSTANDARD LVCMOS33 [get_ports {leds_8bits_tri_o[7]}] set_property PACKAGE_PIN P16 [get_ports {btns_5bits_tri_i[0]}] set_property IOSTANDARD LVCMOS25 [get_ports {btns_5bits_tri_i[0]}] set_property PACKAGE_PIN N15 [get_ports {btns_5bits_tri_i[2]}] set_property IOSTANDARD LVCMOS25 [get_ports {btns_5bits_tri_i[2]}] set_property PACKAGE_PIN T18 [get_ports {btns_5bits_tri_i[4]}] set_property IOSTANDARD LVCMOS25 [get_ports {btns_5bits_tri_i[4]}] set_property PACKAGE_PIN R18 [get_ports {btns_5bits_tri_i[3]}] set_property IOSTANDARD LVCMOS25 [get_ports {btns_5bits_tri_i[3]}] set_property PACKAGE_PIN R16 [get_ports {btns_5bits_tri_i[1]}] set_property IOSTANDARD LVCMOS25 [get_ports {btns_5bits_tri_i[1]}]
(3) Standalone Program
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44#include <stdio.h> #include "platform.h" #include "xil_io.h" #include "xgpio.h" #include "xparameters.h" //void print(char *str); int main() { init_platform(); print("Hello Worldnr"); u32 btn_data; //XGpio //btn_data = Xil_In32(0x41200000); // printf("data is xxx %dn",btn_data); Xil_Out32(0x41200000 , 0x08); sleep(1); //Xil_Out32(0x41200000 , 0x00); while(1){ //Xil_Out32(0x41210000 , 0x00000000); btn_data = Xil_In32(0x41210000); //if(btn_data & 0x01){ //Xil_Out32(0x41210000 , 0x01); sleep(1); printf("data is %ldn",btn_data); //} /*if(btn_data & 0x00000001) Xil_Out32(0x41200000 , 0x01); if(btn_data & 0x00000002) Xil_Out32(0x41200000 , 0x02); if(btn_data & 0x00000004) Xil_Out32(0x41200000 , 0x04); if(btn_data & 0x00000008) Xil_Out32(0x41200000 , 0x08); */ } //sleep(1); return 0; }
(4) Linux Driver:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154#include <linux/module.h> #include <linux/version.h> #include <linux/kernel.h> #include <linux/init.h> #include <linux/fs.h> #include <linux/cdev.h> #include <linux/delay.h> #include <linux/spinlock.h> #include <linux/device.h> #include <linux/types.h> #include <linux/ioctl.h> #include <asm/io.h> #include <asm/uaccess.h> #include <asm/atomic.h> #include <linux/wait.h> #include <linux/cdev.h> #define DEVICE_NAME "gpio_dev" #define LED_PHY_ADDR 0x41200000 #define KEY_PHY_ADDR 0X41210000 /* #define ULTRASONIC_IOC_MAGIC 'Z' #define LED_SHUTDOWN _IOR(ULTRASONIC_IOC_MAGIC, 0, int) #define LED_OPEN _IOR(ULTRASONIC_IOC_MAGIC, 1, int) #define GET_KEY_STATUS _IOR(ULTRASONIC_IOC_MAGIC, 2, int) */ static unsigned long led_addr = 0; static unsigned long key_addr = 0; static struct class* gpio_class = NULL; static struct device* gpio_device = NULL; static int gpio_major = 0; //arg means the led number, cmd controls it on or off static ssize_t gpio_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { //printk("fun(gpio_ioctl):"); u32 status = 0xff; int ret; switch(cmd){ case 0: case 1: //if(arg > 8) // return -EINVAL; status = ioread32(led_addr); if(0 == cmd) status &= ~(0x1 << arg); else if(1 == cmd) status |= (0x1 << arg); iowrite32(status,led_addr); //printk("debug1 cmd= %dn",cmd); return 0; case 3: //printk("debug3 cmd=%dn",cmd); status = ioread32(key_addr); ret = __put_user(status, (u32 *)arg); printk("key print = 0x%xn",status); return 0; default: printk("default cmd=%dn",cmd); return -EINVAL; } } /* static ssize_t key_read(struct file *file,u32 __user *buf, size_t count, loff_t *ppos) { u32 data; int ret = 0; data = ioread32(key_addr); ret = __put_user(data, (u32 *)buf); printk("key print = 0x%xn",data); return (sizeof(u32)); } */ static struct file_operations gpio_fops = { .owner = THIS_MODULE, .unlocked_ioctl = gpio_ioctl, // .read = key_read, }; static int __init gpio_init(void) { int ret; printk("debug0"); ret = register_chrdev(0,DEVICE_NAME, &gpio_fops); if(ret < 0) { printk("gpio: can't get major numbern"); return ret; } printk("debug1"); gpio_major = ret; gpio_class = class_create(THIS_MODULE, "gpio_class"); if(IS_ERR(gpio_class)) { printk("gpio: failed in creating classn"); unregister_chrdev(gpio_major, DEVICE_NAME); return -1; } printk("debug2"); gpio_device = device_create(gpio_class,NULL,MKDEV(gpio_major,0),NULL,DEVICE_NAME); if(IS_ERR(gpio_device)) { printk("gpio: failed in creating device!n"); unregister_chrdev(gpio_major, DEVICE_NAME); class_unregister(gpio_class); class_destroy(gpio_class); return -1; } led_addr = (unsigned long) ioremap(LED_PHY_ADDR, sizeof(u32)); key_addr = (unsigned long) ioremap(KEY_PHY_ADDR, sizeof(u32)); /* iowrite32(0x00,led_addr); mdelay(100); iowrite32(0xff,led_addr); */ printk("gpio installed successfully!"); return 0; } static void __exit gpio_exit(void) { /* iowrite32(0x00,led_addr); mdelay(100); iowrite32(0xff,led_addr); */ device_destroy(gpio_class,MKDEV(gpio_major, 0)); class_unregister(gpio_class); class_destroy(gpio_class); unregister_chrdev(gpio_major,DEVICE_NAME); printk("gpio module exit!"); } module_init(gpio_init); module_exit(gpio_exit); MODULE_AUTHOR("seg"); MODULE_LICENSE("GPL");
(5) Linux App:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/ioctl.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <sys/select.h> #include <sys/time.h> static int led_fd; int main(void) { int i; // open device led_fd = open("/dev/gpio_dev", 0); if (led_fd < 0) { perror("open device gpio_dev error!n"); exit(1); } printf("Please look at the ledsn"); // led all off ioctl(led_fd, 1, 0); ioctl(led_fd, 1, 1); ioctl(led_fd, 1, 2); ioctl(led_fd, 1, 3); ioctl(led_fd, 1, 4); ioctl(led_fd, 1, 5); ioctl(led_fd, 1, 6); ioctl(led_fd, 1, 7); for(i=0;i<2;i++) { ioctl(led_fd, 0, 0); usleep(50000); ioctl(led_fd, 0, 1); usleep(50000); ioctl(led_fd, 0, 2); usleep(50000); ioctl(led_fd, 0, 3); usleep(50000); ioctl(led_fd, 0, 4); usleep(50000); ioctl(led_fd, 0, 5); usleep(50000); ioctl(led_fd, 0, 6); usleep(50000); ioctl(led_fd, 0, 7); usleep(50000); // led off one by one ioctl(led_fd, 1, 0); usleep(50000); ioctl(led_fd, 1, 1); usleep(50000); ioctl(led_fd, 1, 2); usleep(50000); ioctl(led_fd, 1, 3); usleep(50000); ioctl(led_fd, 1, 4); usleep(50000); ioctl(led_fd, 1, 5); usleep(50000); ioctl(led_fd, 1, 6); usleep(50000); ioctl(led_fd, 1, 7); usleep(50000); } while(1) { unsigned int key = 0; //printf("original = %d , %x",key,key); ioctl(led_fd, 3, &key); printf("key = %dn",key); for(i=0;i<8;i++) ioctl(led_fd,0,i); if(key & (0x01<<0)) ioctl(led_fd, 1, 0); else if(key & (0x01<<1)) ioctl(led_fd, 1, 1); else if(key & (0x01<<2)) ioctl(led_fd, 1, 2); else if(key & (0x01<<3)) ioctl(led_fd, 1, 3); else if(key & (0x01<<4)) ioctl(led_fd, 1, 4); else{} usleep(1000000); } close(led_fd); return 0; }
(5)Hardware Interrupt Vivado Project
(6)Hardware Interrupt SDK Project
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258#include "xparameters.h" #include "xgpio.h" #include "xil_exception.h" #include "xscugic.h" /************************** Constant Definitions *****************************/ #define LED_ADDR 0x41200000 #define KEY_ADDR 0X41210000 #define GPIO_DEVICE_ID XPAR_AXI_GPIO_1_DEVICE_ID #define INTC_GPIO_INTERRUPT_ID XPAR_FABRIC_GPIO_1_VEC_ID #define INTC_DEVICE_ID XPAR_SCUGIC_0_DEVICE_ID #define INTC XScuGic #define INTC_HANDLER XScuGic_InterruptHandler #define GPIO_ALL_LEDS 0xFFFF #define GPIO_ALL_BUTTONS 0xFFFF /* * The following constants define the GPIO channel that is used for the buttons * and the LEDs. They allow the channels to be reversed easily. */ #define BUTTON_CHANNEL 1 /* Channel 1 of the GPIO Device */ #define LED_CHANNEL 2 /* Channel 2 of the GPIO Device */ #define BUTTON_INTERRUPT XGPIO_IR_CH1_MASK /* Channel 1 Interrupt Mask */ /* * The following constant is used to wait after an LED is turned on to make * sure that it is visible to the human eye. This constant might need to be * tuned for faster or slower processor speeds. */ #define LED_DELAY 1000000 /**************************** Type Definitions *******************************/ typedef struct { u32 ButtonMask; /* The bit corresponding to the button */ u32 LedMask; /* The bit corresponding to the LED */ } MapButtonTable; /************************** Function Prototypes ******************************/ int MapButton2Led(u32 Buttons, u32 *ButtonFoundPtr); void SequenceLeds(); void GpioIsr(void *InstancePtr); int SetupInterruptSystem(); /************************** Variable Definitions *****************************/ static XGpio Gpio; /* The Instance of the GPIO Driver */ static INTC Intc; /* The Instance of the Interrupt Controller Driver */ volatile int InterruptCount; /* Count of interrupts that have occured */ int main(void) { int Status; SequenceLeds(); /* Initialize the GPIO driver. If an error occurs then exit */ Status = XGpio_Initialize(&Gpio, GPIO_DEVICE_ID); if (Status != XST_SUCCESS) { return XST_FAILURE; } /* * Perform a self-test on the GPIO. This is a minimal test and only * verifies that there is not any bus error when reading the data * register */ XGpio_SelfTest(&Gpio); /* * Setup the interrupts such that interrupt processing can occur. If * an error occurs then exit */ Status = SetupInterruptSystem(); if (Status != XST_SUCCESS) { return XST_FAILURE; } printf("in the loop:n"); while (1) { } return XST_SUCCESS; } void SequenceLeds() { u32 led = 0x01; u32 out = 0x0; int i; for (i = 0; i < 8; i++) { out = led << i; Xil_Out32(LED_ADDR, out); sleep(1); } Xil_Out32(LED_ADDR, 0x00); } /********************************************************************************************************************************************************/ void GpioIsr(void *InstancePtr) { XGpio *GpioPtr = (XGpio *)InstancePtr; u32 Led; u32 LedState; u32 Buttons; u32 ButtonFound; u32 ButtonsChanged = 0; static u32 PreviousButtons; printf("Enter GpioIsr!n"); /* * Disable the interrupt */ XGpio_InterruptDisable(GpioPtr, BUTTON_INTERRUPT); /* Keep track of the number of interrupts that occur */ InterruptCount++; Xil_Out32(LED_ADDR,0x00); ButtonsChanged = Xil_In32(KEY_ADDR); printf("BUTTON:%d;",ButtonsChanged); //while (ButtonsChanged != 0) { /* * Determine which button changed state and then get * the current state of the associated LED */ printf("SET_LED=%d",ButtonsChanged); Xil_Out32(LED_ADDR,ButtonsChanged); // LedState = Xil_In32(LED_ADDR) & Led; /* * Clear the button that is being processed so that it is * done and others can be handled also */ // ButtonsChanged &= ~ButtonFound; /* Toggle the state of the LED */ // if (LedState) { // Xil_Out32(LED_ADDR,LedState & ~Led); // } else { // Xil_Out32(LED_ADDR,Led); // } // } /* Clear the interrupt such that it is no longer pending in the GPIO */ (void)XGpio_InterruptClear(GpioPtr, BUTTON_INTERRUPT); /* * Enable the interrupt */ XGpio_InterruptEnable(GpioPtr, BUTTON_INTERRUPT); } int SetupInterruptSystem() { int Result; INTC *IntcInstancePtr = &Intc; XScuGic_Config *IntcConfig; /* * Initialize the interrupt controller driver so that it is ready to * use. */ IntcConfig = XScuGic_LookupConfig(INTC_DEVICE_ID); if (NULL == IntcConfig) { return XST_FAILURE; } Result = XScuGic_CfgInitialize(IntcInstancePtr, IntcConfig, IntcConfig->CpuBaseAddress); if (Result != XST_SUCCESS) { return XST_FAILURE; } XScuGic_SetPriorityTriggerType(IntcInstancePtr, INTC_GPIO_INTERRUPT_ID, 0xA0, 0x3); /* * Connect the interrupt handler that will be called when an * interrupt occurs for the device. */ Result = XScuGic_Connect(IntcInstancePtr, INTC_GPIO_INTERRUPT_ID, (Xil_ExceptionHandler)GpioIsr, &Gpio); if (Result != XST_SUCCESS) { return Result; } printf("XST_SUCCESS"); /* * Enable the interrupt for the GPIO device. */ XScuGic_Enable(IntcInstancePtr, INTC_GPIO_INTERRUPT_ID); /* * Enable the GPIO channel interrupts so that push button can be * detected and enable interrupts for the GPIO device */ XGpio_InterruptEnable(&Gpio, BUTTON_INTERRUPT); XGpio_InterruptGlobalEnable(&Gpio); /* * Initialize the exception table and register the interrupt * controller handler with the exception table */ Xil_ExceptionInit(); Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT, (Xil_ExceptionHandler)INTC_HANDLER, IntcInstancePtr); /* Enable non-critical exceptions */ Xil_ExceptionEnable(); return XST_SUCCESS; }
(7) Interrupt driver edition
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222#include <linux/module.h> #include <linux/version.h> #include <linux/kernel.h> #include <linux/init.h> #include <linux/fs.h> #include <linux/cdev.h> #include <linux/delay.h> #include <linux/spinlock.h> #include <linux/device.h> #include <linux/types.h> #include <linux/ioctl.h> #include <asm/io.h> #include <asm/uaccess.h> #include <asm/atomic.h> #include <linux/wait.h> #include <linux/cdev.h> #include <linux/interrupt.h> #include <asm/signal.h> #include <linux/gpio.h> #include <linux/irq.h> #define DEVICE_NAME "gpio_dev" #define GPIO_BASEADDR 0x41200000 #define LED_PHY_ADDR 0x41200000 #define KEY_PHY_ADDR 0X41210000 #define INTERRUPT_ID 91 #define IRQ_MASK 0x1 #define IRQ_DEVICE_ID 0 #define XGPIO_GIE_OFFSET 0x11C /**< Glogal interrupt enable register */ #define XGPIO_ISR_OFFSET 0x120 /**< Interrupt status register */ #define XGPIO_IER_OFFSET 0x128 /**< Interrupt enable register */ #define XGPIO_GIE_GINTR_ENABLE_MASK 0x80000000 //#define is_keypad_irq() (!(inb(IRQ_STAT_ADDR) & IRQ_MASK)) //#define disable_irq() (iowrite32(IRQ_DIST_BASEADDR+XGPIO_IER_OFFSET,ioread32(IRQ_DIST_BASEADDR+XGPIO_IER_OFFSET) & ~IRQ_MASK)) //#define enable_irq() (iowrite32(IRQ_DIST_BASEADDR+XGPIO_IER_OFFSET,ioread32(IRQ_DIST_BASEADDR+XGPIO_IER_OFFSET) | IRQ_MASK)) //#define clear_irq() (iowrite32(KEY_PHY_ADDR+XGPIO_IER_OFFSET,ioread32(KEY_PHY_ADDR+XGPIO_IER_OFFSET) & IRQ_MASK)) static unsigned long led_addr = 0; static unsigned long key_addr = 0; static struct class* gpio_class = NULL; static struct device* gpio_device = NULL; static int gpio_major = 0; typedef struct { dev_t dev_no; u32 IsReady; int InterruptPresent; u32 BaseAddress; // spinlock_t lock; atomic_t lock; } KEY_DEV; static KEY_DEV keydev; //arg means the led number, cmd controls it on or off static ssize_t gpio_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { //printk("fun(gpio_ioctl):"); u32 status = 0xff; int ret; switch(cmd){ case 0: case 1: //if(arg > 8) // return -EINVAL; status = ioread32(led_addr); if(0 == cmd) status &= ~(0x1 << arg); else if(1 == cmd) status |= (0x1 << arg); iowrite32(status,led_addr); return 0; case 3: status = ioread32(key_addr); ret = __put_user(status, (u32 *)arg); printk("key print = 0x%xn",status); return 0; default: printk("default cmd=%dn",cmd); return -EINVAL; } } static void InterruptClear() { u32 val; val = ioread32(key_addr + XGPIO_ISR_OFFSET); iowrite32(val & IRQ_MASK,key_addr + XGPIO_ISR_OFFSET); printk("int cleared"); } static irqreturn_t key_interrupt(int irq, void *dev_id, struct pt_regs *regs) { u32 status = 0xff; //disable_irq(INTERRUPT_ID); // disable_irq(); status = ioread32(key_addr); iowrite32(status,led_addr); printk("key print = 0x%xn",status); // clear_irq(); //enable_irq(INTERRUPT_ID); // enable_irq(); InterruptClear(); return 0; } static void InterruptEnable() { //from stand alone program //XGpio_InterruptEnable(&Gpio, BUTTON_INTERRUPT); //XGpio_InterruptGlobalEnable(&Gpio); u32 val; printk("debug1 read addr = %lxn",key_addr+XGPIO_IER_OFFSET); // 0x128 val = ioread32(key_addr + XGPIO_IER_OFFSET); printk("debug2 val=%lxn",val); // 0x128 0x1 iowrite32(val | IRQ_MASK,key_addr + XGPIO_IER_OFFSET); printk("debug3 "); // 0x11c 0x80000000 iowrite32(XGPIO_GIE_GINTR_ENABLE_MASK,key_addr + XGPIO_GIE_OFFSET); } static int key_open(struct inode *inode, struct file *filp) { int ret; printk("open!n"); InterruptEnable(); printk("interrupt Enabled!n"); ret = request_irq(INTERRUPT_ID, key_interrupt,IRQF_TRIGGER_RISING, DEVICE_NAME, &keydev); if(ret) { printk("could not register interrupt!"); return ret; } //disable_irq(INTERRUPT_ID); //enable_irq(INTERRUPT_ID); // enable_irq(); printk("register interrupt success!n"); return 0; } static struct file_operations gpio_fops = { .owner = THIS_MODULE, .unlocked_ioctl = gpio_ioctl, .open = key_open, // .read = key_read, }; static int __init gpio_init(void) { int ret; ret = register_chrdev(0,DEVICE_NAME, &gpio_fops); if(ret < 0) { printk("gpio: can't get major numbern"); return ret; } gpio_major = ret; gpio_class = class_create(THIS_MODULE, "gpio_class"); if(IS_ERR(gpio_class)) { printk("gpio: failed in creating classn"); unregister_chrdev(gpio_major, DEVICE_NAME); return -1; } gpio_device = device_create(gpio_class,NULL,MKDEV(gpio_major,0),NULL,DEVICE_NAME); if(IS_ERR(gpio_device)) { printk("gpio: failed in creating device!n"); unregister_chrdev(gpio_major, DEVICE_NAME); class_unregister(gpio_class); class_destroy(gpio_class); return -1; } led_addr = (unsigned long) ioremap(LED_PHY_ADDR, sizeof(u32)); key_addr = (unsigned long) ioremap(KEY_PHY_ADDR, sizeof(u32)); /* iowrite32(0x00,led_addr); mdelay(100); iowrite32(0xff,led_addr); */ printk("gpio installed successfully!n"); return 0; } static void __exit gpio_exit(void) { /* iowrite32(0x00,led_addr); mdelay(100); iowrite32(0xff,led_addr); */ device_destroy(gpio_class,MKDEV(gpio_major, 0)); class_unregister(gpio_class); class_destroy(gpio_class); unregister_chrdev(gpio_major,DEVICE_NAME); printk("gpio module exit!"); } module_init(gpio_init); module_exit(gpio_exit); MODULE_AUTHOR("seg"); MODULE_LICENSE("GPL");
(8) Useful Tips for write linux driver
Part1: we can use commands below to test gpio led.
1
2
3
4
5cd /sys/class/gpio/ echo 248 > ./export cd gpio248/ echo "out" > ./direction echo 1 > ./value
Part2: we can use commands below to see interrupts status.
1
2cat /proc/interrupts cat /proc/stat
转载于:https://www.cnblogs.com/shenerguang/p/3730047.html
最后
以上就是感性白昼最近收集整理的关于Learn ZYNQ Programming(1)的全部内容,更多相关Learn内容请搜索靠谱客的其他文章。
发表评论 取消回复