Hello everyone!
I'm using a Digispark device to make a tiny one-button mouse for a project where it will be connected to an embedded device running Linux (MIPS core, full application processor).
When I insert my Digispark in my running device it enumerates and works correctly.
However, when I boot my device with the Digispark plugged-in, crazy stuff happens.
When I boot up, the device tries to enumerate so early that the boot process has not gotten yet to the USB initialization and then never enumerates.
This is my base code:
#include "DigiMouse.h"
int buttonPin = 5; //set a button to pin
void setup() {
// don't need to set anything up to use DigiMouse
pinMode(buttonPin, INPUT); // For button press
digitalWrite(buttonPin, HIGH); //pull the button high
}
void loop() {
DigiMouse.update();
if (digitalRead(buttonPin) == 0) { //if the button goes low (gets pressed)
DigiMouse.setButtons(4<<0); //middle click
DigiMouse.delay(300);
DigiMouse.setButtons(0); //unclick all
}
}
I tried modifying the library to
not run the connect/disconnect/usbinit process to enumerate right away, but until I issue an
init() command. You can find my mod
here. (This is a separate topic, but I think it is not a good idea to do the init in the singleton constructor. Specially if at some point I wish to be able to trigger re-enumeration.)
With the modification and a substantial delay (10s) in
setup() before calling
DigiMouse.init() it works well. This matches the time after boot where the kernel modules for USB get loaded.
But, what if my setup for one time takes more than 10s? Also, if I hotplug it, it should not have to wait 10s to start working...
I've tried a few things that did not work but got me some information:
- I tried the same thing in a computer, a BeagleBone and a BeagleBoneBlack. It worked in the three devices.
- I tried a real mouse (a pretty Logitech wired laptop mouse that I like a lot, if you need to know) and it does work well on boot up.
- I tried changing the bootloader to use the jumper version. It did not help.
- I tried changing the function of my button to change the LED state, to check if the device was still running. If I clicked very early, the action worked, but later it stopped working.
- So, I tried to figure out for how long the device runs after the bad enumeration. It turns out it runs about 150k loop() cycles before it gets stuck (it takes about 3 secs).
- So, I tried to set the watchdog to reboot or at least trigger re-enumeration of the device after some time. (Re-enumeration works if I run the DigiMouse.init() method as mentioned above.) I saw that something happened (my LED changed state) after the WDT timeout, but it didn't seem try to run the bootloader/setup again.
- So, I tried to override the WDT ISR with an ISR that called the reboot() function listed in the Tips and Tricks section of the wiki. It seems it doesn't get run either. (I added a LED flash before it runs reboot, and it doesn't happen.)
So... any ideas? I'm trying to figure out if we have a hardware problem in the embedded device, as well, but for now I will need a good workaround in the digispark side that doesn't imply a lenghty and potentially unreliable wait. I really like the idea of using the watchdog, but it doesn't work well.
Thanks for reading, I hope you can help.