edison扩展板otg自动复位

Edison breakout扩展板在reboot之后无法自动识别挂载在usb otg线上的usb client设备,这样极大的限制了edison breakout扩展板的可玩性。尽管不能深入到edison的内核层次修改edison的usb驱动程序,但是我们可以通过一些小的trick绕开edisonbreakout的这个缺陷,实现对usb otg的修复。

1、请按照如下两张图的提示,定制一个将usb id端口和usb GND端口通过si2306 器件隔开的特殊的usb otg线。

说白了呢,就是自制一根usb otg的线啦。只不过就是默认的otg线是将ID引脚和GND引脚直接短接的。但是在我们这个修复的硬件修复补丁里,我们加了一个非常trick的SI2306。至于这个IC的详细资料,请自行查找,总之它就是个1.0v电平就足以触发的mos管。

上面这张图有点糙,不过意思还是能看明白的。看到这里,大家可能会说这个不合理,因为Gate那里应该做10k拉低,不过我确实当时试过拉低,奇怪的是拉低之后,就真的起不来了…………去掉之后非常好用。这里以后请大神给解释一下。

2、完成这个硬件后,请将那根链接在SI2306芯片上的飞线连接到edison breakout底部某一个闲置的GPIO孔上,这里我使用了GPIO128,也就是位于J17行第14个的那个孔。简单的整理一下线路,就可以得到类似下图的效果。


3、编写一个edison的本地IO操作程序,代码如附件pinset.c

使用edison sdk对这个程序进行编译,这里我们编译为pinset,通过scp上传到edison上。

这里我还是把代码贴上了:

#include

#include

#define GPIO_DIR_PATH "/sys/class/gpio/gpio%d/direction"

#define GPIO_VALUE_PATH "/sys/class/gpio/gpio%d/value"

#define GPIO_EXPORT_PATH "/sys/class/gpio/export"

#define BUFFER 64

#define OUT "out"

#define OUTLEN sizeof("out")

#define HIGH "1"

#define LOW "0"

#define VALUELEN sizeof("1")

int create_gpio_fd(int pin)

{

int fd=0;

int err;

char buffer[16];

fd = open(GPIO_EXPORT_PATH,O_WRONLY);

if(fd<0){

//file not exit, sys fail

return -1;

}

sprintf(buffer,"%d",pin);

err = write(fd,buffer,16);

if(err==-1){

return -1;

}

close(fd);

return 0;

}

int main(int argc, char * argv[])

{

if(argc<3){

printf("Usage: pinset [gpio_pin] [0/1]\n"

"\t\teg: $pinset 12 1\n"

"\t\tset gpio12 to HIGH.\n");

return -1;

}

int pin = atol(argv[1]);

if(pin < 0){

printf("Error:Invalid input pin value: %d.\n",pin);

return -1;

}

int value = atol(argv[2]);

if(value!=0)value=1;

printf("Setting GPIO%d to %d...\n",pin,value);

char gpio_direction[BUFFER];

char gpio_value[BUFFER];

int fd_val=0;

int fd_dir=0;

int err=0;

const char *str_value;

if(value){

str_value = HIGH;

}else{

str_value = LOW;

}

//set GPIO paths

snprintf(gpio_direction,BUFFER,GPIO_DIR_PATH,pin);

snprintf(gpio_value,BUFFER,GPIO_VALUE_PATH,pin);

//check if the gpio device exist, if not, create.

fd_dir = open(gpio_direction,O_WRONLY);

if(fd_dir<0){

if(err=create_gpio_fd(pin)){

printf("Error:Fail to create the gpio%d deivce.\n",pin);

goto EXIT;

}

//create and open again.

fd_dir = open(gpio_direction,O_WRONLY);

if(fd_dir<0){

printf("Error:Fail to create the gpio%d deivce.\n",pin);

err=-1;

goto EXIT;

}

}

//check if gpio value fd exist.

fd_val=open(gpio_value,O_WRONLY);

if(fd_val<0){

printf("Error:Fail to open the gpio%d value device.\n",pin);

err=-1;

goto EXIT;

}

//set direction to output

err = write(fd_dir,OUT,OUTLEN);

if(err==-1){

printf("Error:Fail to set the gpio%d to output.\n",pin);

err=-1;

goto EXIT;

}else{

printf("Set GPIO%d direction as OUTPUT.\n",pin);

}

//write value

err= write(fd_val,str_value,VALUELEN);

if(err==-1){

printf("Error:Fail to set the gpio%d to %d.\n",pin,value);

err=-1;

goto EXIT;

}else{

printf("Set GPIO%d to %d.\n",pin,value);

}

EXIT:

if(fd_val>=0)close(fd_val);

if(fd_dir>=0)close(fd_dir);

return err;

}

大家如果喜欢的话,后期可以再加上读取状态的操作,作为一个breakout上专用的IO读写操作小工具。哦,对了,有人问我为什么不用mraa,因为mraa其实是为了arduino extension设计的,在breakout这里并不好用。

4、链接edison的串口并启动,在第一次冷启动后,执行:

#lsusb

如果得到

则执行如下操作:

#./pinset 128 0

等待1秒后再执行

#./pinset 128 1

因为我的那个si2306 Gate的控制线链接到了edison底部的GPIO128上,所以这里参数为128,你要根据自己的情况进行修改。

等待几秒后,再执行lsusb,这时候就应该可以看到如下内容:

说明usb otg已经通过程序操作复位成功,再也不需要在reboot或者冷启动后手动插拔otg线啦!

当然咯,我们可以再进化一点,写个otgreset.sh,把pinset工具放到/usr/bin里面去~

#!/bin/sh

OTG_PIN=128

pinset $OTG_PIN 0

sleep 1

pinset $OTG_PIN 1

sleep 2

5、 如果希望开机的时候自动复位:为edison添加开机启动程序

执行如下操作

$touch /etc/init.d/rc.local

$chmod +x /etc/init.d/rc.local

$update-rc.d /etc/init.d/rc.local start 99 .stop 99

为了编辑方便,创建一个软链接

$ln -s /etc/init.d/rc.local /etc/rc.local

好了,编辑你的rc.local文件,将刚才脚本的内容贴进来就行咯~~

文章来源:创客大爆炸