gpio



Marvell-linux研究—gpio.c源代码分析

 

转载时请注明出处和作者联系方式:http://blog.csdn.net/absurd

作者联系方式:李先静 <xianjimli at hotmail dot com>

更新时间:2007-7-4

 

GPIO General Programmable Input Output Pin的首字母缩写,G(General)表示通用,就是可以用于多种用途,P(Programmable)表示可编程,就是可以用程序去控制它,I(Input)表示输入,就是可以用于从外设读取数据,而O(Output)表示输出,也就是可以用于向外设输出数据。总之,它是CPU与外设进行交互的一种方式。

 

正如其名字所示的,它可以用于多种用途,至于具体做什么,要根据实际情况进行配置。最简单的用途可能是用它来连接一个LED,用程序来控制LED点亮或者关闭,这种用法在实验板上很常见。

 

GPIO编程简单而又功能强大,所以我们选择它作为研究的入口。今天我们分析一下arch/arm/mach-pxa/gpio.c的源代码,该文件提供了对GPIO编程提供了最基本的抽象:

56 int mhn_gpio_set_direction(int gpio_id, int dir)
 57 {
 58         unsigned long flags;
 59         int gpio = MFP2GPIO(gpio_id);
 60 
 61         GPIO_ID_VERIFY(gpio);
 62 
 63         spin_lock_irqsave(&gpio_spin_lock, flags);
 64 #if defined(CONFIG_MONAHANS_GPIOEX)
 65         if (gpio >= GPIO_EXP_START) {
 66                 spin_unlock_irqrestore(&gpio_spin_lock, flags);
 67                 return gpio_exp_set_direction(gpio, dir);
 68         }
 69 #endif
 70         if (dir == GPIO_DIR_IN)
 71                 G CDR(gpio) = 1u << (gpio & 0x1f);
 72         else
 73                 GSDR(gpio) = 1u << (gpio & 0x1f);
 74 
 75         spin_unlock_irqrestore(&gpio_spin_lock, flags);
 76 
 77         return 0;
 78 }

 

该函数用于设置某个GPIO数据的流动方向,所谓方向就是指input还是output,如果dir等于GPIO_DIR_IN则为input,否则为output。只能二选一,不同时即作为input又作为output。

 

MFP2GPIO(gpio_id)只是确保gpio_id的高16位为0,而GPIO_ID_VERIFY(gpio)确保gpio_id没有超出范围。

 

64-69行:如果支持GPIOEX,而且gpio >= GPIO_EXP_START,则调用另外一个函数gpio_exp_set_direction去设置。后面的函数若有类似的处理,我们就不多说了。

 

注意:

PXA系列芯片有128个GPIO,对于一般的设置,每个GPIO都占用寄存器的一位,所以每类寄存器都需要4个(共128位)。G CDR(gpio)之类宏就是为了把gpio映射到对应的寄存器上,而1u << (gpio & 0x1f)之类的代码就是为了设置对应的位。

 

PXA 系列芯片对于一般的GPIO设置,都有三个寄存器,一个用于读取设置,一个用于把设置置为1,一个用于把设置清为零。这样做的目的可能是为了提高效率,在 设置时不必把寄存器的值先读出来,设置适当的位,然后写回去。按这种方式设计,在设置时,不会影响其它GPIO的值,所以不必读取原来的值。

 

 80 int mhn_gpio_get_direction(int gpio_id)
 81 {
 82         int gpio = MFP2GPIO(gpio_id);
 83 
 84         GPIO_ID_VERIFY(gpio);
 85 #if defined(CONFIG_MONAHANS_GPIOEX)
 86         if (gpio >= GPIO_EXP_START)
 87                 return gpio_exp_get_direction(gpio);
 88 #endif
 89 
 90         if (GPDR(gpio) & (1u << (gpio & 0x1f)))
 91                 return GPIO_DIR_OUT;
 92         else
 93                 return GPIO_DIR_IN;
 94 }

该函数获取某个GPIO数据的流动方向,正如前面所说,获取方向时用的另外一个寄存器--GPDR。

 

 96 int mhn_gpio_set_level(int gpio_id, int level)
 97 {
 98         unsigned long flags;
 99         int gpio = MFP2GPIO(gpio_id);
100 
101         GPIO_ID_VERIFY(gpio);
102 
103         spin_lock_irqsave(&gpio_spin_lock, flags);
104 #if defined(CONFIG_MONAHANS_GPIOEX)
105         if (gpio >= GPIO_EXP_START) {
106                 spin_unlock_irqrestore(&gpio_spin_lock, flags);
107                 return gpio_exp_set_level(gpio, level);
108         }
109 #endif
110 
111         if (level == GPIO_LEVEL_LOW)
112                 GPCR(gpio) = 1u << (gpio & 0x1f);
113         else
114                 GPSR(gpio) = 1u << (gpio & 0x1f);
115 
116         spin_unlock_irqrestore(&gpio_spin_lock, flags);
117 
118         return 0;
119 }

 

该函数用于设置输出的数据,可以设置输出高电平或者低电平,它与设置数据流动方向的函数类似,只是操作GPCR和GPSR两个寄存器,这里不再多说。让人费解是,不就是输出的数据嘛,为什么要叫level而不叫data呢。我想可能与《PXA300 and PXA310 Developers Manual 1》的4.11.3.2中所说的Second Level Generic Wakeups有关呢。

 

121 int mhn_gpio_get_level(int gpio_id)
122 {
123         int gpio = MFP2GPIO(gpio_id);
124 
125         GPIO_ID_VERIFY(gpio);
126 #if defined(CONFIG_MONAHANS_GPIOEX)
127         if (gpio >= GPIO_EXP_START)
128                 return gpio_exp_get_level(gpio);
129 #endif
130 
131         if (GPLR(gpio) & (1u << (gpio & 0x1f)))
132                 return GPIO_LEVEL_HIGH;
133         else
134                 return GPIO_LEVEL_LOW;
135 }

 

该函数用于获取输入数据,其与获取数据流动方向类似,只是操作GPLR寄存器。

 

140 int mhn_gpio_set_rising_edge_detect(int gpio_id, int enable)
141 {
142         unsigned long flags;
143         int gpio = MFP2GPIO(gpio_id);
144 
145         GPIO_ID_VERIFY(gpio);
146 #if defined(CONFIG_MONAHANS_GPIOEX)
147         if (gpio >= GPIO_EXP_START)
148                 return 0;
149 #endif
150 
151         spin_lock_irqsave(&gpio_spin_lock, flags);
152 
153         if (enable == 0)
154                 GCRER(gpio) = 1u << (gpio & 0x1f);
155         else
156                 GSRER(gpio) = 1u << (gpio & 0x1f);
157 
158         spin_unlock_irqrestore(&gpio_spin_lock, flags);
159 
160         return 0;
161 }

 

该函数用于设置是否启用上升沿触发中断,它与设置数据流动方向的函数类似,只是操作GCRER和GSRER两个寄存器。如果启用,则输入数据从低电平进入高电平时触发中断。

 

163 int mhn_gpio_get_rising_edge_detect(int gpio_id)
164 {
165         int gpio = MFP2GPIO(gpio_id);
166 
167         GPIO_ID_VERIFY(gpio);
168 #if defined(CONFIG_MONAHANS_GPIOEX)
169         if (gpio >= GPIO_EXP_START)
170                 return 0;
171 #endif
172 
173         if (GRER(gpio) & (1u << (gpio & 0x1f)))
174                 return 1;
175 
176         return 0;
177 }

 

该函数用于判断是否启用了上升沿触发中断。

 

179 int mhn_gpio_set_falling_edge_detect(int gpio_id, int enable)
180 {
181         unsigned long flags;
182         int gpio = MFP2GPIO(gpio_id);
183 
184         GPIO_ID_VERIFY(gpio);
185 
186 #if defined(CONFIG_MONAHANS_GPIOEX)
187         if (gpio >= GPIO_EXP_START)
188                 return 0;
189 #endif
190 
191         spin_lock_irqsave(&gpio_spin_lock, flags);
192 
193         if (enable == 0)
194                 GCRER(gpio) = 1u << (gpio & 0x1f);
195         else
196                 GSRER(gpio) = 1u << (gpio & 0x1f);
197 
198         spin_unlock_irqrestore(&gpio_spin_lock, flags);
199 
200         return 0;
201 }

 

该函数用于设置是否启用下降沿触发中断,它与设置数据流动方向的函数类似,只是操作GCFER和GSFER两个寄存器。如果启用,则输入数据从高电平进入低电平时触发中断。由于该函数与mhn_gpio_set_rising_edge_detect极为类似,作者copy-paste时忘了修改寄器,所以代码中的寄存器是错的。

 

203 int mhn_gpio_get_falling_edge_detect(int gpio_id)
204 {
205         int gpio = MFP2GPIO(gpio_id);
206 
207         GPIO_ID_VERIFY(gpio);
208 
209 #if defined(CONFIG_MONAHANS_GPIOEX)
210         if (gpio >= GPIO_EXP_START)
211                 return 0;
212 #endif
213 
214         if (GFER(gpio) & (1u << (gpio & 0x1f)))
215                 return 1;
216 
217         return 0;
218 }

 

该函数用于判断是否启用了下降沿触发中断。

 

220 int mhn_gpio_get_edge_detect_status(int gpio_id)
221 {
222         int gpio = MFP2GPIO(gpio_id);
223 
224         GPIO_ID_VERIFY(gpio);
225 
226 #if defined(CONFIG_MONAHANS_GPIOEX)
227         if (gpio >= GPIO_EXP_START)
228                 return 0;
229 #endif
230 
231         if (GEDR(gpio) & (1u << (gpio & 0x1f)))
232                 return 1;
233 
234         return 0;
235 }

 

该函数用于检测是否发生了电平变化,即是否有上升沿触发中断,或者下降沿触发中断发生。

 

237 int mhn_gpio_clear_edge_detect_status(int gpio_id)
238 {
239         unsigned long flags;
240         int gpio = MFP2GPIO(gpio_id);
241 
242         GPIO_ID_VERIFY(gpio);
243 
244 #if defined(CONFIG_MONAHANS_GPIOEX)
245         if (gpio >= GPIO_EXP_START)
246                 return 0;
247 #endif
248 
249         spin_lock_irqsave(&gpio_spin_lock, flags);
250 
251         GEDR(gpio) = 1u << (gpio & 0x1f);
252 
253         spin_unlock_irqrestore(&gpio_spin_lock, flags);
254 
255         return 0;
256 }

 

清除发生电平变化的标志,如果发生电平变化,GEDR会自动设置,但不会自动清除,而需要程序主动清除。这里获取和清除是同一个寄存器,原因是不需要程序去设置,所以不需要独立的寄存器。

 

262 void mhn_gpio_save(void)
263 {
264         gpio_saved_reg.gpdr0 = GPDR0;
265         gpio_saved_reg.gpdr1 = GPDR1;
266         gpio_saved_reg.gpdr2 = GPDR2;
267         gpio_saved_reg.gpdr3 = GPDR3;
268 
269         gpio_saved_reg.gplr0 = GPLR0;
270         gpio_saved_reg.gplr1 = GPLR1;
271         gpio_saved_reg.gplr2 = GPLR2;
272         gpio_saved_reg.gplr3 = GPLR3;
273 
274         gpio_saved_reg.grer0 = GRER0;
275         gpio_saved_reg.grer1 = GRER1;
276         gpio_saved_reg.grer2 = GRER2;
277         gpio_saved_reg.grer3 = GRER3;
278 
279         gpio_saved_reg.gfer0 = GFER0;
280         gpio_saved_reg.gfer1 = GFER1;
281         gpio_saved_reg.gfer2 = GFER2;
282         gpio_saved_reg.gfer3 = GFER3;
283 }
284 
285 void mhn_gpio_restore(void)
286 {
287         GPDR0 = gpio_saved_reg.gpdr0;
288         GPDR1 = gpio_saved_reg.gpdr1;
289         GPDR2 = gpio_saved_reg.gpdr2;
290         GPDR3 = gpio_saved_reg.gpdr3;
291 
292         GPSR0 = gpio_saved_reg.gplr0;
293         GPSR1 = gpio_saved_reg.gplr1;
294         GPSR2 = gpio_saved_reg.gplr2;
295         GPSR3 = gpio_saved_reg.gplr3;
296         GPCR0 = ~(gpio_saved_reg.gplr0);
297         GPCR1 = ~(gpio_saved_reg.gplr1);
298         GPCR2 = ~(gpio_saved_reg.gplr2);
299         GPCR3 = ~(gpio_saved_reg.gplr3);
300 
301         GRER0 = gpio_saved_reg.grer0;
302         GRER1 = gpio_saved_reg.grer1;
303         GRER2 = gpio_saved_reg.grer2;
304         GRER3 = gpio_saved_reg.grer3;
305 
306         GFER0 = gpio_saved_reg.gfer0;
307         GFER1 = gpio_saved_reg.gfer1;
308         GFER2 = gpio_saved_reg.gfer2;
309         GFER3 = gpio_saved_reg.gfer3;
310 }

 

这两个函数用于保存或恢复GPIO的设置,主要是在电源管理中,用于suspendresume

 

PXA3xxx中,GPIO实际上已经是一个逻辑上的概念,它不但可以作为通用的IO,可以作为专用的IO Pin,这可以通过程序设置,在Multi-Function Pin中,我们将继续研究。

 

~~end~~


marginwidth="0" marginheight="0" frameborder="0" scrolling="no" width="728" height="90" src="http://www.360doc.com/ad/aboveConentAD.htm?t=2014012201">
gpio.c源代码分析
收藏人:guitarhua
2012-01-09 | 阅:218  转:1  
 |    来源
  |  分享 
  
 

Marvell-linux研究—gpio.c源代码分析

 

转载时请注明出处和作者联系方式:http://blog.csdn.net/absurd

作者联系方式:李先静 <xianjimli at hotmail dot com>

更新时间:2007-7-4

 

GPIO General Programmable Input Output Pin的首字母缩写,G(General)表示通用,就是可以用于多种用途,P(Programmable)表示可编程,就是可以用程序去控制它,I(Input)表示输入,就是可以用于从外设读取数据,而O(Output)表示输出,也就是可以用于向外设输出数据。总之,它是CPU与外设进行交互的一种方式。

 

正如其名字所示的,它可以用于多种用途,至于具体做什么,要根据实际情况进行配置。最简单的用途可能是用它来连接一个LED,用程序来控制LED点亮或者关闭,这种用法在实验板上很常见。

 

GPIO编程简单而又功能强大,所以我们选择它作为研究的入口。今天我们分析一下arch/arm/mach-pxa/gpio.c的源代码,该文件提供了对GPIO编程提供了最基本的抽象:

56 int mhn_gpio_set_direction(int gpio_id, int dir)
 57 {
 58         unsigned long flags;
 59         int gpio = MFP2GPIO(gpio_id);
 60 
 61         GPIO_ID_VERIFY(gpio);
 62 
 63         spin_lock_irqsave(&gpio_spin_lock, flags);
 64 #if defined(CONFIG_MONAHANS_GPIOEX)
 65         if (gpio >= GPIO_EXP_START) {
 66                 spin_unlock_irqrestore(&gpio_spin_lock, flags);
 67                 return gpio_exp_set_direction(gpio, dir);
 68         }
 69 #endif
 70         if (dir == GPIO_DIR_IN)
 71                 G CDR(gpio) = 1u << (gpio & 0x1f);
 72         else
 73                 GSDR(gpio) = 1u << (gpio & 0x1f);
 74 
 75         spin_unlock_irqrestore(&gpio_spin_lock, flags);
 76 
 77         return 0;
 78 }

 

该函数用于设置某个GPIO数据的流动方向,所谓方向就是指input还是output,如果dir等于GPIO_DIR_IN则为input,否则为output。只能二选一,不同时即作为input又作为output。

 

MFP2GPIO(gpio_id)只是确保gpio_id的高16位为0,而GPIO_ID_VERIFY(gpio)确保gpio_id没有超出范围。

 

64-69行:如果支持GPIOEX,而且gpio >= GPIO_EXP_START,则调用另外一个函数gpio_exp_set_direction去设置。后面的函数若有类似的处理,我们就不多说了。

 

注意:

PXA系列芯片有128个GPIO,对于一般的设置,每个GPIO都占用寄存器的一位,所以每类寄存器都需要4个(共128位)。G CDR(gpio)之类宏就是为了把gpio映射到对应的寄存器上,而1u << (gpio & 0x1f)之类的代码就是为了设置对应的位。

 

PXA 系列芯片对于一般的GPIO设置,都有三个寄存器,一个用于读取设置,一个用于把设置置为1,一个用于把设置清为零。这样做的目的可能是为了提高效率,在 设置时不必把寄存器的值先读出来,设置适当的位,然后写回去。按这种方式设计,在设置时,不会影响其它GPIO的值,所以不必读取原来的值。

 

 80 int mhn_gpio_get_direction(int gpio_id)
 81 {
 82         int gpio = MFP2GPIO(gpio_id);
 83 
 84         GPIO_ID_VERIFY(gpio);
 85 #if defined(CONFIG_MONAHANS_GPIOEX)
 86         if (gpio >= GPIO_EXP_START)
 87                 return gpio_exp_get_direction(gpio);
 88 #endif
 89 
 90         if (GPDR(gpio) & (1u << (gpio & 0x1f)))
 91                 return GPIO_DIR_OUT;
 92         else
 93                 return GPIO_DIR_IN;
 94 }

该函数获取某个GPIO数据的流动方向,正如前面所说,获取方向时用的另外一个寄存器--GPDR

 

 96 int mhn_gpio_set_level(int gpio_id, int level)
 97 {
 98         unsigned long flags;
 99         int gpio = MFP2GPIO(gpio_id);
100 
101         GPIO_ID_VERIFY(gpio);
102 
103         spin_lock_irqsave(&gpio_spin_lock, flags);
104 #if defined(CONFIG_MONAHANS_GPIOEX)
105         if (gpio >= GPIO_EXP_START) {
106                 spin_unlock_irqrestore(&gpio_spin_lock, flags);
107                 return gpio_exp_set_level(gpio, level);
108         }
109 #endif
110 
111         if (level == GPIO_LEVEL_LOW)
112                 GPCR(gpio) = 1u << (gpio & 0x1f);
113         else
114                 GPSR(gpio) = 1u << (gpio & 0x1f);
115 
116         spin_unlock_irqrestore(&gpio_spin_lock, flags);
117 
118         return 0;
119 }

 

该函数用于设置输出的数据,可以设置输出高电平或者低电平,它与设置数据流动方向的函数类似,只是操作GPCRGPSR两个寄存器,这里不再多说。让人费解是,不就是输出的数据嘛,为什么要叫level而不叫data呢。我想可能与《PXA300 and PXA310 Developers Manual 1》的4.11.3.2中所说的Second Level Generic Wakeups有关呢。

 

121 int mhn_gpio_get_level(int gpio_id)
122 {
123         int gpio = MFP2GPIO(gpio_id);
124 
125         GPIO_ID_VERIFY(gpio);
126 #if defined(CONFIG_MONAHANS_GPIOEX)
127         if (gpio >= GPIO_EXP_START)
128                 return gpio_exp_get_level(gpio);
129 #endif
130 
131         if (GPLR(gpio) & (1u << (gpio & 0x1f)))
132                 return GPIO_LEVEL_HIGH;
133         else
134                 return GPIO_LEVEL_LOW;
135 }

 

该函数用于获取输入数据,其与获取数据流动方向类似,只是操作GPLR寄存器。

 

140 int mhn_gpio_set_rising_edge_detect(int gpio_id, int enable)
141 {
142         unsigned long flags;
143         int gpio = MFP2GPIO(gpio_id);
144 
145         GPIO_ID_VERIFY(gpio);
146 #if defined(CONFIG_MONAHANS_GPIOEX)
147         if (gpio >= GPIO_EXP_START)
148                 return 0;
149 #endif
150 
151         spin_lock_irqsave(&gpio_spin_lock, flags);
152 
153         if (enable == 0)
154                 GCRER(gpio) = 1u << (gpio & 0x1f);
155         else
156                 GSRER(gpio) = 1u << (gpio & 0x1f);
157 
158         spin_unlock_irqrestore(&gpio_spin_lock, flags);
159 
160         return 0;
161 }

 

该函数用于设置是否启用上升沿触发中断,它与设置数据流动方向的函数类似,只是操作GCRERGSRER两个寄存器。如果启用,则输入数据从低电平进入高电平时触发中断。

 

163 int mhn_gpio_get_rising_edge_detect(int gpio_id)
164 {
165         int gpio = MFP2GPIO(gpio_id);
166 
167         GPIO_ID_VERIFY(gpio);
168 #if defined(CONFIG_MONAHANS_GPIOEX)
169         if (gpio >= GPIO_EXP_START)
170                 return 0;
171 #endif
172 
173         if (GRER(gpio) & (1u << (gpio & 0x1f)))
174                 return 1;
175 
176         return 0;
177 }

 

该函数用于判断是否启用了上升沿触发中断。

 

179 int mhn_gpio_set_falling_edge_detect(int gpio_id, int enable)
180 {
181         unsigned long flags;
182         int gpio = MFP2GPIO(gpio_id);
183 
184         GPIO_ID_VERIFY(gpio);
185 
186 #if defined(CONFIG_MONAHANS_GPIOEX)
187         if (gpio >= GPIO_EXP_START)
188                 return 0;
189 #endif
190 
191         spin_lock_irqsave(&gpio_spin_lock, flags);
192 
193         if (enable == 0)
194                 GCRER(gpio) = 1u << (gpio & 0x1f);
195         else
196                 GSRER(gpio) = 1u << (gpio & 0x1f);
197 
198         spin_unlock_irqrestore(&gpio_spin_lock, flags);
199 
200         return 0;
201 }

 

该函数用于设置是否启用下降沿触发中断,它与设置数据流动方向的函数类似,只是操作GCFERGSFER两个寄存器。如果启用,则输入数据从高电平进入低电平时触发中断。由于该函数与mhn_gpio_set_rising_edge_detect极为类似,作者copy-paste时忘了修改寄器,所以代码中的寄存器是错的。

 

203 int mhn_gpio_get_falling_edge_detect(int gpio_id)
204 {
205         int gpio = MFP2GPIO(gpio_id);
206 
207         GPIO_ID_VERIFY(gpio);
208 
209 #if defined(CONFIG_MONAHANS_GPIOEX)
210         if (gpio >= GPIO_EXP_START)
211                 return 0;
212 #endif
213 
214         if (GFER(gpio) & (1u << (gpio & 0x1f)))
215                 return 1;
216 
217         return 0;
218 }

 

该函数用于判断是否启用了下降沿触发中断。

 

220 int mhn_gpio_get_edge_detect_status(int gpio_id)
221 {
222         int gpio = MFP2GPIO(gpio_id);
223 
224         GPIO_ID_VERIFY(gpio);
225 
226 #if defined(CONFIG_MONAHANS_GPIOEX)
227         if (gpio >= GPIO_EXP_START)
228                 return 0;
229 #endif
230 
231         if (GEDR(gpio) & (1u << (gpio & 0x1f)))
232                 return 1;
233 
234         return 0;
235 }

 

该函数用于检测是否发生了电平变化,即是否有上升沿触发中断,或者下降沿触发中断发生。

 

237 int mhn_gpio_clear_edge_detect_status(int gpio_id)
238 {
239         unsigned long flags;
240         int gpio = MFP2GPIO(gpio_id);
241 
242         GPIO_ID_VERIFY(gpio);
243 
244 #if defined(CONFIG_MONAHANS_GPIOEX)
245         if (gpio >= GPIO_EXP_START)
246                 return 0;
247 #endif
248 
249         spin_lock_irqsave(&gpio_spin_lock, flags);
250 
251         GEDR(gpio) = 1u << (gpio & 0x1f);
252 
253         spin_unlock_irqrestore(&gpio_spin_lock, flags);
254 
255         return 0;
256 }

 

清除发生电平变化的标志,如果发生电平变化,GEDR会自动设置,但不会自动清除,而需要程序主动清除。这里获取和清除是同一个寄存器,原因是不需要程序去设置,所以不需要独立的寄存器。

 

262 void mhn_gpio_save(void)
263 {
264         gpio_saved_reg.gpdr0 = GPDR0;
265         gpio_saved_reg.gpdr1 = GPDR1;
266         gpio_saved_reg.gpdr2 = GPDR2;
267         gpio_saved_reg.gpdr3 = GPDR3;
268 
269         gpio_saved_reg.gplr0 = GPLR0;
270         gpio_saved_reg.gplr1 = GPLR1;
271         gpio_saved_reg.gplr2 = GPLR2;
272         gpio_saved_reg.gplr3 = GPLR3;
273 
274         gpio_saved_reg.grer0 = GRER0;
275         gpio_saved_reg.grer1 = GRER1;
276         gpio_saved_reg.grer2 = GRER2;
277         gpio_saved_reg.grer3 = GRER3;
278 
279         gpio_saved_reg.gfer0 = GFER0;
280         gpio_saved_reg.gfer1 = GFER1;
281         gpio_saved_reg.gfer2 = GFER2;
282         gpio_saved_reg.gfer3 = GFER3;
283 }
284 
285 void mhn_gpio_restore(void)
286 {
287         GPDR0 = gpio_saved_reg.gpdr0;
288         GPDR1 = gpio_saved_reg.gpdr1;
289         GPDR2 = gpio_saved_reg.gpdr2;
290         GPDR3 = gpio_saved_reg.gpdr3;
291 
292         GPSR0 = gpio_saved_reg.gplr0;
293         GPSR1 = gpio_saved_reg.gplr1;
294         GPSR2 = gpio_saved_reg.gplr2;
295         GPSR3 = gpio_saved_reg.gplr3;
296         GPCR0 = ~(gpio_saved_reg.gplr0);
297         GPCR1 = ~(gpio_saved_reg.gplr1);
298         GPCR2 = ~(gpio_saved_reg.gplr2);
299         GPCR3 = ~(gpio_saved_reg.gplr3);
300 
301         GRER0 = gpio_saved_reg.grer0;
302         GRER1 = gpio_saved_reg.grer1;
303         GRER2 = gpio_saved_reg.grer2;
304         GRER3 = gpio_saved_reg.grer3;
305 
306         GFER0 = gpio_saved_reg.gfer0;
307         GFER1 = gpio_saved_reg.gfer1;
308         GFER2 = gpio_saved_reg.gfer2;
309         GFER3 = gpio_saved_reg.gfer3;
310 }

 

这两个函数用于保存或恢复GPIO的设置,主要是在电源管理中,用于suspendresume

 

PXA3xxx中,GPIO实际上已经是一个逻辑上的概念,它不但可以作为通用的IO,可以作为专用的IO Pin,这可以通过程序设置,在Multi-Function Pin中,我们将继续研究。

 

~~end~~


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值