Linux gpio application instance

Source: Internet
Author: User

Requirement Description:
The status light on the Main Board should correctly display the connection status of The ONU module. That is, when the light node module is inserted into the main board slot, the status light should be on and removed.

 

Hardware interface:
When SFP module is plugged in, the gpio [2] status will change from high to low automatically.
When SW detect the change, just make the gpio [18] to generate low signal (default is high), The ONU led will be lighted.

 

The preceding information is used to receive tasks. So I began to look for information to solve the problem.

What is the background information of gpio?
That is, general input and output. Industrial Standard for controlling the CPU pins directly connected to peripherals without passing through the bus or controller, such as connecting a pin to the LED, by setting a bit 0/1, the LED can be switched off.

 

What is the hardware structure? Look for schematics:
1. The right side is the CPU, and the left side is the pin link. ">" and "<" indicate the direction of input.

 

2. corresponding to the first figure, the light is on the left, and the gpio interface of the connected CPU is on the right.

 

3. corresponding to the first figure, CPU on the left

 

Software solutions?
There are two implementation methods, one is to round the potential of gpio [2], and the other is to interrupt the potential changes of gpio [2.
Find an example of another user using gpio on the current motherboard. The function of this example is: press the hardware restart button and send it to the gpio pins of the CPU to restart the motherboard.
In this example, the interrupt is implemented, and the preparation is also implemented in the interrupt mode.

 

So how can we interrupt the potential changes of gpio [2?

On the Current Device, check to list the interrupt numbers that have been occupied:
Root:/proc # Cat interrupts
Cpu0 cpu1 cpu2 cpu3 cpu4 cpu5 cpu6
0: 526 83 11 4 1423 164 MIPS smtc_ipi
2: 0 0 0 0 40 MIPS pmcmsp_tsmac
3: 0 0 3 0 00 MIPS pmcmsp_tsmac
4: 0 0 0 0 00 MIPS ehci_hcd: usb1, ehci_hcd: usb2
5: 0 0 0 13 00 MIPS pmcmsp_tsmac
6: 0 0 0 0 00 mips cic Cascade
8: 0 0 0 0 00 msp_cic softreset button
21: 0 0 0 0 00 msp_cic per Cascade
25: 5853436 1664 28 4 0 00 msp_cic Timer
27: 3575 0 0 0 00 msp_cic serial
34: 0 0 0 5851128 138 30 msp_cic vpe1 local Timer
46: 1 0 0 0 00 msp_per pmcmsptwi

 

Err: 1

 

How is the hardware of the existing button connected?

 

How is the interruption of existing buttons implemented?

We can see that the gpio21 pin is connected to both the button and irq0 (interrupt request 0 ). View code

Subsys_initcall (msp_hwbutton_setup); // register the subsystem

 

 <Br/> static int _ init msp_hwbutton_setup (void) <br/>{< br/> msp_hwbutton_register (& softreset_sw); <br/>... <br/>}</P> <p> static struct hwbutton_interrupt softreset_sw ={< br/>. name = "softreset button", <br/>. IRQ = msp_int_ext0, <br/>. eirq = 0, <br/>. initial_state = hwbutton_hi, <br/>. handle_hi = softreset_release, // function called when the button is released <br/>. handle_lo = softreset_push, // The function called when the button is pressed <br/>. data = NULL, <br/> }; </P> <p>/* <br/> * This struct describes a hardware button <br/> */<br/> struct hwbutton_interrupt {<br/> char * Name; /* Name of Button */<br/> int IRQ;/* Actual Linux IRQ * // system interruption corresponding to the following external interruption, defined in the Lib of the motherboard System <br/> int eirq;/* extended IRQ Number (0-7) * /// gpio2 is split to irq0 <br/> int initial_state; /* the "normal" state of the switch * // This is learned from the hardware engineer <br/> void (* handle_hi) (void *);/* Handler: switch Input has gone hi * // handler learn from function requirements <br/> void (* handle_lo) (void *);/* Handler: switch Input has gone lo * // handler learn from function requirements <br/> void * data; /* optional data to pass to handler * // parameters passed to handler <br/>}; <br/>

 

</P> <p> # define msp_msb_base (0x18000000)/* msbus address start */<br/> # define msp_cpuif_base (msp_msb_base + 0xc00000) /* CPU interface REGISTERS */<br/>/* Central Interrupt Controller REGISTERS */<br/> # define msp_cic_base (msp_cpuif_base + 0x8000) /* Central interrupt REGISTERS */<br/> # define cic_ext_1__reg regptr (msp_cic_base + 0x00)/* External Interrupt configuration */<br/> # define ext_in T_edge (eirq) (1 <eirq) <br/> # define cic_ext_set_trigger_level (Reg, eirq) reg & = ~ Ext_int_edge (eirq) </P> <p> static int msp_hwbutton_register (struct hwbutton_interrupt * hirq) <br/>{< br/> unsigned long cic_ext; </P> <p> If (hirq-> handle_hi = NULL | hirq-> handle_lo = NULL) <br/> return-einval; </P> <p> cic_ext = * cic_ext_1__reg; <br/> decrypt (cic_ext, hirq-> eirq); <br/> If (hirq-> initial_state = hwbutton_hi) <br/> cic_ext_set_active_lo (cic_ext, hirq-> eirq); <br/> else <br/> cic_ext_set_active_hi (cic_ext, hirq-> eirq ); <br/> * cic_ext_assist_reg = cic_ext; </P> <p> return request_irq (hirq-> IRQ, hwbutton_handler, sa_interrupt, <br/> hirq-> name, (void *) hirq); <br/> // return request_irq (msp_int_ext0, hwbutton_handler, sa_interrupt, "softrest button ", & <br/>}</P> <p>

 

<Br/> static irqreturn_t hwbutton_handler (int irq, void * Data) <br/>{< br/> struct hwbutton_interrupt * hirq = (struct hwbutton_interrupt *) data; <br/> unsigned long cic_ext = * cic_ext_1__reg; </P> <p> If (IRQ! = Hirq-> IRQ) <br/> return irq_none; </P> <p> If (cic_ext_is_active_hi (cic_ext, hirq-> eirq )) {<br/>/* interrupt: PIN is now Hi */<br/> cic_ext_set_active_lo (cic_ext, hirq-> eirq ); <br/> hirq-> handle_hi (hirq-> data); <br/>}else {<br/>/* interrupt: pin is now lo */<br/> cic_ext_set_active_hi (cic_ext, hirq-> eirq); <br/> hirq-> handle_lo (hirq-> data ); <br/>}</P> <p>/* <br/> * invert the polarity of this level interrupt to ack the interrupt <br/> * Thus next state change will invoke the opposite message <br/> */<br/> * cic_ext_1__reg = cic_ext; </P> <p> return irq_handled; <br/>}< br/>

 

Now question?
In this CPU, the GPIO0-15 can be configured to generate an internal interrupt, gpio16 and above cannot be generated through the configuration; the above example uses gpio21, can not generate an interrupt through the configuration, so it is necessary to receive irq0
The gpio foot of the LED lamp to be implemented is not like an example of a button, it is not connected to an external interrupt, But it is required to determine the potential of the LED gpio2, within the scope of the GPIO0-15, it can be interrupted by configuring the CPU.
However, the CPU vendor does not provide the documentation on how to configure the service, and the cpu sdk does not support the configuration of gpio interruptions.
Summary: The hardware and software available cannot interrupt gpio2.
So we can only go round-robin. The Code is as follows:

 Static unsigned long records = 0; <br/> static struct timer_list records; <br/> static msp_gpio_data_t records; </P> <p> static void e220_sfp_led_update (unsigned long data) <br/>{< br/> msp_gpio_data_t e220_sfp_current_status; </P> <p> If (msp_gpio_pin_mode (msp_gpio_input, 2 )! = 0) {<br/> printk (kern_info "gpio [2] input mode failed/N "); <br/>}</P> <p> If (msp_gpio_pin_mode (msp_gpio_output, 18 )! = 0) {<br/> printk (kern_info "gpio [18] Output Mode failed/N "); <br/>}</P> <p> e220_sfp_current_status = msp_gpio_pin_get (2); </P> <p> If (e220_sfp_current_status! = E220_sfp_old_status) {</P> <p> If (e220_sfp_current_status = msp_gpio_lo) {<br/> printk (kern_info "SFP module inserted/N "); <br/> msp_gpio_pin_lo (18); <br/>} else if (e220_sfp_current_status = msp_gpio_hi) {<br/> printk (kern_info "SFP module removed/N "); <br/> msp_gpio_pin_hi (18); <br/>}else {<br/> printk (kern_info "SFP module state unknown/N "); <br/>}</P> <p> e220_sfp_old_status = e220_sfp_current_status; <br/>}</P> <p> mod_timer (& e220_sfp_led_update_timer, jiffies + msecs_to_jiffies (1000); <br/>}</P> <p> static int forward (void) <br/>{< br/> e220_sfp_old_status = msp_gpio_none; <br/> setup_timer (& e220_sfp_led_update_timer, e220_sfp_led_update, null); </P> <p> // expire timer immediately <br/> return mod_timer (& signature, jiffies + 1); <br/>}</P> <p>

 

OK.

 

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.