im6q中的: pad csi
pad 管脚
pad control: 管脚控制
csi:CMOS serial interface, 即和CMOS摄像头的通信接口。
imx 芯片的非常好的在线资料:
https://www.digi.com/resources/documentation/digidocs/90002287/reference/bsp/cont_devices_interfaces_cc6.htm?tocpath=Digi%20Embedded%20Yocto%7CSystem%20development%7CLinux%20kernel%7CLinux%20%20v4.9%20Board%20Support%20Package%7CDevices%20and%20interfaces%7C_____0
https://www.digi.com/resources/documentation/digidocs/90001546/reference/bsp/cc6/r_general_purpose_input_output.htm
https://www.digi.com/resources/documentation/digidocs/90001546/Default.htm#reference/bsp/v3-14_cc6/r_general_purpose_input_output_v3-14.htm%3FTocPath%3DAdditional%2520resources%7CLinux%2520v3.14%2520Board%2520Support%2520Package%7C_____10
一、RS232标准中的RTS与CTS
RTS,CTS------请求发送/清除发送,用于半双工时的收发切换,属于辅助流控信号。半双工的意思是说,发的时候不收,收的时候不发。那么怎么区分收发呢?缺省时是DCE向DTE发送数据,当DTE决定向DCE发数据时,先有效RTS,表示DTE希望向DCE发送。一般DCE不能马上转换收发状态,DTE就通过监测CTS是否有效来判断可否发送,这样避免了DTE在DCE未准备好时发送所导致的数据丢失。
二、MODEM硬件流控中的RTS与CTS
按照SIMCOM公司的解释,RTS和CTS是独立,
1.RTS是模块的输入端,用于MCU通知模块,MCU是否准备好,模块是否可向MCU发送信息,RTS的有效电平为低。
2.CTS是模块的输出端,用于模块通知MCU,模块是否准备好,MCU是否可向模块发送信息,CTS的有效电平为低
从文字看,RTS和CTS是独立的,不存在每次单向数据传输的发起者问题。如果主机输出RTS有效,那么模块有数据就会发往主机;如果模块输出CTS有效,那么主机就可以将数据送达模块接收。
三、通信协议中的RTS与CTS
RTS/CTS协议即请求发送/允许发送协议,相当于一种握手协议,主要用来解决"隐藏终端"问题。"隐藏终端"(Hidden Stations)是指,基站A向基站B发送信息,基站C未侦测到A也向B发送,故A和C同时将信号发送至B,引起信号冲突,最终导致发送至B的信号都丢失了。"隐藏终端"多发生在大型单元中(一般在室外环境),这将带来效率损失,并且需要错误恢复机制。当需要传送大容量文件时,尤其需要杜绝"隐藏终端"现象的发生。IEEE802.11提供了如下解决方案。在参数配置中,若使用RTS/CTS协议,同时设置传送上限字节数----一旦待传送的数据大于此上限值时,即启动RTS/CTS握手协议:首先,A向B发送RTS信号,表明A要向B发送若干数据,B收到RTS后,向所有基站发出CTS信号,表明已准备就绪,A可以发送,其余基站暂时"按兵不动",然后,A向B发送数据,最后,B接收完数据后,即向所有基站广播ACK确认帧,这样,所有基站又重新可以平等侦听、竞争信道了。
附:UART串口历史
很久很久以前,计算机还没有出现,那时就已经存在了(计算机)史前的串口设备(电传打字机,工控测量设备,通信调制解调器),为了连接这些串口,EIA制定了RS232标准,采用DB25接插件,支持同步和异步串口,D型的接口可以有效防止插反。标准化给使用带来了便利。
时光荏苒,个人计算机出现了,这些已有的串口设备毫无疑问地成为了最初的外设,自然而然地RS232标准被个人计算机采纳。但是设备制造商倾向于体积更小,成本更低的接口,因此,将DB25中未使用的和支持同步模式的引脚去掉,形成DB9。最初的情况相当混乱,因为DB9只定义了信号,却没有指定信号和引脚的对应关系,各个制造商只能自行定义。幸运的是,IBM的PC成了工业标准,DB9逐渐统一到IBM的定义上来。
DB9只有9根线,遵循RS232标准。定义如下:
DTR,DSR------DTE设备准备好/DCE设备准备好。主流控信号。
RTS,CTS------请求发送/清除发送。用于半双工时,收发切换。属于辅助流控信号。半双工的意思是说,发的时候不收,收的时候不发。那么怎么区分收发呢?缺省时是DCE向DTE发送数据,当DTE决定向DCE发数据时,先有效RTS,表示DTE希望向DCE发送,一般DCE不能马上转换收发状态,DTE就通过监测CTS是否有效来判断可否发送,这样避免了DTE在DCE未准备好时发送所导致的数据丢失。全双工时,这两个信号一直有效即可。
随着计算机的日益普及,很多非RS232的串口也要接入PC机,如果为每一种新出现的串口都增加一个新的I/O口显然不现实,因为PC后面板位置有限,因此,将RS232串口和非RS232串口都通过RS232口接入是最佳方案。UART的U(通用)指的就是这个意思。早期ROM BIOS和DOS里的通信软件都是为RS232设计的,在没有检测到DCD有效前不会发送数据,因此,就连发送一个字符这样朴素的应用也要给出DCD、DTR、DSR等控制信号。因此,串口接头上要将一些控制线短接,或者干脆绕过系统软件自己写通信程序。
到此,UART的涵义就总结为:通用的 异步 (串行) I/O口。
就在UART冠以通用二字,准备一统江湖的时候,制造商们不满于它的速度、体积和灵活性(软件可配置),推出了USB和1394串口。目前,笔记本上的UART串口有被取消的趋势,因而有网友发出了“没有串口,吾谁与归”的慨叹,古今多少事,都付笑谈中,USB取代UART是后话,暂且不表。
话说自从贺氏(Hayes)公司推出了聪明猫(SmartModem),他们制定的MODEM接口就成了业界标准,自此以后,所有公司制造的兼容猫都符合贺氏标准(连AT指令也兼容)。
细观贺氏制定的MODEM串口,与RS232标准大不相同。DTR在整个通信过程中一直保持有效,DSR在MODEM上电后/可以拨号前有效(取决于软件对DSR的理解),在通信过程的任意时刻,只要DTR/DSR无效,通信过程立即终止。在某种意义上,这也可以算是流控,但肯定不是RS232所指的那种主流控。如果拘泥于RS232,你是不会理解DTR和DSR的用途的。
贺氏不但改了DTR和DSR,竟然连RTS和CTS的涵义也重新定义了。因此,RTS和CTS已经不具有最开始的意义了。从字面理解RTS和CTS,是用于半双工通信的,当DTE想从收模式改为发模式时,就有效RTS请求发送,DCE收到RTS请求后不能立即完成转换,需要一段时间,然后有效CTS通知DTE:DCE已经转到发模式,DTE可以开始发送了。在全双工时,RTS和CTS都缺省置为有效即可。然而,在贺氏的MODEM串口定义中,RTS和CTS用于硬件流控,和什么全双工/半双工一点关系也没有。 注意,硬件流控是靠软件实现的,之所以强调“硬件”二字,仅仅是因为硬件流控提供了用于流量情况指示的硬件连线,并不是说,你只要把线连上,硬件就能自己流控。如果软件不支持,光连上RTS和CTS是没有用的。
RTS和CTS硬件流控的软件算法如下:(RTS有效表示PC机可以收,CTS有效表示MODEM可以收,这两个信号互相独立,分别指示一个方向的流量情况。)
PC端处理:
发. 当发现(不一定及时发现) CTS (-3v to -15v)无效时,停止发送,
当发现(不一定及时发现) CTS (3v to 15v)有效时,恢复发送;
收. 当接收buffers中的bytes当接收buffers中的bytes>N 时,给 RTS 无效信号(-3v to -15v);
MODEM端处理:
同上,但RTS与CTS交换。
在RS232中本来CTS 与RTS 有明确的意义,但自从贺氏(HAYES) 推出了聪明猫(SmartModem)后就有点混淆了。在RS232中RTS 与CTS 是用来半双工模式下的方向切换;HAYES Modem中的RTS ,CTS 是用来进 行硬件流控的。通常UART的RTC、CTS 的含义指后者,即用来做硬流控的。
硬流控的RTS 、CTS :RTS (Require To Send,发送请求)为输出信号,用于指示本设备准备好可接收;CTS(Clear To Send,发送清除)为输入信号,有效时停止发送。假定A、B两设备通信,A设备的RTS 连接B设备的CTS ;A设备的CTS 连接B设备 的RTS 。 前一路信号控制B设备的发送,后一路信号控制A设备的发送。对B设备的发送(A设备接收)来说,如果A设备接收缓冲快满的时发出RTS 信号(意思 通知B设备停止发送),B设备通过CTS 检测到该信号,停止发送;一段时间后A设备接收缓冲有了空余,发出RTS 信号,指示B设备开始发送数据。A设备发(B设备接收) 类似。上述功能也能在数据流中插入Xoff(特殊字符)和Xon(另一个特殊字符)信号来实现。A设备一旦接收到B设备发送过来的Xoff,立刻停止发 送;反之,如接收到B设备发送过来的Xon,则恢复发送数据给B设备。同理,B设备也类似,从而实现收发双方的速度匹配。
半双工的方向切换:RS232中使用DTR(Date Terminal Ready,数据终端准备)与DSR(Data Set Ready ,数据设备准备好)进行主流控,类似上述的RTS 与CTS 。对半双工的通信的DTE(Date Terminal Equipment,数据终端设备)与DCE(Data circuit Equipment )来说,默认的方向是DTE接收,DCE发送。如果DTE要发送数据,必须发出RTS 信号,请求发送数据。DCE收到后如果 空闲则发出CTS 回 应RTS 信 号,表示响应请求,这样通信方向就变为DTE->TCE,同时RTS 与CTS 信号必须一直保持。从这里可以看出,CTS ,TRS虽 然也有点流控的意思(如CTS 没有发出,DTE也不能发送数据),但主要是用来进行方向切换的。
如果UART只有RX、TX两个信号,要流控的话只能是软流控;如果有RX,TX,CTS ,RTS 四个信号,则多半是支持硬流控的UART;如果有 RX,TX,CTS ,RTS ,DTR,DSR 六个信号的话,RS232标准的可能性比较大。
顺便提一下:
DCD( Data Carrier Detect, 数据载波检测):DCE向DTE指示,线路上检测到载波。
RI(Ring Indicator,振铃指示):DCE向DTE指示,有呼叫接入。
====================================我是分割线=====================================================================================================
这两天基于STM32的串口做了测试。之前一直用的时候根本没有往串口协议上靠,只是能用起来解决了问题就匆匆完事。直到最近看《深入理解计算机网络》这本网络基础书,里面讲232协议以及485协议时,忽然想拿板子测试下。上面提到的CTS/RTS流控方面的应用是我之前使用串口时没有注意到的。之前在用USART做串口编程时,一般都是设备作为从机来使用,包括一些教程也都是从这样的应用来讲解。大部分的教程都是在将单片机Usart同上位机超级终端之间通过232协议转换模块进行通信。最最常见的用法就是使用串口中断进行流控(当然这种做法是推荐的,因为232的CTS/RTS不是干这个用的,本文只是那上位机的232这么测试一下。。。)
前几天看书看到232的时候,我忽然想到是不是可以用RTS/CTS来代替中断实现上位机的交互。上位机的超级终端或者串口小助手,在接收的数据的时候,可以游刃有余,因为stm32函数库里面,usart的发送数据是通过串口打印冲定义实现的,将fputs()函数进行了修改,最终使用printf函数进行输出。这种方法其实是通过函数fputs()本身进行了缓存操作,使得USART_SendData函数能一位位的将数据发出。也就是说,即是不用发送中断,我们依然能够井然有序的通过stm32的Usart的TX端口将数据发出。如下代码是stm32函数库中串口打印冲定义函数,注意是USART1。
1 #ifdef __GNUC__
2 /* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf
3 set to 'Yes') calls __io_putchar() */
4 #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
5 #else
6 #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
7 #endif /* __GNUC__ */
8
9 PUTCHAR_PROTOTYPE
10 {
11 /* Place your implementation of fputc here */
12 /* e.g. write a character to the USART */
13 USART_SendData(USART1,(u8)ch);
14
15 /* Loop until the end of transmission */
16 while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
17
18 return ch;
19 }
但是,如果我们不使用中断,而从上位机超级终端向stm32发送数据的话,你会发现,单片机只能收到你发的字符串的首个字符。其它的字符全部丢失。这就是没有做流控的结果。比如下面:
1 int main(void)
2 {
3 u32 i=0xffffff;
4 SystemInit();
5 usart_Configuration();
6 //NVIC_Configuration();
7 while(1)
8 {
9 printf("Waveshare!\r\n");
10 while(--i);
11 i=0xffffff;
12 printf("%c",USART_ReceiveData(USART1));
}
13 }
但是如果我们使用中断,或者是使用RTS/RTS做流控则不会发生这种现象。从机理上讲,上面是发生了接收溢出错误。串口状态寄存器的ORE位由于在RENE=1的情况(也就是第一个字符已经被写满数据寄存器DR)下接收到了数据,造成了数据溢出,此时SR.ORE位会置1.这点参考硬件手册,而且读取DR数据寄存器的话,仅会清除RXNE位,而不会清空数据寄存器DR。所以一直会输出S。但是如果我们发送再次发送一个字符,比如ASDF。则会发现输出字符变成了AWaveshare!道理跟之前一样,因为我们已经通过调用USART_ReceiveData()清空了RXNE,所以第一个字符A还是能读进去的,只不过当第二字字符S时又发生了前面的事情。所以,在做通信的时候必须做流控。
使用中断做流控我们就不说了,很多。这里说一下CTS/RTS。其实这个比中断简单,因为中断我们还得配置,而且中断可以写中断服务函数,所以应用广。毕竟CTS/RTS其实是用来做流控或者半双工通信的,具体的含义不一样,这里只讲232的。以RTS为例,其含义如下:
也就是说,Tx管脚接收到1个字符(默认8bit通信),硬件上RTS会产生一个置位,使得接收数据标志位RXNE=1.所以只要在软件里我们判断RXNE的状态,就可以实现流控。CTS道理一个样。故而代码可以如下:
1 int main(void)
2 {
3 SystemInit();
4 USART_CTRT_Configuartion();
5 while(NbrOfDataToTransfer--)
6 {
7 USART_SendData(USART1,TxBuffer[TxCounter++]);
8 while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET); //等待发送结束
9 }
10
11 /*Receive a string (Max RxBufferSize bytes) from the Hyperterminal ended by '\r' (Enter key) */
12 do
13 {
14 if((USART_GetFlagStatus(USART1, USART_FLAG_RXNE) != RESET)&&(RxCounter < RxBufferSize)) //0xFF:256字符
15 {
16 RxBuffer[RxCounter] = USART_ReceiveData(USART1);
17 USART_SendData(USART1, RxBuffer[RxCounter++]);
18 }
19
20 }while((RxBuffer[RxCounter - 1] != '\r')&&(RxCounter != RxBufferSize));
21
22 //串口配置函数
23
24 void USART_CTRT_Configuartion(void)
25 {
26 USART_InitTypeDef USART_InitStruct;
27
28 Rcc_Configuration();
29
30 USART_InitStruct.USART_BaudRate = 115200;
31 USART_InitStruct.USART_StopBits = USART_StopBits_1;
32 USART_InitStruct.USART_WordLength = USART_WordLength_8b;
33 USART_InitStruct.USART_Parity = USART_Parity_No;
34 USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_RTS_CTS;
35 USART_InitStruct.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
36
37 USART_Init(USART1, &USART_InitStruct);
38
39 USART_Cmd(USART1, ENABLE);
40
41 UsartGPIO_CTRT_Configuration();
42 }
完整的代码可以自己参考库函数。这里不再贴了。
引用参考:http://www.cnblogs.com/sunyubo/archive/2010/04/21/2282176.html
LinuxGPIO驱动使用其实很简单
转自:http://blog.csdn.net/drivermonkey/article/details/20132241
1.1.References
1.2.GPIO Usage from a Linux Application
1.2.1Overview
1.2.2.Configure the kernel for GPIO support in sysfs
1.2.3.Enable GPIO access from user space
1.2.4.GPIO interrupts from user space
1.2.4.1.Reference
1.2.4.2.LeopoardBoard 365 GPIO 0 connection
1.2.4.3.Using poll to monitor for GPIO 0 change
3.Example shell script making it easy to set GPIOs from the command line
1.1.References
1.2.GPIO Usage from a Linux Application
1.2.1.Overview
The following table summarizes the steps to configuring and using GPIO signals from a Linux application.
Step | Action | Description |
---|---|---|
1 | Configure the kernel for GPIO support in sysfs | Allow GPIO configuration and control from Linux applications (user space). The GPIO shoulw up in the system file system, sysfs, at /sys/class/gpio |
2 | Export GPIO to user space | Each GPIO is are not accessible from user space until the GPIO has been exported. You can only export a GPIO that isn't owned by a Linux kernel driver |
3 | Configure GPIO for input or output | To avoid hardware issues where two devices are driving the same signal, GPIOs default to be configured as an input. If you want to use the GPIO as an output, you need to change the configuration |
4 | Configure GPIO an an interrupt source | If you have a GPIO that is an input, and you have an application you want to block waiting for the GPIO to change level, you can configure the GPIO as an interrupt source. You also need to configure if the interrupt occurs when the GPIO signal has a rising edge, a falling edge, or interrupts on both rising and falling edges. Once configured as an interrupt, your application can read the value file and the read will block until the interrupt occurs, then your application will return from the read system call and continue running. |
The sysfs directory /sys/class/gpio contains subdirectories and files that are used for configuring and using GPIO signals from a Linux application.
File or directory |
Meaning | Notes |
---|---|---|
/sys/class/gpio | sysfs GPIO subdirectory | Linux applications can configuration and use GPIO signals by accessing files in this subdirectory. |
/sys/class/gpio/export | Write-only file to expose a GPIO | Before a Linux application can configuration and use a GPIO, the GPIO first has to beexported to user space by writing the GPIO number to this file. |
/sys/class/gpio/gpio<<<number>>> | Subdirectory for configuring and reading a specific GPIO signal | Once a GPIO has been exported to user space, a new directory appears with a set of files that allow the GPIO to be configured and used by a Linux application |
/sys/class/gpio/gpio<<<number>>>/direction | Read-write supporting values of inand out | |
/sys/class/gpio/gpio<<<number>>>/value | Read-write supporting values of 0 and1 | |
/sys/class/gpio/gpio<<<number>>>/edge | Read-write supporting values ofrising, falling, and both | Check your processor documentation. Not all GPIO pins support interrupts. |
1.2.2.Configure the kernel for GPIO support in sysfs
Symbol: GPIO_SYSFS [=y]
Prompt: /sys/class/gpio/... (sysfs interface)
Defined at drivers/gpio/Kconfig:51
Depends on: GPIOLIB && SYSFS && EXPERIMENTAL
Location:
-> Kernel configuration
-> Device Drivers
-> GPIO Support (GPIOLIB [=y])
1.2.3.Enable GPIO access from user space
GPIO=22 cd /sys/class/gpio
ls
echo $GPIO > export
ls
Notice on the first ls that gpio22 doesn't exist, but does after you export GPIO 22 to user space.
cd /sys/class/gpio/gpio$GPIO
ls
There are files to set the direction and retrieve the current value.
echo "in" > direction
cat value
You can configure the GPIO for output and set the value as well.
echo "out" > direction
echo 1 > value
1.2.4.PIO interrupts from user space
1.2.4.1.Reference
- http://bec-systems.com/site/281/how-to-implement-an-interrupt-driven-gpio-input-in-linux
- http://www.spinics.net/lists/linux-newbie/msg01028.html
- elinux.org/images/d/d4/Celf-gpio.odp
- http://docs.blackfin.uclinux.org/doku.php?id=linux-kernel:drivers:gpio-sysfs
1.2.4.2.eopoardBoard 365 GPIO 0 connection
On the LeopardBoard 365, the only GPIO I could find that was usable for interrupt input is GPIO0, also called CMOS_TRIGGER in the schematics. In looking at the schematics resistor R12 is not loaded and one of the pads connects to CMOS_TRIGGER. This R12 pad is the one closest to R11. If you hold the leopardboard 365 with the SD card slot facing you and rotate the board until the SD card slot is on the bottom edge, the the R12 pads are to the right of J6 and to the left of the SD card slot upper left corner.
1.2.4.3.sing poll() to monitor for GPIO 0 change
The gpio-int-test.c program (or gpiopin.cpp for those who prefer C++) shows one way of using the sysfs file /sys/class/gpio/gpio0/value to block program execution using poll() until the input level on GPIO0 changes. The tricky part was figuring out to use POLLPRI instead of POLLIN as the event to monitor. You must have GPIO support in sysfs for this program to work (or you will not see the /sys/class/gpio directory).
The gpio-int-test.c program uses poll() to wake up every 3 seconds (using poll() timeout mechanism) at which time it prints a period. The poll() function is also watching for input from stdin and for an interrupt from GPIO 0.
Here is an example output. I started gpio-int to watch GPIO 0. I waited around 12 seconds (4 timeout periods), then pressed the letter 'a' twice followed by enter key. Then I shorted the haywire to 3.3V that is accessible on pin 5 on the JTAG connector. JTAG pin 5 is across from the JTAG missing pin). I exited the program using cntl-C.
/root # gpio-int 0 ....aa poll() stdin read 0xA61 poll() stdin read 0xA61 poll() stdin read 0xA0A
..
poll() GPIO 0 interrupt occurred (len 0) poll() GPIO 0 interrupt occurred (len 0) poll() GPIO 0 interrupt occurred (len 0) poll() GPIO 0 interrupt occurred (len 0)
..^C
2.Viewing GPIO Configuration
You can use debugfs to videw the current GPIO configuration. You may also be able to use debugfs to see if the GPIO pin is multiplex as a GPIO or is dedicated to some other function.
Configure the kernel to enable debugfs:
Symbol: DEBUG_FS [=y]
Prompt: Debug Filesystem
Defined at lib/Kconfig.debug:77
Depends on: SYSFS
Location:
-> Kernel configuration
-> Kernel hacking
Boot the target hardware and mount debugfs:
mount -t debugfs none /sys/kernel/debug
Dump the GPIO configuration.
cat /sys/kernel/debug/gpio
Dump the pin multiplexing configuration.
cat /sys/kernel/debug/omap_mux/board # for OMAP
cat /sys/kernel/debug/dm365_mux # for DM36x
3.Example shell script making it easy to set GPIOs from the command line
If you want to have a simple way to control a GPIO signal from the Linux command line, try the gpio.sh script below.
For examaple, if you want to read the value of GPIO 72 without setting its direction, try
gpio.sh 72
If you want to force GPIO 35 to be in input and read the current value, try
gpio.sh 35 in
If you want to configure GPIO 4 to be an output and set the value high, try
gpio.sh 4 out 1
For the script below to work, you need to first make sure you have build busybox with printf enabled.
#!bin/sh show_usage()
{
printf "\ngpio.sh <gpio pin number> [in|out [<value>]]\n"
} if [ \( $# -eq 0 \) -o \( $# -gt 3 \) ] ; then
show_usage
printf "\n\nERROR: incorrect number of parameters\n"
exit 255
fi #doesn't hurt to export a gpio more than once
echo $1 > /sys/class/gpio/export if [ $# -eq 1 ] ; then
cat /sys/class/gpio/gpio$1/value
exit 0
fi if [ \( "$2" != "in" \) -a \( "$2" != "out" \) ] ; then
show_usage
printf "\n\nERROR: second parameter must be 'in' or 'out'\n"
exit 255
fi echo $2 > /sys/class/gpio/gpio$1/direction if [ $# -eq 2 ] ; then
cat /sys/class/gpio/gpio$1/value
exit 0
fi VAL=$3 if [ $VAL -ne 0 ] ; then
VAL=1
fi echo $VAL > /sys/class/gpio/gpio$1/value
4.Example of C/C++ code making it easier to set GPIOs
/* Copyright (c) 2011, RidgeRun
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the RidgeRun.
* 4. Neither the name of the RidgeRun nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY RIDGERUN ''AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL RIDGERUN BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ #include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <poll.h> /****************************************************************
* Constants
****************************************************************/ #define SYSFS_GPIO_DIR "/sys/class/gpio"
#define POLL_TIMEOUT (3 * 1000) /* 3 seconds */
#define MAX_BUF 64 /****************************************************************
* gpio_export
****************************************************************/
int gpio_export(unsigned int gpio)
{
int fd, len;
char buf[MAX_BUF]; fd = open(SYSFS_GPIO_DIR "/export", O_WRONLY);
if (fd < 0) {
perror("gpio/export");
return fd;
} len = snprintf(buf, sizeof(buf), "%d", gpio);
write(fd, buf, len);
close(fd); return 0;
} /****************************************************************
* gpio_unexport
****************************************************************/
int gpio_unexport(unsigned int gpio)
{
int fd, len;
char buf[MAX_BUF]; fd = open(SYSFS_GPIO_DIR "/unexport", O_WRONLY);
if (fd < 0) {
perror("gpio/export");
return fd;
} len = snprintf(buf, sizeof(buf), "%d", gpio);
write(fd, buf, len);
close(fd);
return 0;
} /****************************************************************
* gpio_set_dir
****************************************************************/
int gpio_set_dir(unsigned int gpio, unsigned int out_flag)
{
int fd, len;
char buf[MAX_BUF]; len = snprintf(buf, sizeof(buf), SYSFS_GPIO_DIR "/gpio%d/direction", gpio); fd = open(buf, O_WRONLY);
if (fd < 0) {
perror("gpio/direction");
return fd;
} if (out_flag)
write(fd, "out", 4);
else
write(fd, "in", 3); close(fd);
return 0;
} /****************************************************************
* gpio_set_value
****************************************************************/
int gpio_set_value(unsigned int gpio, unsigned int value)
{
int fd, len;
char buf[MAX_BUF]; len = snprintf(buf, sizeof(buf), SYSFS_GPIO_DIR "/gpio%d/value", gpio); fd = open(buf, O_WRONLY);
if (fd < 0) {
perror("gpio/set-value");
return fd;
} if (value)
write(fd, "1", 2);
else
write(fd, "0", 2); close(fd);
return 0;
} /****************************************************************
* gpio_get_value
****************************************************************/
int gpio_get_value(unsigned int gpio, unsigned int *value)
{
int fd, len;
char buf[MAX_BUF];
char ch; len = snprintf(buf, sizeof(buf), SYSFS_GPIO_DIR "/gpio%d/value", gpio); fd = open(buf, O_RDONLY);
if (fd < 0) {
perror("gpio/get-value");
return fd;
} read(fd, &ch, 1); if (ch != '0') {
*value = 1;
} else {
*value = 0;
} close(fd);
return 0;
} /****************************************************************
* gpio_set_edge
****************************************************************/ int gpio_set_edge(unsigned int gpio, char *edge)
{
int fd, len;
char buf[MAX_BUF]; len = snprintf(buf, sizeof(buf), SYSFS_GPIO_DIR "/gpio%d/edge", gpio); fd = open(buf, O_WRONLY);
if (fd < 0) {
perror("gpio/set-edge");
return fd;
} write(fd, edge, strlen(edge) + 1);
close(fd);
return 0;
} /****************************************************************
* gpio_fd_open
****************************************************************/ int gpio_fd_open(unsigned int gpio)
{
int fd, len;
char buf[MAX_BUF]; len = snprintf(buf, sizeof(buf), SYSFS_GPIO_DIR "/gpio%d/value", gpio); fd = open(buf, O_RDONLY | O_NONBLOCK );
if (fd < 0) {
perror("gpio/fd_open");
}
return fd;
} /****************************************************************
* gpio_fd_close
****************************************************************/ int gpio_fd_close(int fd)
{
return close(fd);
} /****************************************************************
* Main
****************************************************************/
int main(int argc, char **argv, char **envp)
{
struct pollfd fdset[2];
int nfds = 2;
int gpio_fd, timeout, rc;
char *buf[MAX_BUF];
unsigned int gpio;
int len; if (argc < 2) {
printf("Usage: gpio-int <gpio-pin>\n\n");
printf("Waits for a change in the GPIO pin voltage level or input on stdin\n");
exit(-1);
} gpio = atoi(argv[1]); gpio_export(gpio);
gpio_set_dir(gpio, 0);
gpio_set_edge(gpio, "rising");
gpio_fd = gpio_fd_open(gpio); timeout = POLL_TIMEOUT; while (1) {
memset((void*)fdset, 0, sizeof(fdset)); fdset[0].fd = STDIN_FILENO;
fdset[0].events = POLLIN; fdset[1].fd = gpio_fd;
fdset[1].events = POLLPRI; rc = poll(fdset, nfds, timeout); if (rc < 0) {
printf("\npoll() failed!\n");
return -1;
} if (rc == 0) {
printf(".");
} if (fdset[1].revents & POLLPRI) {
len = read(fdset[1].fd, buf, MAX_BUF);
printf("\npoll() GPIO %d interrupt occurred\n", gpio);
} if (fdset[0].revents & POLLIN) {
(void)read(fdset[0].fd, buf, 1);
printf("\npoll() stdin read 0x%2.2X\n", (unsigned int) buf[0]);
} fflush(stdout);
} gpio_fd_close(gpio_fd);
return 0;
}
Using GPIO from a linux shell on iMX based products
https://www.technexion.com/support/knowledgebase/using-gpio-from-a-linux-shell-on-imx-based-products/
Summary
This guide teaches how to find the correct GPIO number for a pin. It also shows how to read the value of an input gpio, or set the value of an output gpio.
Background
The iMX-series CPUs (iMX5, iMX6, iMX6SX, iMX6UL, iMX7D, iMX8M, …) refer to GPIOs using two parameters: a bank number and an io number. For example typical GPIOs can be GPIO2_IO12 or GPIO1_IO00.
The bank refers to the internal GPIO controller inside the CPU, and one controller has 32 IOs. For the example gpios, GPIO2_IO12 uses bank 2 and io 12.
Finding gpio number
To use a GPIO its number needs to be known. If we know the bank and io number, the kernel’s number can be calculated with
N = (BANK – 1) * 32 + IO
For example GPIO2_IO12 would get the kernel GPIO number
N = (2 – 1) * 32 + 12 = 44
Finding out which bank and io a pin has, one has to consult the schematics.
Once the pin name has been found, it’s corresponding GPIO bank and io number can be looked up either in the processor’s reference manual, or from within the kernel source code. In the latter the pinmuxes are defined in the device tree folder arch/arm/boot/dts/
, usually in a file named *pinfunc.h
or so.
A pin can only have one pinmux as GPIO, and a GPIO+IO can only be present on one pin (it is a one-to-one mapping).
Setting and reading a GPIO
The GPIOs are typically accessible in /sys/class/gpio
folder.
Each GPIO has its own folder. For instance GPIO 44 will use folder named /sys/class/gpio/gpio44
. If the folder is not present, the GPIO needs to be exported first. This can be done by:# echo 44 > /sys/class/gpio/export
and similarily unexported by# echo 44 > /sys/class/gpio/unexport
Inside the gpio folder are the two important ‘files’: value
and direction
.
To read the value of a gpio, first set the gpio as an input by# echo in > /sys/class/gpio/gpio44/direction
and then read the value by# cat /sys/class/gpio/gpio44/value
Similarily, set the value of output GPIOs by first setting the direction# echo out > /sys/class/gpio/gpio44/direction
and then set the value low by# echo 0 > /sys/class/gpio/gpio44/value
or to high# echo 1 > /sys/class/gpio/gpio44/value
NB: On products that have isolated GPIOs this semantic is reversed, use 1 for low and 0 for high.
GPIO expanders
GPIO expanders appear on some TechNexion products. Typically the GPIOs on expander chips do not follow the bank/io priniciple. Instead
the GPIOs are directly mapped to the end of the gpio number space(即更简单了,就是相应的数字). Look for folders name gpiochip*
in /sys/class/gpio/
.
Easiest way to find the expander is to look at the ngpio file in the gpiochipN folder. A 8-bit expander will have an 8 in ngpio.
Then the GPIO numbers can be found by looking at the base
file. A value of, say, 208 means that the expanders gpios will be number
208, 209, 210, …
When the GPIO numbers have been identified, they can be exported and used just as the CPU native banked GPIOs.
Future of GPIOs
Since 2016 there is a movement in Linux kernel community to move away from the sysfs based GPIOs to character devices (/dev/gpiochip
N). The current /sys/class/gpio/
folder is likely to be around for quite some time – but applications that want to be futureproof should considering
using the character devices instead.
Troubleshooting GPIOs
Sometimes it might appear that writes to the value file have no effect, the value stays 0 and measuring the voltage on the gpio line gives the same result.
Some common causes for this type of problems are:
- The pin is already used by something else, typically defined to do so in the device tree. Look there first.
- The pin number is wrong. Do the math again.
im6q中的: pad csi的更多相关文章
- python中numpy.pad简单填充0用法
# -*- coding: utf-8 -*-"""Created on Sun Apr 28 22:07:02 2019 @author: jiangshan" ...
- 21.altera fpga 芯片中 pin 和 pad 区别
在chip planner 中 ,看管脚时,会看到 pin 和pad 同时出现, 如 pin120/pad174 Bank 4 那么有什么区别? PIN指芯片封装好后的管脚,即用户看到的管脚: PAD ...
- GStreamer基础教程03 - 媒体类型与Pad
摘要 在上一篇文章中,我们介绍了如何将多个element连接起来构造一个pipline,进行数据传输.那么GStreamer是通过何种方式保证element之间能正常的进行数据传输?今天就将介绍GSt ...
- ICC中用Tcl脚本给版图中的Port/Terminal加Label的方法
本文转自:自己的微信公众号<数字集成电路设计及EDA教程> 里面主要讲解数字IC前端.后端.DFT.低功耗设计以及验证等相关知识,并且讲解了其中用到的各种EDA工具的教程. 考虑到微信公众 ...
- 基于openshift+华为对象存储的CSI开发
目录 需求来源 环境准备 代码修改 镜像下载 镜像生成 修改部署文件 部署CSI插件 CSI原理 核心原理 生命周期: 组件介绍 FAQ 参考: 需求来源 项目上目前使用的是openshift 3.1 ...
- kubelet分析-csi driver注册源码分析
kubelet注册csi driver分析 kubelet注册csi driver的相关功能代码与kubelet的pluginManager有关,所以接下来对pluginManager进行分析.分析将 ...
- REVERSE-极客大挑战-geek2.apk
嗯 一道apk的题目,题目本身并不是很难,但是我用的python却坑了我小半天...不过在纠错的过程中我也学到了不少东西 链接:http://pan.baidu.com/s/1i5LkJDr 密码: ...
- Python开源框架
info:更多Django信息url:https://www.oschina.net/p/djangodetail: Django 是 Python 编程语言驱动的一个开源模型-视图-控制器(MVC) ...
- 镜头覆盖范围FOV 的规划与FOV去四角
本文纲要: 规划FOV的原因 FOV去四角 简单的声明 FOV查找思路 查找FOV的代码 TNoFourCornersRect结构及Contains函数 判断两个矩形是否相交 延伸与拓展 本文内容: ...
随机推荐
- FreeRTOS中断测试
configMAX_SYSCALL_INTERRUPT_PRIORITY 高于此优先级的中断,不能被禁止 #ifdef __NVIC_PRIO_BITS #define configPRIO_BITS ...
- linux防火墙开放端口,针对固定ip开放端口
编辑/etc/sysconfig/iptables,添加 -A INPUT -m state --state NEW -m tcp -p tcp -s 127.0.0.1 --dport 6379 - ...
- linux删除同目录及子目录下统一扩展名的文件
find . -name '*.csv' -type f -print -exec rm -rf {} \; 利用find去查找文件,点是指当前目录下,引号中是相应的数据的名称,自己可以定义,然后用t ...
- django学习记录1
在看django的基础知识,还是按照以前一样来总结,还是晚上再统一总结好了,边看边总结好像效果不大. 第一部分是生成数据库,用python manage.migrate命令来生成django的基础架构 ...
- CV2识别图片A,B,C,D
这个模型是经过简单训练,只能识别四个英文字母:ABCD,是我为了提取答案才训练的,因为科大,百度,以及腾讯的识别不是很准,所以自己训练自己使用,希望能够给你带来方便.下面是训练好的model,如多你感 ...
- Django图书管理系统(前端对数据库的增删改查)
图书管理系统 出版社的管理 源码位置:https://gitee.com/machangwei-8/learning_materials/tree/master/%E9%A1%B9%E7%9B%AE/ ...
- 【转】Http和Https下的cookie的写入问题
网站https:// 可以登陆, 但是切换到http的时候不能登陆. 原因是:https访问的时候,返回的cookie设置了secure=1, 切换成http访问的时候, 这个时候不能操作那个cook ...
- (java)selenium webdriver学习--打开新窗口,并判断新窗口是否与目标窗口一致
描述:selenium webdriver学习--打开新窗口,并判断新窗口是否与目标窗口一致,若一致则切换到该窗口并获取标题 跳出if判断,获取父级标题,并关闭 HTML标签不太明显时,可以用路径表示 ...
- Github的使用/git远程提交代码到Github
Github的使用/git远程提交代码到Github Github是全球最大的社交编程及代码托管网站 Git是一个开源的分布式版本控制系统 1.基本概念 Repository(仓库):仓库用于存放项目 ...
- k8s-yaml
apiVersion: v1 #指定api版本,此值必须在kubectl apiversion中 kind: Pod #指定创建资源的角色/类型 metadata: #资源的元数据/属性 name: ...
- python中numpy.pad简单填充0用法