Skip to content Skip to sidebar Skip to footer

Uart / GPS Driver Sample Buffer Overflow

I am trying the sample for the GPS driver with a raspberry pi 3 and the Ultimate GPS V3 breakout board. Here is the full source code: https://github.com/androidthings/drivers-sampl

Solution 1:

In some cases processBuffer() will process the whole buffer (512 bytes) regardless of how many bytes are read from the UART. If it happens to miss a start or end character you can end up with a lot of '0' in the message buffer. You can modify this to be like this:

int count;
while ((count = uart.read(buffer, buffer.length)) > 0) {
  processBuffer(buffer, count);
}

then modify this to be more like this:

private void processBuffer(byte[] buffer, int length) {
    for (int i = 0; i < length; i++) {
        if (mParser.getFrameStart() == buffer[i]) {
            handleFrameStart();
        } else if (mParser.getFrameEnd() == buffer[i]) {
            handleFrameEnd();
        } else {
            //Insert all other characters into the buffer
            mMessageBuffer.put(buffer[i]);
        }
    }
}

Then you won't be filling the message buffer with garbage if an end character gets dropped. I noticed this happening in a project I'm working on that uses this source code. The readUartBuffer() method can read split messages, i.e., the start or end of a message. If it does, bad things happen.


Solution 2:

Looking at the demo code https://github.com/androidthings/drivers-samples/blob/master/gps/src/main/java/com/example/androidthings/driversamples/GpsActivity.java#L35 the Baud rate is set correctly as per the data sheet: https://cdn-learn.adafruit.com/downloads/pdf/adafruit-ultimate-gps.pdf

And looking at the contrib-driver for NmeaGpsModule the message buffer length is twice the size of the buffer read from the driver https://github.com/androidthings/contrib-drivers/blob/master/gps/src/main/java/com/google/android/things/contrib/driver/gps/NmeaGpsModule.java#L169 so it can't overflow with just one read.

A theory for the issue could be that the message buffer is not being cleared after it receives data - therefore you get a BufferOverflowException after a few packets.

The buffer is reset in 2 places:

When a new frame starts:

https://github.com/androidthings/contrib-drivers/blob/master/gps/src/main/java/com/google/android/things/contrib/driver/gps/NmeaGpsModule.java#L187

Or when a frame ends:

https://github.com/androidthings/contrib-drivers/blob/master/gps/src/main/java/com/google/android/things/contrib/driver/gps/NmeaGpsModule.java#L209


I don't have the hardware to debug your issue, however I can recommend how you could do it:

This goes for anyone wanting to debug a contrib-driver

Fork / Make a copy of this android library: https://github.com/androidthings/contrib-drivers/tree/master/gps

Edit the build.gradle to add this dependency: https://github.com/novoda/bintray-release (follow the README for instructions).

Once you add that dependency the build.gradle will look like this:

apply plugin: 'com.android.library'
apply plugin: 'com.novoda.bintray-release' // new code

android {
    compileSdkVersion 24
    buildToolsVersion '24.0.3'

    defaultConfig {
        minSdkVersion 24
        targetSdkVersion 24
        versionCode 1
        versionName "1.0"
    }
}

buildscript {
    repositories {
        jcenter()
   }
    dependencies {
        classpath 'com.novoda:bintray-release:0.4.0'  // new code
    }
}

dependencies {
    compile 'com.android.support:support-annotations:24.2.0'
    provided 'com.google.android.things:androidthings:0.1-devpreview'
}

publish {  // new code
    userOrg = 'google'
    groupId = 'com.google.android.things.contrib'
    artifactId = 'driver-gps'
    publishVersion = '0.1-DEBUG'
}

Now you can release your own version of the GPS driver for debugging, but first:

Edit the java files, to add logging. In the NmeaGpsModule.java of your fork/copy, make two changes:

private void init(UartDevice device, int baudRate, Handler handler) throws IOException {
    Log.d("XXX", "MY VERSION BEING USED"); // new code
    mDevice = device;
    mDevice.setBaudrate(baudRate);
    mDevice.registerUartDeviceCallback(mCallback, handler);

    mParser = new NmeaParser();
}

and

private void resetBuffer() {
    Log.d("XXX", "BUFFER BEING RESET");  // new code
    mMessageBuffer.clear();
    mFrameFlag = false;
}

To release this version run this command in a terminal from the same folder as the build.gradle:

 ./gradlew clean build bintrayUpload -PdryRun=true

Now you have released a dependency! Back in your application (in this case the driver-samples) https://github.com/androidthings/drivers-samples/blob/master/gps/build.gradle#L39:

Change the build.gradle to have a different dependency:

 compile 'com.google.android.things.contrib:driver-gps:0.1'

becomes

 compile 'com.google.android.things.contrib:driver-gps:0.1-DEBUG'

and tell it to look locally for this dependency:

repositories {
    mavenLocal()
    jcenter()
}

Now rerun the application and you should see your logs! First the sanity log to prove it worked "MY VERSION BEING USED" then the buffer being reset "BUFFER BEING RESET" if the buffer isn't being reset .. you need to check your hard wiring or add more logs to figure out why.


Post a Comment for "Uart / GPS Driver Sample Buffer Overflow"