How does the Android IOIO App loop() function work?

180 views
Skip to first unread message

Vincent Nadon

unread,
Mar 11, 2015, 1:55:55 PM3/11/15
to ioio-...@googlegroups.com
How does the Android IOIO App loop() function work? Is there a way to create functions in the Looper class which are called inside this loop() according to a listener on a Button or a Spinner? This way it would simplify my code since I need to send a lot of twi commands in the loop() based on the user input in my Android UI Menu.

Vincent Nadon

unread,
Mar 11, 2015, 2:48:45 PM3/11/15
to ioio-...@googlegroups.com
I am having the following problem : http://stackoverflow.com/questions/28989176/android-app-stops-i2c-bluetooth-communication-ioio 
and I think it's because all my code to call the twi.WriteReadAsync is outside the loop() function.

Ytai Ben-Tsvi

unread,
Mar 12, 2015, 12:28:13 AM3/12/15
to ioio-...@googlegroups.com
There's nothing special about the loop() method, it is mostly a convenience feature. You may call IOIO APIs from any thread including the UI thread (which includes all sorts of GUI listeners).
The code you posted on stackoverflow doesn't have anything that's related to IOIO on it, so I don't think you'd get much help there. I recommend you to make a copy of your problematic app, trim it down to the bare minimum that illustrates the problem and then post it here.

--
You received this message because you are subscribed to the Google Groups "ioio-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ioio-users+...@googlegroups.com.
To post to this group, send email to ioio-...@googlegroups.com.
Visit this group at http://groups.google.com/group/ioio-users.
For more options, visit https://groups.google.com/d/optout.

Vincent Nadon

unread,
Mar 12, 2015, 10:06:20 AM3/12/15
to ioio-...@googlegroups.com
Hi,

Here is the trimmed down file that should illustrate the problem. I think it mainly comes from my threads (timers) and the IOIO management...

Hope you guys can help me out :)

See attached file!
IOIO_bug_example.java

Ytai Ben-Tsvi

unread,
Mar 12, 2015, 5:00:50 PM3/12/15
to ioio-...@googlegroups.com

Is that really the minimum required, in the sense that anything you'd remove would make the problem disappear? Also some things are missing, e.g. where the response buffer being defined and why are you comfortable sharing it across asynchronous calls.

Vincent Nadon

unread,
Mar 13, 2015, 8:04:47 AM3/13/15
to ioio-...@googlegroups.com
Hi,

I trimmed it a bit more again, I haven't tested this code because I would have to put some code back in... but it should show the problem. I have shown where "response" is defined in this version. I am comfortable sharing across asynchronous calls since these calls are supposed to be sequential if I see it right and also it is simply a read data buffer.

Thanks for further help :)
IOIO_bug_example.java

Ytai Ben-Tsvi

unread,
Mar 13, 2015, 7:11:28 PM3/13/15
to ioio-...@googlegroups.com
I think you misunderstood what I meant by "minimal code". What I meant is that you provide me with minimum code that actually does build and run and exhibits your problem and that is as small as possible. Reading through your 300 or so lines of code trying to figure out what's going on is a pretty time-consuming task. It is very likely that in the process of trying to strip down your code you'll find out the problem yourself. Otherwise, you'd be at least able to explain it more precisely.

As for the asynchronous calls, if you actually care about what's in the buffer, you shouldn't share it across concurrent calls. Otherwise, why are you passing it in the first place?

Vincent Nadon

unread,
Mar 16, 2015, 1:54:19 PM3/16/15
to ioio-...@googlegroups.com
Hi,

I am sorry about that. I understand that debugging a lot of code is time consuming. Here attached is a version that I debugged step by step. I found that I had calls to functions which might call the twi.writeReadAsync simultaneously, removing these calls made my app responsive to subsequent calls of my stim_on and stim_off. Moreover, calling the twi.writeReadAsync for the RB buffer at multiple places as you mentioned seemed to cause the App to crash after a second call of my stim_on and stim_off. Removing all calls to  twi.writeReadAsync for RB buffer solved the problem for the moment.

I figured that I need to keep the screen alive (as I used to do) so that after my Timer is up my stim_off is executed, otherwise it is not executed.

I also have a problem that is persisting, I cannot call my stim_on with my button on my screen more than 8 times precisely, is that related to some buffer or something?

I would like to know how I can make sure that I can call the twi.writeReadAsync in multiple functions, sequentially (one after the other). For example, DSP_button1(); followed by  DSPbutton2(); and DSPbutton3(); each containing calls of  twi.writeReadAsync .

Thanks again for your help!
SensorGraphActivity.java

Ytai Ben-Tsvi

unread,
Mar 16, 2015, 2:08:39 PM3/16/15
to ioio-...@googlegroups.com
You should be able to use the entire API concurrently with no problem. It is all thread safe.
How exactly does it crash when it does?
Also, you seem to be clobbering the "response" buffer from multiple requests and you also seem to be reading from it without waiting for the transaction to complete.

Vincent Nadon

unread,
Mar 16, 2015, 2:20:13 PM3/16/15
to ioio-...@googlegroups.com
The App doesn't crash anymore when I take out the twi call for RB buffer. When it crashes it starts my stim_on (so I hear sounds with my device) and then it tells me that Unfortunately the App has stopped. I can confirm to you tomorrow more precisely how...

How can I make sure to wait for the transaction to complete? with delays? I think this might be a problem like you say. Also, you say calling multiple functions subsequently with calls to twi shouldn't be a problem?

Vincent Nadon

unread,
Mar 17, 2015, 10:22:23 AM3/17/15
to ioio-...@googlegroups.com
So I included back the call of twi to read RB and put it in "response" buffer (see attached code) to make the App crash. Now, when I start my timer it starts stim_on and after a few seconds the App crashes, in the LogCat I see IOIOthread is exiting.
SensorGraphActivity.java

Ytai Ben-Tsvi

unread,
Mar 17, 2015, 8:24:36 PM3/17/15
to ioio-...@googlegroups.com

When an Android app crashes, an error message an stack trace gets written to the log. What's in your log?
Also, in order to wait for completion just call writeRead() instead of Async(). Another option is using the object returned from Async() to await completion.

Vincent Nadon

unread,
Mar 19, 2015, 2:47:36 PM3/19/15
to ioio-...@googlegroups.com
I printed the LogCat outpout related to the App crash, you can find it attached to this post . I don't know exactly what you mean by stack trace, I hope it is contained inside the LogCat messages... or did you mean another Log file? I am not familiar with all the Logs...

I tried to wait completion of Async() with the returned object as follows, but it still crashes before I see message "Stim stopped" because of the following twi call which doesn't work :

public class dataRecCountDownTimer extends CountDownTimer {
public dataRecCountDownTimer(long startTime, long interval) {
super(startTime, interval);
}
@Override
public void onTick(long millisUntilFinished) {
try {
read_ack = twi.writeReadAsync(addressDSP3, false, RB,
RB.length, response,
response.length);

} catch (ConnectionLostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@Override
public void onFinish() {
if(read_ack.equals(1))
{
try {
twi.writeReadAsync(addressDSP1, false, stim_off,
stim_off.length, null, 0);

} catch (ConnectionLostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
iWrite("Stim stopped");
}
}
}

When I try with the synchronous method writeRead() it completely freezes my Android App:

public class dataRecCountDownTimer extends CountDownTimer {
public dataRecCountDownTimer(long startTime, long interval) {
super(startTime, interval);
}
@Override
public void onTick(long millisUntilFinished) {

try {
read_ack = twi.writeRead(addressDSP3, false, RB, RB.length, response,
response.length);
} catch (ConnectionLostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

}
@Override
public void onFinish() {
if(read_ack == true)
{

try {
twi.writeRead(addressDSP1, false, stim_off,
stim_off.length, null, 0);
} catch (ConnectionLostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

iWrite("Stim stopped");
}
}
Android_App_Error_log.txt

Ytai Ben-Tsvi

unread,
Mar 23, 2015, 1:01:34 AM3/23/15
to ioio-...@googlegroups.com
  1. Are you using a very old version of IOIOLib? Looks like you're hitting a bug that has been resolved long ago.
  2. You're not using the result correctly. You should call waitReady() on it, as well as check the return value for success.
  3. You seem to still be generating a lot of async requests writing to the same result buffer.
What are you actually trying to achieve? You seem to be reading data and then not using it at all. There's probably a better and simpler way to do what you want.

Vincent Nadon

unread,
Mar 23, 2015, 6:47:04 AM3/23/15
to ioio-...@googlegroups.com
1. I am using IOIOlib version 3.30, is it considered too old? I am using this version because it is compatible with my firmware in my PIC, according to what you are saying I might have to upgrade everything (PIC firmware and IOIOlib) which might be a bit difficult for me since I have to put back all the modifications I did in the firmware until now. If I have to do it I will do it, but of course I would like to avoid this trouble.

2. I will try that.

3. I need to read the DSP register every 100ms for 10 consecutive reads (total 1 second). Then calculate the average of these register values and show it to the user on the Android UI screen. After that I put the stim_off, to stop the stimuli procedure. In the code I attached I removed the averaging part since I had to give you the minimal code showing the problem. I am open for suggestions to find a better way to do what I need to do.


Thanks!

Vincent

Vincent Nadon

unread,
Mar 23, 2015, 7:47:50 AM3/23/15
to ioio-...@googlegroups.com
So I tried with the waitReady() and it freezes as soon as I call it...

See code:
public void onFinish() {
iWrite("Read ack? :" + read_ack_bool);

try {
read_ack =  twi.writeReadAsync(addressDSP1, false, stim_off,
stim_off.length, null, 0);

read_ack_bool = read_ack.waitReady();

iWrite("Read ack? :" + read_ack_bool);

Vincent Nadon

unread,
Mar 23, 2015, 2:20:22 PM3/23/15
to ioio-...@googlegroups.com
I think I might have found something related to the problem while I was updating my Firmware files. I saw that all calls with rx_queue in i2c.c were commented, I don't remember why we did this, but it would explain why the waitReady() and all calls waiting for an answer through TWI would crash. 

Do you think this would be a possible explanation?

I am continuing to update all my Firmware and Android IOIO libs. I should be able to give some news about the progress during the week.

Ytai Ben-Tsvi

unread,
Mar 23, 2015, 4:47:10 PM3/23/15
to ioio-...@googlegroups.com
There is no inherent timeout on the TWI calls. They will block forever if the response never arrives (or the thread is interrupted).
In order to save everybody's time, I would suggest that you try getting this piece of code to work with a stock v5.x firmware and stock v5 IOIOLib and only once you've nailed down the software consider going back to custom.

I have no explanation for the crashes. Let's try to get your software right first and see if they still occur.

If you're sampling every 100ms you should be perfectly OK using only blocking calls. This will make you life a lot easier. Make sure to check the return code of writeRead(). If it is false, the transaction failed (e.g. NACKed), which means you should disregard any data in the response buffer.

Vincent Nadon

unread,
Mar 24, 2015, 6:17:31 AM3/24/15
to ioio-...@googlegroups.com
Yes, I did start to upgrade to V5 firmware and V5 IOIOLib. This is what I meant by updating my Firmware files.

I will tell you with the status of my progress once I am done with the ugprade. For the sampling I will try to use the writeRead() calls only as you say.

--
You received this message because you are subscribed to a topic in the Google Groups "ioio-users" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/ioio-users/1eSftDUOSvo/unsubscribe.
To unsubscribe from this group and all its topics, send an email to ioio-users+...@googlegroups.com.

To post to this group, send email to ioio-...@googlegroups.com.
Visit this group at http://groups.google.com/group/ioio-users.
For more options, visit https://groups.google.com/d/optout.



--
Vincent Nadon
Ph.D. candidate, M. A. Sc., B.Eng.
Universiteit Gent
Belgian Mobile number: 0 470 94 58 82

Vincent Nadon

unread,
Mar 26, 2015, 12:30:03 PM3/26/15
to ioio-...@googlegroups.com
  • So I tried the V5.X firmware, as plain vanilla as I could. I have put some call for LEDs to light up during boot process and I connected an Arduino USB2Serial to monitor the logging.
 As it is, no LEDs light up and I don't see anything in the logging, no "***** Hello from app-layer! *******", nothing... Even my bluetooth dongle doesn't seem to light up anymore.
 
I did configure everything to suit my hardware (PIC24FJ256DA206) and then also changed the pins for my UART according to what I had working in my previous firmware, and changed few pins for LEDs. I also configured the ENABLE_LOGGING in the pic30-gcc preprocessor macros.
 

libusb, libconn, libbtstack, libadb, Bootloader and AppLayerV1 all build without errors.

  • I have also another question, in my previous firmware version I had to set Memory_Model to Large Data, Large code and small scalar.  I also had to modify QUEUE_SIZE in protocol.c to 128 (instead of 8192) to fit the code to program my DSPs in the pic memory. Would you have a better suggestion to provide the memory space for DSP code? (I use the pic to program my DSPs at bootup)

Ytai Ben-Tsvi

unread,
Mar 27, 2015, 3:43:31 AM3/27/15
to ioio-...@googlegroups.com

There are too many things that can go wrong in your setup: custom IOIO, custom forward with changes that are very likely to break stuff and a fair amount of complexity in your app.
I recommend that you start by eliminating some possible causes (e.g. test your app on a stock IOIO with stock firmware or run a rigorous test on your custom hardware/firmware, such as the IOIO torture test.
Otherwise you'd be wasting our time.

--

Vincent Nadon

unread,
Mar 27, 2015, 6:22:59 AM3/27/15
to ioio-...@googlegroups.com
I'm only talking about the Hardware firmware now. I can't even try with my Android App since my hardware doesn't even boot and therefore doesn't establish the bluetooth or USB connection. As I said I am using the IOIO V5.x as plain as I can. I will try again without changing anything at all, but chances are there might be something that I need to modify that I don't see.

As you say it is hard to find the problem since I have custom hardware and therefore need to modify the Firmware a bit.

Vincent Nadon

unread,
Mar 31, 2015, 12:28:20 PM3/31/15
to ioio-...@googlegroups.com
UPDATE: I have found the problem related to the non responsive calls of twi.readWrite() with my custom firmware (V3.x), this was due to some modifications we did in the i2c.c file commenting all calls of rx_queue. After uncommenting these lines, the Andrdoid App received the read acknowledge (Result...).

I still wasn't able to make V5.x stock firmware work on my custom platform. As you say I would probably need to try it on a stock IOIO hardware board, but at this time for me it is too complicated (buying a IOIO, trying it, then trying to debug my custom board again) and it would get me further from the problem that I already partly solved.

Now, I have two problems:
  1. After about 24 twi.readWrite() calls, my PIC restarts by itself so I can only do 24 reads whether it is 1 every 100ms or 1 every 1second. In my case I would like to do 22x 10 readings, 1 every 100ms. I had previously decreased DEFINE_STATIC_BYTE_QUEUE to 128 instead of 8192 for the rx to have enough memory space for proper functionnality of my DSPs. I tried to increase it to 2048, but then my audio signals didn't sound right in my DSP and also it didn't solve the problem that after 24 reads the PIC restarts. To me this seems to be some kind of buffer problem, when it gets full it crashes. I guess there could be a way to reset this buffer every few calls, if we find this faulty buffer??
  2. I cannot read the response value. I see in my PIC logging that the command to read passes and the correct value is in the buffer in the PIC, but it doesn't get in the Android App...

Ytai Ben-Tsvi

unread,
Mar 31, 2015, 1:04:51 PM3/31/15
to ioio-...@googlegroups.com
I don't see how I can effectively help you when you're running a modified version of the firmware that I am not familiar with and are unable to demonstrate the the problem originates from the standard codebase (not to say that it doesn't).
You need to debug your code and figure out what's happening. If you get to a conclusion that some of the existing code is wrong, I would love to look into it. If you have specific question about the code or about how to debug I would love to help.

Vincent Nadon

unread,
Apr 2, 2015, 12:31:03 PM4/2/15
to ioio-...@googlegroups.com
Okay, I will try to ask more specific questions. I also saw that a similar problem was reported here: Maximum TWI transaction size . This might be related?

Questions:

1. I cannot find the files for for previous versions of the Firmware. I downloaded all the files contained in the GitHub. I would like to take a look at the files of Firmware version IOIO0326 to compare them with my slightly modified versions to see the differences. Especially the i2c.c/.h and the protocol.c/.h.  Is there a way to find such files somewhere else?

2. The problem I have seems to be related to latency or drops of bytes (because of a full buffer?). Which lead to disconnection of the PIC IOIO and freezing my App. I am able to receive the first few bytes and then after a few writeRead() the PIC sends a  AppProtocolSendMessageWithVarArgSplit then the Android App freezes. Obviously, now I get writeRead acknowledges for the correct reads, when it drops I don't get the aknowledge. This  AppProtocolSendMessageWithVarArgSplit seems to occur because of a latency problem which provokes a lost of bytes (0 bytes at beginning and 183 bytes at the end? when I am supposed to have 4 bytes , see screenshot attached). Please note that psd_buff_ptr contains the value I'm reading (in my UART logging) and I am able to see this value appear in my LogCat sometimes or partly see attached LogCat excerpt.

 I tried increasing Interrupt Priority level from 4 to 2, as you did in the change from V3.x to V5.x of the Firmware. Then my Device seems to bootup faster because of all my i2c calls which now have higher priority, but my latency or dropout problem still occurs. As soon as I get the drop and then reboot my App, my Device also reboots to reconnect with the App. Please find my versions of i2c and protocol.c attached (based on V3.x), I think the problem would mainly be there. Again I did compare these files with the V5.x version and didn't see major changes other than optimization of some functions like atomic16 and   AssignMI2CxIF. The problem occurs no matter if I use twi.writeRead() or twi.writeReadAsync().

Maybe I need a better explanation of how to use  twi.writeRead() and twi.writeReadAsync()? Also explanation on the use of buffers RX_BUF_SIZE in i2c.c and DEFINE_STATIC_BYTE_QUEUE in protocol.c could help me? Would it be useful to clear these buffers after a few reads?

I included an excerpt of the problematic code section of my Android App in attachment. If I take out the writeRead() call everything is fine since the i2c would not be used.

3. I am starting to think that it could be the reading of the DSP register that could cause the latency and crash the connection? According to the 0 bytes received in the logging...What do you think?

I am deeply sorry if all my messages bother you. I am simply doing my best to find the problem and solve it.

Vincent
IOIO_I2C_readWrite_latencybug.png
i2c.h
protocol.c
protocol.h
i2c.c
Android_App_buggy_section.java
LogCat_excerpt.txt

Ytai Ben-Tsvi

unread,
Apr 2, 2015, 2:19:31 PM4/2/15
to ioio-...@googlegroups.com
Inline

On Thu, Apr 2, 2015 at 9:31 AM, Vincent Nadon <vincent....@gmail.com> wrote:
Okay, I will try to ask more specific questions. I also saw that a similar problem was reported here: Maximum TWI transaction size . This might be related?

Questions:

1. I cannot find the files for for previous versions of the Firmware. I downloaded all the files contained in the GitHub. I would like to take a look at the files of Firmware version IOIO0326 to compare them with my slightly modified versions to see the differences. Especially the i2c.c/.h and the protocol.c/.h.  Is there a way to find such files somewhere else?

Everything is in the git history. Official releases are tagged.
 

2. The problem I have seems to be related to latency or drops of bytes (because of a full buffer?). Which lead to disconnection of the PIC IOIO and freezing my App. I am able to receive the first few bytes and then after a few writeRead() the PIC sends a  AppProtocolSendMessageWithVarArgSplit then the Android App freezes. Obviously, now I get writeRead acknowledges for the correct reads, when it drops I don't get the aknowledge. This  AppProtocolSendMessageWithVarArgSplit seems to occur because of a latency problem which provokes a lost of bytes (0 bytes at beginning and 183 bytes at the end? when I am supposed to have 4 bytes , see screenshot attached). Please note that psd_buff_ptr contains the value I'm reading (in my UART logging) and I am able to see this value appear in my LogCat sometimes or partly see attached LogCat excerpt.

 I tried increasing Interrupt Priority level from 4 to 2, as you did in the change from V3.x to V5.x of the Firmware. Then my Device seems to bootup faster because of all my i2c calls which now have higher priority, but my latency or dropout problem still occurs. As soon as I get the drop and then reboot my App, my Device also reboots to reconnect with the App. Please find my versions of i2c and protocol.c attached (based on V3.x), I think the problem would mainly be there. Again I did compare these files with the V5.x version and didn't see major changes other than optimization of some functions like atomic16 and   AssignMI2CxIF. The problem occurs no matter if I use twi.writeRead() or twi.writeReadAsync().

Maybe I need a better explanation of how to use  twi.writeRead() and twi.writeReadAsync()?

If bytes are lost in the communication between the IOIO and the Android it totally doesn't matter what you do in your app. Everything is designed around the assumption that the channel is reliable.
 
Also explanation on the use of buffers RX_BUF_SIZE in i2c.c and DEFINE_STATIC_BYTE_QUEUE in protocol.c could help me? Would it be useful to clear these buffers after a few reads?

This again gets you to the lost bytes case. Doesn't seem like a viable approach.
 
I included an excerpt of the problematic code section of my Android App in attachment. If I take out the writeRead() call everything is fine since the i2c would not be used.

You've probably reduced the load on the buffers by doing that, so no more data gets discarded.
 

3. I am starting to think that it could be the reading of the DSP register that could cause the latency and crash the connection? According to the 0 bytes received in the logging...What do you think?

I don't think latency has to do with it.
 

I am deeply sorry if all my messages bother you. I am simply doing my best to find the problem and solve it.

You're probably better off starting figuring out other ways to save RAM than messing with the one place where all data goes through. You can disable some features (e.g. UART, SPI) which also use RAM buffers. Also, I would slowly encourage you to keep the delta from stock firmware minimal (if at all) or otherwise really make sure you understand how the firmware works and what impact changes you make might have.

Vincent Nadon

unread,
Apr 3, 2015, 5:12:12 AM4/3/15
to ioio-...@googlegroups.com
Okay, in this case how do I disable the SPI to save the RAM ressources? Since I am using the UART, but not the SPI, I think it would be a really good idea to disable it if I can save a good amount of bytes (8000 bytes?).

Thanks!

Ytai Ben-Tsvi

unread,
Apr 4, 2015, 2:21:15 PM4/4/15
to ioio-...@googlegroups.com
The simplest way would be to just go to spi.c and make all the buffers really small.

Vincent Nadon

unread,
Apr 7, 2015, 6:07:46 AM4/7/15
to ioio-...@googlegroups.com
Okay thanks! I might use that later on.

I have finally found the solution to my writeRead acknowledges, it was the ByteQueuePushByte(&i2c->rx_queue, 0x00) in i2c.c that I had removed because it was bugging my bootup sequence. My fix was to put an external variable "bootup" that I control in my main.c to put this stop byte after my bootup was done, see code below. Now my App doesn't bug anymore and I can do around 15 read bursts (1/75ms or 1/100ms) 22 times (so around 330 reads in about 40 seconds), maybe I can do more using the Async(). Hope this post will help someone! :)

    case STATE_STOP_WRITE_ONLY:
     
if (reg->stat >> 15) { goto error; }


     
if(bootup==0)
 
ByteQueuePushByte(&i2c->rx_queue, 0x00);
     
     
goto done;
Reply all
Reply to author
Forward
0 new messages