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 线。

图片1.jpg

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

图片2.png

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

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

图片4.jpg

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

如果得到

图片5--.jpg

则执行如下操作:

#./pinset 128 0

等待 1 秒后再执行

#./pinset 128 1

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

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

图片5.jpg

说明 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 文件,将刚才脚本的内容贴进来就行咯~~

发布者:MakerCollider,转载请注明出处:http://www.makercollider.com/kit/1436

发表评论

登录后才能评论
QR code