Operating gpio ports at the Linux Application Layer

Source: Internet
Author: User

Perform gpio operations in Linux:

For operating systems that do not support virtual memory and do not use the operating system to operate gpio to directly read and write the corresponding gpio register, but in operating systems such as Linux, both the kernel layer and the application layer are in virtual addresses, while the gpio registers are in physical addresses. You must write a gpio driver or use some flexible techniques to operate gpio.

Currently, I know two methods to operate gpio in Linux:

1. write a driver. Of course, you must be familiar with the compiling methods and skills of the driver in Linux. The driver contains virtual addresses. You can use the ioremap function to obtain the gpio physical base address pointer, then, use the ioctl command to read and write the gpio register and send the result back to the application layer. Here are some program snippets for your reference:

Int init_module (void ){

Printk (kern_alert "IOCTL load. \ r \ n ");

Register_chrdev (254, "ioreg", & FOPS );

Stb_gpio = (stbx25xx_gpio_reg *) ioremap (gpio_base, gpio_len );

If (stb_gpio = NULL ){

Printk (kern_alert "can't get Io base. \ r \ n ");

Return-1;

}

Return 0;

}

Int io_ioctl (struct inode * inode, struct file * filp, unsigned int cmd, unsigned long Arg ){

Unsigned long ugpio;

Printk (kern_alert "io_ioctl cmd = % 04x, Arg = % 04x. \ r \ n", CMD, (INT) Arg );

Switch (CMD ){

Case set_io_dir :{

Printk (kern_alert "set_io_dir \ r \ n ");

Break;

}

Case set_io_value :{

Printk (kern_alert "set_io_value \ r \ n ");

Break;

}

Case get_io_value :{

Printk (kern_alert "get_io_value \ r \ n ");

Ugpio = stb_gpio-> GPI;

Printk (kern_alert "gpio = % 08x", (INT) ugpio );

Copy_to_user (void *) Arg, (const void *) & ugpio, sizeof (ugpio ));

Break;

}

Case get_io_dir :{

Printk (kern_alert "get_io_dir \ r \ n ");

Break;

}

}

Return 0;

}

2. use the MMAP function at the application layer to obtain the virtual address pointer corresponding to the gpio physical base address (in the application layer) at the application layer, allowing the user program to directly access the device memory, and then use this pointer to read and write gpio registers, here are some program snippets for your reference:

/Dev/MEMIt is a full image of the physical memory and can be used to access the physical memory. The general usage isOpen ("/dev/mem", o_rdwr | o_sync)Then, MMAP can use the MMAP address to access the physical memory. This is actually a method to implement the user space drive.

/Dev/kmem: The full image of the virtual memory seen by the kernel, which can be used to access the contents of the kernel.

 

1g virtual address for kernel space and 3G virtual address for user space
Therefore, ioremap certainly cannot separate 1g addresses for your use (the size of ioreamp space is limited)
A physical address. The kernel calls ioremap to obtain a virtual address within 1 GB to operate the physical memory.
The Application Layer calls MMAP to obtain a virtual address within 3G, which is used to operate the physical memory.

Char dev_name [] = "/dev/mem ";

Gpio_register * gpio_base;

FD = open (dev_name, o_rdwr );

If (FD <0 ){

Printf ("Open % s is error \ n", dev_name );

Return-1;

}

Gpio_base = (gpio_register *) MMAP (0, 0x32, prot_read | prot_write, map_shared, FD, 0x40060000 );

If (gpio_base = NULL ){

Printf ("gpio base MMAP is error \ n ");

Close (FD );

Return-1;

}

Gpio_base-> OR = (gpio_base-> or & 0x7fffff );

Complete program:

# Include <stdio. h>
# Include <stdlib. h>
# Include <unistd. h>
# Include <fcntl. h>
# Include <sys/types. h>
# Include <sys/STAT. h>
# Include <sys/Mman. h>
# Include <string. h>
# Include <time. h>

# Define time_out 5/* the timeout time, in seconds */
/**
* Define behaviour's when the button is pressed enough time.
*/
Void longtu_timeout (){
Printf ("***** pressed 5 seconds, call recovery! * *** \ N ");
// System ("/sbin/recover_longtu.sh ");
// System ("/sbin/reboot ");
}

/*
* The main function.
*/
Int main (INT argc, char * argv [])
{
Int MFD;
Unsigned int val = 0, last_val;
Void * base;
Char * sys_pinstaterd;
Time_t t_now, t_old;
Int flag_issued = 0;
# If 0
// Uncomment these to make the program a daemon.

Pid_t PID;
Int I;
If (pid = fork () <0)
Return-1;
Else if (PID! = 0)
Exit (0 );
Setsid ();
Chdir ("/");
Umask (0 );
For (I = 0; I <256; I ++)
Close (I );
# Endif

// Open the memery mapped file.
MFD = open ("/dev/mem", o_rdwr );
If (MFD <0 ){
Printf ("cannot open/dev/MEM. \ n ");
Exit (-1 );
}

// Initialize the map
Base = MMAP (null, 0x130, prot_read | prot_write, map_shared, MFD, 0x1fe00000 );
If (base <0 ){
Exit (-1 );
}

// Got the pointer to sys_pinstaterd register of gs32i CPU.
Sys_pinstaterd = base + 0x011c;

// Init the temperay Variables
T_now = t_old = Time (null );
Last_val = 0;
While (1)
{
// Get status of gpio7 pin.
Val = * (volatile unsigned int *) sys_pinstaterd );
Val = (Val & 0x4 )? 1:0;
Printf ("\ tgpio 7 stat = % x. \ n", Val );
If (VAL ){
// The button is pressed down !!
If (last_val = 0 ){
// Starting time of press, log the time
T_old = Time (null );
Last_val = 1;
Printf ("button down \ n ");
} Else {
// Already pressed down! Let's count the time!
T_now = Time (null );
If (t_now-t_old> = time_out & flag_issued = 0 ){
// Pressed long enough, issue the handler script !!
Flag_issued = 1;
Longtu_timeout ();
}
}
} Else {
// No button pressed.
If (flag_issued ){
Flag_issued = 0;
Printf ("button up. \ n ");
}
}

Last_val = val;
Usleep (100 );
}

Munmap (base, 0x000 );
Close (MFD );
Return 0;
}

 

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.