Reorganised GPS driver to allow for non-blocking acquisition of NMEA sentences

pull/87/head
Silvano Seva 2022-06-14 19:20:42 +02:00
rodzic 3cc5852ef3
commit 45d919f50f
6 zmienionych plików z 81 dodań i 48 usunięć

Wyświetl plik

@ -61,6 +61,6 @@ gps_t;
* if available, enabled and ready, decode NMEA sentences and update * if available, enabled and ready, decode NMEA sentences and update
* the radio state with the retrieved data. * the radio state with the retrieved data.
*/ */
void gps_taskFunc(char *line, int len); void gps_taskFunc(char *line);
#endif /* GPS_H */ #endif /* GPS_H */

Wyświetl plik

@ -36,6 +36,7 @@ extern "C" {
/** /**
* Initialise the GPS driver. * Initialise the GPS driver.
* This function does not turn on the GPS module. * This function does not turn on the GPS module.
*
* @param baud: baud rate of GPS serial interface. * @param baud: baud rate of GPS serial interface.
*/ */
void gps_init(const uint16_t baud); void gps_init(const uint16_t baud);
@ -58,19 +59,35 @@ void gps_disable();
/** /**
* Detect if a GPS module is present in the system, it can be called also * Detect if a GPS module is present in the system, it can be called also
* when driver is not initialised. * when driver is not initialised.
*
* @param timeout: timeout for GPS detection, in milliseconds. * @param timeout: timeout for GPS detection, in milliseconds.
* @return true if a GPS module is present, false otherwise. * @return true if a GPS module is present, false otherwise.
*/ */
bool gps_detect(uint16_t timeout); bool gps_detect(uint16_t timeout);
/** /**
* Read a NMEA sentence from the GPS module, blocking function. * Start the acquisition of a new NMEA sentence from the GPS module.
* The function returns immediately and acquisition is stopped when a complete
* sentence is received or maximum buffer length is reached.
*
* @param buf: buffer to which the NMEA sentence is written. * @param buf: buffer to which the NMEA sentence is written.
* @param maxLength: maximum writable length inside the buffer. * @param maxLength: maximum writable length inside the buffer.
* @return number of characters written in the buffer or -1 on error. * @return number of characters written in the buffer or -1 on error.
*/ */
int gps_getNmeaSentence(char *buf, const size_t maxLength); int gps_getNmeaSentence(char *buf, const size_t maxLength);
/**
* Check if a newly acquired NMEA sentence is available.
*
* @return true if a NMEA sentence has been read from the GPS.
*/
bool gps_nmeaSentenceReady();
/**
* Wait until a new NMEA sentence is ready, blocking the execution flow.
*/
void gps_waitForNmeaSentence();
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

Wyświetl plik

@ -30,10 +30,8 @@
/** /**
* This function parses a GPS NMEA sentence and updates radio state * This function parses a GPS NMEA sentence and updates radio state
*/ */
void gps_taskFunc(char *line, int len) void gps_taskFunc(char *line)
{ {
(void) len;
char nmea_id[3] = { 0 }; char nmea_id[3] = { 0 };
// Little mechanism to ensure that RTC is synced with GPS time only once. // Little mechanism to ensure that RTC is synced with GPS time only once.

Wyświetl plik

@ -242,14 +242,16 @@ void *gps_task(void *arg)
while(1) while(1)
{ {
int len = gps_getNmeaSentence(line, MINMEA_MAX_LENGTH*10); int status = gps_getNmeaSentence(line, MINMEA_MAX_LENGTH*10);
if(len != -1) gps_waitForNmeaSentence();
if(status != -1)
{ {
// Lock mutex and update internal state // Lock mutex and update internal state
pthread_mutex_lock(&state_mutex); pthread_mutex_lock(&state_mutex);
// GPS readout is blocking, no need to delay here // GPS readout is blocking, no need to delay here
gps_taskFunc(line, len); gps_taskFunc(line);
// Unlock state mutex // Unlock state mutex
pthread_mutex_unlock(&state_mutex); pthread_mutex_unlock(&state_mutex);

Wyświetl plik

@ -26,15 +26,14 @@
#include <miosix.h> #include <miosix.h>
#include <kernel/scheduler/scheduler.h> #include <kernel/scheduler/scheduler.h>
int8_t detectStatus = -1; static int8_t detectStatus = -1;
size_t bufPos = 0; static size_t bufPos = 0;
size_t maxPos = 0; static size_t maxPos = 0;
char *dataBuf; static char *dataBuf;
bool receiving = false; static bool receiving = false;
uint8_t status = 0;
using namespace miosix; using namespace miosix;
Thread *gpsWaiting = 0; static Thread *gpsWaiting = 0;
#ifdef PLATFORM_MD3x0 #ifdef PLATFORM_MD3x0
#define PORT USART3 #define PORT USART3
@ -74,7 +73,8 @@ void __attribute__((used)) GpsUsartImpl()
if((receiving == false) && (bufPos != 0)) if((receiving == false) && (bufPos != 0))
{ {
status = (bufPos < maxPos) ? 0x01 : 0x02; // NMEA sentence received, turn off serial port
PORT->CR1 &= ~USART_CR1_UE;
if(gpsWaiting) if(gpsWaiting)
{ {
@ -127,10 +127,8 @@ void gps_init(const uint16_t baud)
| USART_CR1_RXNEIE; | USART_CR1_RXNEIE;
#ifdef PLATFORM_MD3x0 #ifdef PLATFORM_MD3x0
NVIC_ClearPendingIRQ(USART3_IRQn);
NVIC_SetPriority(USART3_IRQn, 14); NVIC_SetPriority(USART3_IRQn, 14);
#else #else
NVIC_ClearPendingIRQ(USART1_IRQn);
NVIC_SetPriority(USART1_IRQn, 14); NVIC_SetPriority(USART1_IRQn, 14);
#endif #endif
} }
@ -149,7 +147,15 @@ void gps_terminate()
void gps_enable() void gps_enable()
{ {
gpio_setPin(GPS_EN); gpio_setPin(GPS_EN);
PORT->CR1 |= USART_CR1_UE;
// Enable IRQ
#ifdef PLATFORM_MD3x0
NVIC_ClearPendingIRQ(USART3_IRQn);
NVIC_EnableIRQ(USART3_IRQn);
#else
NVIC_ClearPendingIRQ(USART1_IRQn);
NVIC_EnableIRQ(USART1_IRQn);
#endif
} }
void gps_disable() void gps_disable()
@ -162,6 +168,9 @@ void gps_disable()
#else #else
NVIC_DisableIRQ(USART1_IRQn); NVIC_DisableIRQ(USART1_IRQn);
#endif #endif
receiving = false;
bufPos = 0;
} }
bool gps_detect(uint16_t timeout) bool gps_detect(uint16_t timeout)
@ -199,16 +208,23 @@ int gps_getNmeaSentence(char *buf, const size_t maxLength)
if(detectStatus != 1) return -1; if(detectStatus != 1) return -1;
memset(buf, 0x00, maxLength); memset(buf, 0x00, maxLength);
bufPos = 0; bufPos = 0;
maxPos = maxLength; maxPos = maxLength;
dataBuf = buf; dataBuf = buf;
#ifdef PLATFORM_MD3x0 // Enable serial port
NVIC_EnableIRQ(USART3_IRQn); PORT->CR1 |= USART_CR1_UE;
#else
NVIC_EnableIRQ(USART1_IRQn);
#endif
return 0;
}
bool gps_nmeaSentenceReady()
{
return (receiving == false) && (bufPos > 0);
}
void gps_waitForNmeaSentence()
{
/* /*
* Put the calling thread in waiting status until a complete sentence is ready. * Put the calling thread in waiting status until a complete sentence is ready.
*/ */
@ -222,20 +238,7 @@ int gps_getNmeaSentence(char *buf, const size_t maxLength)
FastInterruptEnableLock eLock(dLock); FastInterruptEnableLock eLock(dLock);
Thread::yield(); Thread::yield();
} }
} while(gpsWaiting); }
while(gpsWaiting);
} }
#ifdef PLATFORM_MD3x0
NVIC_DisableIRQ(USART3_IRQn);
#else
NVIC_DisableIRQ(USART1_IRQn);
#endif
if(status & 0x01)
{
return bufPos;
}
return -1;
} }

Wyświetl plik

@ -26,7 +26,8 @@
#define MAX_NMEA_LEN 80 #define MAX_NMEA_LEN 80
#define NMEA_SAMPLES 8 #define NMEA_SAMPLES 8
char test_nmea_sentences [NMEA_SAMPLES][MAX_NMEA_LEN] = { char test_nmea_sentences [NMEA_SAMPLES][MAX_NMEA_LEN] =
{
"$GPGGA,223659.522,5333.735,N,00959.130,E,1,12,1.0,0.0,M,0.0,M,,*62", "$GPGGA,223659.522,5333.735,N,00959.130,E,1,12,1.0,0.0,M,0.0,M,,*62",
"$GPGSA,A,3,01,02,03,04,05,06,07,08,09,10,11,12,1.0,1.0,1.0*30", "$GPGSA,A,3,01,02,03,04,05,06,07,08,09,10,11,12,1.0,1.0,1.0*30",
"$GPGSV,3,1,12,30,79,066,27,05,63,275,21,07,42,056,,13,40,289,13*76", "$GPGSV,3,1,12,30,79,066,27,05,63,275,21,07,42,056,,13,40,289,13*76",
@ -36,28 +37,30 @@ char test_nmea_sentences [NMEA_SAMPLES][MAX_NMEA_LEN] = {
"$GPVTG,92.15,T,,M,0.15,N,0.28,K,A*0C" "$GPVTG,92.15,T,,M,0.15,N,0.28,K,A*0C"
}; };
void gps_init(__attribute__((unused)) const uint16_t baud) void gps_init(const uint16_t baud)
{ {
; (void) baud;
return;
} }
void gps_terminate() void gps_terminate()
{ {
; return;
} }
void gps_enable() void gps_enable()
{ {
; return;
} }
void gps_disable() void gps_disable()
{ {
; return;
} }
bool gps_detect(__attribute__((unused)) uint16_t timeout) bool gps_detect(uint16_t timeout)
{ {
(void) timeout;
return true; return true;
} }
@ -77,3 +80,13 @@ int gps_getNmeaSentence(char *buf, const size_t maxLength)
return len; return len;
} }
bool gps_nmeaSentenceReady()
{
return true;
}
void gps_waitForNmeaSentence()
{
return;
}