GPRS_C_SDK
GPRS_C_SDK copied to clipboard
data is sometimes messed up when reading from UART
1. SDK version(SDK 版本)
B2120
There seems to be a serious problem when two UART's work in parallel (build-in GPS and UART1 in my case).
when data transfer happens exactly at the same time, the data is messed up.
I have connected another GPS module to UART1.
this is excerpt of the data from internal GPS (newlines added between frames for clarity):
[...]
$GNGGA,000134.212,5922.4188,N,02442.3154,E,0,0,,130.2,M,19.8,M,,*50
$GPGSA,A,1,,,,,,,,,,,,,,,*1E
$GLGSA,A,1,,,,,,,,,,,,,,,*02
$GPGSV,1,1,00*79
$GLGSV,1,1,00*65
$GNRMC,000134.212,V,5922.4188,N,02442.3154,E,0.000,0.00,060180,,,N*5A
$GNVTG,0.00,T,,M,0.000,N,0.000,K,N*2C
$GNGGA,000135.214,5922.4188,N,02442.3154,E,0,0,,130.2,M,19.8,M,,*57
$GPGSA,A,1,,,,,,,,,,,,,,,*1E
$GLGSA,A,1,,,,,,,,,,,,,,,*02
$GPGSV,1,1,00*79
$GLGSV,1,1,00*65
$GNRMC,000135.214,V,5922.4188,N,02442.3154,E,0.000,0.00,060180,,,N*5D
$GNVTG,0.00,T,,M,0.000,N,0.000,K,N*2C
$GNRMC,,V,,,,,,,6,5922.4188,N,02442.3154,E,0,0,,130.2,M,19.8,M,,*56
$GPGSA,A,1,,,,,,,,,,,,,,,*1E
$GLGSA,A,1,,,,,,,,,,,,,,,*02
$GPGSV,1,1,00*79
$GLGSV,1,1,00*65
$GNRMC,000136.216,V,5922.4188,N,02442.3154,E,0.000,0.00,060180,,,N*5C
$GNVTG,0.00,T,,M,0.000,N,0.000,K,N*2C
NMEA frames from internal gps start with $GNGGA .. note that in the third frame here starts with invalid $GNRMC record.
at the same time, log from external GPS in UART1 (newlines added between frames for clarity):
[...]
$GNRMC,,V,,,,,,,,,,N*4D
$GNVTG,,,,,,,,,N*2E
$GNGGA,,,,,,0,00,99.99,,,,,,*56
$GNGSA,A,1,,,,,,,,,,,,,99.99,99.99,99.99*2E
$GNGSA,A,1,,,,,,,,,,,,,99.99,99.99,99.99*2E
$GPGSV,1,1,00*79
$GLGSV,1,1,00*65
$GNGLL,,,,,,V,N*7A
$GNRMC,,V,,,,,,,,,,N*4D
$GNVTG,,,,,,,,,N*2E
$GNGGA,,,,,,0,00,99.99,,,,,,*56
$GNGSA,A,1,,,,,,,,,,,,,99.99,99.99,99.99*2E
$GNGSA,A,1,,,,,,,,,,,,,99.99,99.99,99.99*2E
$GPGSV,1,1,00*79
$GLGSV,1,1,00*65
$GNGLL,,,,,,V,N*7A
note that the frames here start with $GNRMC ..
it seems the first 16 bytes of GPS data is overwritten with data from UART1
It does not happen always (I assume it happens when the transfer happens exactly at the same time). I've seen the situation reversed, too - ie some bytes of data from internal GPS appear when reading from UART1 ...
This is easily repeatable without external sender.
Connect UART1 rx and tx pins together and run the following code (modified from demo_gps.c)
#include <string.h>
#include <stdio.h>
#include <api_os.h>
#include <api_gps.h>
#include <api_event.h>
#include <api_hal_uart.h>
#include <api_debug.h>
#include "buffer.h"
#include "gps_parse.h"
#include "math.h"
#include "gps.h"
#define MAIN_TASK_STACK_SIZE (2048 * 2)
#define MAIN_TASK_PRIORITY 0
#define MAIN_TASK_NAME "GPS Test Task"
#define max(a,b) \
({ __typeof__ (a) _a = (a); \
__typeof__ (b) _b = (b); \
_a < _b ? _a : _b; })
static HANDLE gpsTaskHandle = NULL;
bool flag = false;
bool isGpsOn = true;
void EventDispatch(API_Event_t* pEvent)
{
switch(pEvent->id)
{
case API_EVENT_ID_NETWORK_REGISTERED_HOME:
case API_EVENT_ID_NETWORK_REGISTERED_ROAMING:
Trace(1,"gprs register complete");
flag = true;
break;
case API_EVENT_ID_GPS_UART_RECEIVED: {
int maxn = min(pEvent->param1, 20);
// make null-terminated string buffer
uint8_t data[maxn+1];
memcpy(data, pEvent->pParam1, maxn);
data[maxn] = 0;
Trace (1, "BUG1 GPS: received, length: %d, data: %s", pEvent->param1, data);
break;
}
case API_EVENT_ID_UART_RECEIVED:
if(pEvent->param1 == UART1) {
// make null-terminated string buffer
int maxn = min(pEvent->param2, 20);
uint8_t data[maxn+1];
memcpy(data, pEvent->pParam1, maxn);
data[maxn] = 0;
Trace(1, "BUG2 uart received data, length: %d, data: %s", pEvent->param2, data);
if(strcmp(data,"close") == 0)
{
Trace(1,"close gps");
GPS_Close();
isGpsOn = false;
}
else if(strcmp(data,"open") == 0)
{
Trace(1,"open gps");
GPS_Open(NULL);
isGpsOn = true;
}
}
break;
default:
break;
}
}
void gps_testTask(void *pData) {
GPS_Info_t* gpsInfo = Gps_GetInfo();
//wait for gprs register complete
//The process of GPRS registration network may cause the power supply voltage of GPS to drop,
//which resulting in GPS restart.
while(!flag) {
Trace(1,"wait for gprs register complete");
OS_Sleep(2000);
}
//open GPS hardware(UART2 open either)
GPS_Init();
GPS_Open(NULL);
//wait for gps start up, or gps will not response command
while(gpsInfo->rmc.latitude.value == 0)
OS_Sleep(1000);
if(!GPS_SetOutputInterval(1000))
Trace(1,"set nmea output interval fail");
Trace(1,"init ok");
while(1) {
OS_Sleep(5000);
}
}
void sendToUart (void *p) {
char kala[100];
snprintf (kala, sizeof(kala), "a123456789b123456789c123456789d123456789e123456789");
UART_Write(UART1,kala,strlen(kala));
UART_Write(UART1,"\r\n\r\n",4);
OS_StartCallbackTimer (gpsTaskHandle, 1000, sendToUart, NULL);
}
void gps_MainTask(void *pData)
{
API_Event_t* event=NULL;
//open UART1 to print NMEA infomation
UART_Config_t config = {
.baudRate = UART_BAUD_RATE_9600,
.dataBits = UART_DATA_BITS_8,
.stopBits = UART_STOP_BITS_1,
.parity = UART_PARITY_NONE,
.rxCallback = NULL,
.useEvent = true
};
UART_Init(UART1,config);
// call loopback sender
OS_StartCallbackTimer (gpsTaskHandle, 1000, sendToUart, NULL);
//Create UART1 send task and location print task
OS_CreateTask(gps_testTask,
NULL, NULL, MAIN_TASK_STACK_SIZE, MAIN_TASK_PRIORITY, 0, 0, MAIN_TASK_NAME);
//Wait event
while(1)
{
if(OS_WaitEvent(gpsTaskHandle, (void**)&event, OS_TIME_OUT_WAIT_FOREVER))
{
EventDispatch(event);
OS_Free(event->pParam1);
OS_Free(event->pParam2);
OS_Free(event);
}
}
}
void gps_Main(void) {
gpsTaskHandle = OS_CreateTask(gps_MainTask,
NULL, NULL, MAIN_TASK_STACK_SIZE, MAIN_TASK_PRIORITY, 0, 0, MAIN_TASK_NAME);
OS_SetUserMainHandle(&gpsTaskHandle);
}
now, in CoolWatcher, filter trace by BUG, and the output is as follows:
- initially (gps not fully started), there goes several lines of
`BUG2 uart received data, length: 54, data: a123456789b123456789
- then, gps starts sending and there are lines both from gps and uart visible, something like this:
BUG1 GPS: received, length: 275, data: $GNGGA,000000.262,59
BUG2 uart received data, length: 54, data: a123456789b123456789
BUG1 GPS: received, length: 275, data: $GNGGA,000000.262,59
BUG2 uart received data, length: 54, data: a123456789b123456789
BUG1 GPS: received, length: 275, data: $GNGGA,000000.262,59
BUG2 uart received data, length: 54, data: a123456789b123456789
[...]
- then, after a while, things get messed up, like this:
BUG2 uart received data, length: 54, data: a123456789b123456789
BUG1 GPS: received, length: 275, data: $GNGGA,000005.262,59
BUG2 uart received data, length: 54, data: a123456789b123456789
BUG1 GPS: received, length: 275, data: $GNGGA,000006.262,59
BUG2 uart received data, length: 54, data: a123456789b123456789
BUG1 GPS: received, length: 275, data: a123456789b123456789
BUG2 uart received data, length: 54, data: a123456789b123456789
BUG1 GPS: received, length: 275, data: a123456789b123456789
[...]
notice how a123456789b123456789 appears from GPS uart ....
Hello, have you found the solution to this problem? I am having the same problem. Thank you!
Just adding a comment here (albeit years later) in case anyone else comes across this, it seems that if you use the callback for UART1 rather than the event handler you can avoid the clash. (albeit you can't TRACE or make other uart calls from the callback)
Hi!
I have a same problem. Pls help me to fix it. Thank you so much.
Sure instead of using the event handler to process the uart use a callback instead:
UART_Config_t uart_config = {.baudRate = UART_BAUD_RATE_115200, // UART_BAUD_RATE_115200,
.dataBits = UART_DATA_BITS_8,
.stopBits = UART_STOP_BITS_1,
.parity = UART_PARITY_NONE,
.rxCallback = onSerial,
.useEvent = false};
(i.e. rxCallback rather than useEvent) This seemed to prevent the clashing/corruption completely for me. The callback gets called with the buffer and size:
static void onSerial(UART_Callback_Param_t param) //
{
if ((param.length > 1) && param.buf) // Have some data
Sure instead of using the event handler to process the uart use a callback instead:
UART_Config_t uart_config = {.baudRate = UART_BAUD_RATE_115200, // UART_BAUD_RATE_115200, .dataBits = UART_DATA_BITS_8, .stopBits = UART_STOP_BITS_1, .parity = UART_PARITY_NONE, .rxCallback = onSerial, .useEvent = false};
(i.e. rxCallback rather than useEvent) This seemed to prevent the clashing/corruption completely for me. The callback gets called with the buffer and size:
static void onSerial(UART_Callback_Param_t param) // { if ((param.length > 1) && param.buf) // Have some data
I tried to use rxCallback.
static void OnUart1ReceivedData(UART_Callback_Param_t param)
{
UART_Write(UART1,param.buf,param.length);
Trace(1,"uart1 interrupt received data,length:%d,read:,data:%s",param.length,param.buf);
}
UART_Config_t config = {
.baudRate = UART_BAUD_RATE_115200,
.dataBits = UART_DATA_BITS_8,
.stopBits = UART_STOP_BITS_1,
.parity = UART_PARITY_NONE,
.rxCallback = OnUart1ReceivedData,
.useEvent = false,
};
But the GPS NMEA data is still mixed to UART1 data. Now I fixed by stupid method, that is turn of gps when I receive the message that i want, then turn on when finish. But the LAT and LON is not good, the accuracy is very large. I hope I can resolve this case with the best method. I don't want to use another external GPS module.
um, yeah, see my comment in that earlier post!
(albeit you can't TRACE or make other uart calls from the callback)
For what you're doing copy the data somewhere and/or set a flag, then use it from your main loop.
Hi!
Here is my code for callback
static void OnUart1ReceivedData(UART_Callback_Param_t param)
{
uint8_t data[param.length+1];
int32_t ret;
RTC_Time_t time;
TIME_GetRtcTime(&time);
data[param.length] = 0;
memcpy(data,param.buf,param.length);
if(strstr(data,"start_create_image_file") != NULL)
{
start = true;
snprintf(filetestpath,sizeof(filetestpath),"/t/img%d%02d%02d%02d%02d%02d.txt",time.year,time.month,time.day,time.hour+time.timeZone,time.minute,time.second);
fd_imgtest = API_FS_Open(filetestpath, FS_O_RDWR | FS_O_CREAT, 0);
}
else if(strstr(data,"close_image_file") != NULL)
{
ret = API_FS_Close(fd_imgtest);
start = false;
if(ret == 0)
sendpic = 1;
}
else if (start == true)
{
ret = API_FS_Write(fd_imgtest, data, param.length);
}
}
```
UART_Config_t config = {
.baudRate = UART_BAUD_RATE_230400,
.dataBits = UART_DATA_BITS_8,
.stopBits = UART_STOP_BITS_1,
.parity = UART_PARITY_NONE,
.rxCallback = OnUart1ReceivedData,
.useEvent = false
};
UART_Init(UART1,config);
After upload lod file, the A9G is crashed. Pls see the picture below:
Pls help me. Thank you so much.