
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文件,将刚才脚本的内容贴进来就行咯~~
文章来源:创客大爆炸