Uart / GPS驱动程序样本缓冲区溢出

时间:2016-12-26 21:40:38

标签: uart raspberry-pi3 baud-rate android-things

我正在尝试使用覆盆子pi 3和Ultimate GPS V3分线板的GPS驱动程序示例。

以下是完整的源代码:https://github.com/androidthings/drivers-samples/tree/master/gps

按照此原理图连接GPS板: enter image description here

启动示例应用程序时,出现以下错误:

com.example.androidthings.driversamples E/AndroidRuntime: FATAL EXCEPTION: main


Process: com.example.androidthings.driversamples, PID: 1299
   java.nio.BufferOverflowException
       at java.nio.Buffer.nextPutIndex(Buffer.java:508)
       at java.nio.HeapByteBuffer.put(HeapByteBuffer.java:142)
       at com.google.android.things.contrib.driver.gps.NmeaGpsModule.processBuffer(NmeaGpsModule.java:178)
       at com.google.android.things.contrib.driver.gps.NmeaGpsModule.readUartBuffer(NmeaGpsModule.java:160)
       at com.google.android.things.contrib.driver.gps.NmeaGpsModule.access$000(NmeaGpsModule.java:35)
       at com.google.android.things.contrib.driver.gps.NmeaGpsModule$1.onUartDeviceDataAvailable(NmeaGpsModule.java:139)
       at com.google.android.things.pio.UartDevice$UartDeviceCallbackDispatch.dispatchInterruptEvent(UartDevice.java:507)
       at com.google.android.things.pio.CallbackDispatch.onFileDescriptorEvents(CallbackDispatch.java:127)
       at android.os.MessageQueue.dispatchEvents(MessageQueue.java:282)
       at android.os.MessageQueue.nativePollOnce(Native Method)
       at android.os.MessageQueue.next(MessageQueue.java:323)
       at android.os.Looper.loop(Looper.java:136)
       at android.app.ActivityThread.main(ActivityThread.java:6077)
       at java.lang.reflect.Method.invoke(Native Method)
       at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:865)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755)

更新1

在contrib-driver项目中启用调试后,我看到一个新错误:W/NmeaParser: Invalid checksum (62), expected 108

12-28 17:53:28.638 1378-1378/com.example.androidthings.driversamples D/XXX: Debug version used
12-28 17:53:29.451 1378-1378/com.example.androidthings.driversamples I/Choreographer: Skipped 34 frames!  The application may be doing too much work on its main thread.
12-28 17:53:29.862 1378-1378/com.example.androidthings.driversamples W/NmeaParser: Invalid checksum (62), expected 108
12-28 17:53:29.862 1378-1378/com.example.androidthings.driversamples D/XXX: Buffer reset
12-28 17:53:30.427 1378-1378/com.example.androidthings.driversamples D/AndroidRuntime: Shutting down VM
12-28 17:53:30.428 1378-1378/com.example.androidthings.driversamples E/AndroidRuntime: FATAL EXCEPTION: main
   Process: com.example.androidthings.driversamples, PID: 1378
   java.nio.BufferOverflowException
       at java.nio.Buffer.nextPutIndex(Buffer.java:508)
       at java.nio.HeapByteBuffer.put(HeapByteBuffer.java:142)
       at com.google.android.things.contrib.driver.gps.NmeaGpsModule.processBuffer(NmeaGpsModule.java:179)
       at com.google.android.things.contrib.driver.gps.NmeaGpsModule.readUartBuffer(NmeaGpsModule.java:161)
       at com.google.android.things.contrib.driver.gps.NmeaGpsModule.access$000(NmeaGpsModule.java:35)
       at com.google.android.things.contrib.driver.gps.NmeaGpsModule$1.onUartDeviceDataAvailable(NmeaGpsModule.java:140)
       at com.google.android.things.pio.UartDevice$UartDeviceCallbackDispatch.dispatchInterruptEvent(UartDevice.java:507)
       at com.google.android.things.pio.CallbackDispatch.onFileDescriptorEvents(CallbackDispatch.java:127)
       at android.os.MessageQueue.dispatchEvents(MessageQueue.java:282)
       at android.os.MessageQueue.nativePollOnce(Native Method)
       at android.os.MessageQueue.next(MessageQueue.java:323)
       at android.os.Looper.loop(Looper.java:136)
       at android.app.ActivityThread.main(ActivityThread.java:6077)
       at java.lang.reflect.Method.invoke(Native Method)
       at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:865)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755)
12-28 17:53:30.439 1378-1378/com.example.androidthings.driversamples I/Process: Sending signal. PID: 1378 SIG: 9

更新2

在将缓冲区大小增加4之后,我能够收到少量消息。我看到一些消息有一些垃圾可以解释溢出:

12-28 23:38:17.393 2366-2366/? D/XXX: message: ��GPGGA,233817.000,3742.1931,N,12208.3976,W,1,04,1.96,164.3,M,-25.5,M,,*58
12-28 23:38:17.394 2366-2366/? D/XXX: Buffer reset
12-28 23:38:17.394 2366-2366/? D/XXX: message: GPGSA,A,3,23,03,26,22,,,,,,,,,2.20,1.96,1.00*0B
12-28 23:38:17.395 2366-2366/? D/XXX: Buffer reset
12-28 23:38:17.544 2366-2366/com.example.androidthings.driversamples D/XXX: message: GP��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������RMC,233817.000,A��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������,3742.1931,N,12208.3976,W,0.42,205.67,281216,,,A*71
12-28 23:38:17.545 2366-2366/com.example.androidthings.driversamples D/XXX: Buffer reset
12-28 23:38:17.545 2366-2366/com.example.androidthings.driversamples D/XXX: message: GPVTG,205.67,T,,M,0.42,N,0.78,K,A*32
12-28 23:38:17.546 2366-2366/com.example.androidthings.driversamples D/XXX: Buffer reset

我不知道垃圾可能来自哪里......

2 个答案:

答案 0 :(得分:1)

查看演示代码https://github.com/androidthings/drivers-samples/blob/master/gps/src/main/java/com/example/androidthings/driversamples/GpsActivity.java#L35,根据数据表正确设置波特率:https://cdn-learn.adafruit.com/downloads/pdf/adafruit-ultimate-gps.pdf

查看NmeaGpsModule的contrib-driver消息缓冲区长度是从驱动程序https://github.com/androidthings/contrib-drivers/blob/master/gps/src/main/java/com/google/android/things/contrib/driver/gps/NmeaGpsModule.java#L169读取的缓冲区大小的两倍,因此只有一次读取就不会溢出。

问题的理论可能是消息缓冲区在收到数据后没有被清除 - 因此在几个数据包之后你得到BufferOverflowException

缓冲区在2个位置重置:

新框架开始时:

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

或框架结束时:

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

我没有硬件来调试您的问题,但我可以推荐您如何做到这一点:

对于想要调试 contrib-driver

的人来说

分叉/制作这个安卓库的副本:https://github.com/androidthings/contrib-drivers/tree/master/gps

编辑build.gradle以添加此依赖关系:https://github.com/novoda/bintray-release(请参阅自述文件以获取说明)。

添加该依赖关系后,build.gradle将如下所示:

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'
}

现在您可以发布自己版本的GPS驱动程序进行调试,但首先:

编辑java文件,添加日志记录。在fork / copy的NmeaGpsModule.java中,进行两处更改:

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();
}

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

要发布此版本,请在与build.gradle

相同的文件夹中的终端中运行此命令
 ./gradlew clean build bintrayUpload -PdryRun=true

现在你已经发布了一个依赖项! 返回您的应用程序(在本例中为driver-sampleshttps://github.com/androidthings/drivers-samples/blob/master/gps/build.gradle#L39

build.gradle更改为具有不同的依赖关系:

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

变为

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

并告诉它在本地寻找这种依赖:

repositories {
    mavenLocal()
    jcenter()
}

现在重新运行应用程序,您应该看到您的日志!首先是完整性日志,证明它工作"MY VERSION BEING USED"然后缓冲区被重置"BUFFER BEING RESET"如果没有重置缓冲区..你需要检查你的硬接线或添加更多日志来找出原因。< / p>

答案 1 :(得分:1)

在某些情况下,无论从UART读取多少字节,processBuffer()都将处理整个缓冲区(512字节)。如果碰巧错过了开头或结尾字符,你最终可能会在消息缓冲区中输入很多“0”。您可以将this修改为:

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

然后修改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]);
        }
    }
}

如果结束字符被删除,那么您将不会使用垃圾填充消息缓冲区。我注意到这发生在我正在使用这个源代码的项目中。 readUartBuffer()方法可以读取拆分消息,即消息的开始或结束。如果是这样,就会发生坏事。