2024-09-02 03:26 PM
Hello board. I am attempting to implement an STM32F0 to receive data from a GPS module, a NEO-6M in this case, and then transmit it to an external LoRa module.
I am attempting to implement this by initializing a ring buffer and inserting information one character at a time via a UART global interrupt (code below).
To keep the ISR short, I set a flag and disable the ISR at the end of the call to allow the main function to process the data.
I then store the newly stored element in the ring buffer to a different "packet_buffer" in order to allow me to check if the NMEA sentence is correct, which I check for utilizing the minmea library from GitHub.
Here is the issue: Utilizing the current program, I'm--at best--able to get one correct transmission out to an external UART logger (which I'm using to debug the program). In most cases, however, I'm simply getting a "Bad Data" message, which tells me that the data I'm receiving into the buffer isn't high quality, or even passable at that.
The GPS module is getting a lock, so I'm at a bit of a mental-block as to what could be going on software-wise.
Thank you in advance.
#include "main.h"
#include "ChangeClockTo48Mhz.h"
#include "string.h"
#include "minmea.h"
#include "Ring_Buffer.h"
#define BUFFERSIZE 120
volatile uint8_t packet_buffer[BUFFERSIZE] = "\0";
volatile int Packet_Flag;
volatile int packet_index;
volatile int Buffer_Flag;
volatile uint8_t temp_hold;
char *newline;
//Pre-Defined Size of 256 in Header
ring_buffer rbuffer;
void TransmitChar(USART_TypeDef* USARTx, uint8_t ch);
void TransmitString(USART_TypeDef* USARTx, uint8_t * str);
void put_in_buffer(uint8_t entry);
int get_from_que(uint8_t *entry);
void Send_To_LoRa(USART_TypeDef* USARTx);
void SetupRegs(void);
int main(void)
{
HAL_Init();
ChangeInternalClockTo48MHZ();
SetupRegs();
NVIC_EnableIRQ(USART1_IRQn);
while (1)
{
if(Packet_Flag)
{
temp_hold = rbuffer_get(&rbuffer);
packet_buffer[packet_index++] = temp_hold;
if(packet_index >= BUFFERSIZE)
{
Buffer_Flag = 1;
packet_index = 0;
}
if(minmea_check(packet_buffer, true))
{
Send_To_LoRa(USART1);
packet_index = 0;
memset(packet_buffer, 0, strlen(packet_buffer));
}
else
{
TransmitString(USART1, "Bad Data\n");
packet_index = 0;
memset(packet_buffer, 0, strlen(packet_buffer));
}
Packet_Flag = 0;
__enable_irq();
}
}
}
void USART1_IRQHandler(void)
{
if(USART1->ISR & (USART_ISR_ORE | USART_ISR_PE))
{
USART1->ICR |= USART_ICR_ORECF;
}
if ((USART1->ISR & USART_ISR_RXNE))
{
// put_in_buffer(USART1->RDR);
rbuffer_put(&rbuffer, USART1->RDR);
Packet_Flag = 1;
__disable_irq();
}
}
void TransmitChar(USART_TypeDef* USARTx, uint8_t ch){
while(!(USARTx->ISR & USART_ISR_TXE));
USART1->TDR = ch;
}
void TransmitString(USART_TypeDef* USARTx, uint8_t* str){
while(*str != 0)
{
TransmitChar(USARTx, *str);
str++;
}
}
void Send_To_LoRa(USART_TypeDef* USARTx){
uint8_t AT_SEND_CMD[125] = "AT+SEND=1,100,";
//ERROR WITH 2nd Argument String
strcat(AT_SEND_CMD, packet_buffer);
TransmitString(USARTx, (uint8_t*) AT_SEND_CMD );
//TransmitString(USARTx, (uint8_t*) packet_buffer);
}
void SetupRegs(void){
RCC->AHBENR |= RCC_AHBENR_GPIOAEN;
//Mode Register
GPIOA->MODER &= ~(GPIO_MODER_MODER9_0 | GPIO_MODER_MODER10_0);
GPIOA->MODER |= (GPIO_MODER_MODER9_1 | GPIO_MODER_MODER10_1);
//Speed Register
GPIOA->OSPEEDR &= (GPIO_OSPEEDR_OSPEEDR9 | GPIO_OSPEEDR_OSPEEDR10);
//PUPDR Register (Pulled High)
GPIOA->PUPDR &= ~(GPIO_PUPDR_PUPDR9 | GPIO_PUPDR_PUPDR10);
GPIOA->PUPDR |= (GPIO_PUPDR_PUPDR9_0 | GPIO_PUPDR_PUPDR10_0);
//Type Register
GPIOA->OTYPER &= ~(GPIO_OTYPER_OT_9 | GPIO_OTYPER_OT_10);
//Set the Alternate Functions
GPIOA->AFR[1] &= ~(GPIO_AFRH_AFRH1 | GPIO_AFRH_AFRH2);
GPIOA->AFR[1] |= (1 << 4) | (1 << 8);
//Enable USART1
RCC->APB2ENR |= RCC_APB2ENR_USART1EN;
//Baud Rate and Oversampling
USART1->BRR = 0x1388;
USART1->CR1 &= ~USART_CR1_OVER8;
USART1->CR3 &= ~USART_CR3_ONEBIT;
//Setting Word Length
USART1->CR1 &= ~(USART_CR1_M);
//Disable Parity Bit
USART1->CR1 &= ~USART_CR1_PCE;
//Stop Bit
USART1->CR2 &= ~USART_CR2_STOP;
//Enable Transmission
USART1->CR1 |= USART_CR1_TE;
//Enable Receiving Interrupt
USART1->CR1 |= USART_CR1_RXNEIE;
USART1->CR1 |= USART_CR1_RE;
//Enable USART
USART1->CR1 |= USART_CR1_UE;
}
Here is the ring buffer header + src files
/*
* Ring_Buffer.c
*
* Created on: Sep 2, 2024
*
*/
#include "Ring_Buffer.h"
#include <stdint.h>
void rbuffer_initialize(ring_buffer *rbuffer){
rbuffer->read_index = 0;
rbuffer->write_index = 0;
}
void rbuffer_put(ring_buffer *rbuffer, uint8_t entry){
rbuffer->buffer[rbuffer->write_index++] = entry;
}
uint8_t rbuffer_get(ring_buffer *rbuffer)
{
return rbuffer->buffer[rbuffer->read_index++];
}
///Ring_Buffer.h
#ifndef RING_BUFFER_H_
#define RING_BUFFER_H_
#include <stdint.h>
typedef struct
{
uint8_t buffer[256];
volatile uint8_t write_index;
volatile uint8_t read_index;
}ring_buffer;
void rbuffer_initialize(ring_buffer *rbuffer);
void rbuffer_put(ring_buffer *rbuffer, uint8_t entry);
uint8_t rbuffer_get(ring_buffer *rbuffer);
#endif /*RING_BUFFER_H_ */
Solved! Go to Solution.
2024-09-02 03:42 PM
There's little value to using 8-bit indexes, it does the modulo 256, but not really efficient at a code level
Problem here looks to be that you don't check or protect the buffer from capacity issues, that the input/output can de-synchronize with the way you flag things.
2024-09-02 03:42 PM
There's little value to using 8-bit indexes, it does the modulo 256, but not really efficient at a code level
Problem here looks to be that you don't check or protect the buffer from capacity issues, that the input/output can de-synchronize with the way you flag things.
2024-09-02 03:45 PM
https://github.com/cturvey/RandomNinjaChef/blob/main/f746g_disco_gps.c
2024-09-02 05:28 PM - edited 2024-09-02 05:30 PM
So I've tried to implement a similar capacity protection element as in the code you sent in your other comment (including getting rid of the circular buffer), but I'm still getting now data.
The only way I'll get to my LoRa send command is if I remove the condition which checks for if the buffer has content.
So then I'm guessing that the data just never actually reaches my buffer somehow?
I've attached my updated ISR and main.
int main(void)
{
HAL_Init();
ChangeInternalClockTo48MHZ();
SetupRegs();
NVIC_EnableIRQ(USART1_IRQn);
while (1)
{
if(Transmission_Flag)
{
if(minmea_check(packet_buffer, true))
{
Send_To_LoRa(USART1);
memset(packet_buffer, 0, strlen(packet_buffer));
}
else
{
TransmitString(USART1, "Bad Data\n");
packet_index = 0;
memset(packet_buffer, 0, strlen(packet_buffer));
}
Transmission_Flag = 0;
}
}
}
void USART1_IRQHandler(void) //Sync and Queue NMEA Sentences
{
static char rx_buffer[BUFFERSIZE];
static int rx_index = 0;
if(USART1->ISR & (USART_ISR_ORE | USART_ISR_PE)) //Overrun Error
{
USART1->ICR |= USART_ICR_ORECF;
}
if ((USART1->ISR & USART_ISR_RXNE)) //Received Character?
{
char rx = (char)(USART1->RDR & 0xFF);
if ((rx =='\r') || (rx =='\n')) //CRF character?
{
if(rx_index != 0)
{
memcpy((void *)packet_buffer, rx_buffer, rx_index); //Copy to static line buffer from dynamic receive buffer
packet_buffer[rx_index] = 0;
Transmission_Flag = 1;
}
}
else
{
if((rx == '$') || (rx_index == BUFFERSIZE)) //If Resync or Overflow Occurs, Pull Back to Start
{
rx_index = 0;
}
rx_buffer[rx_index] = rx;
}
}
}
2024-09-03 01:31 PM
Never mind last comment. Simply forgot to increment rx_buffer index. Original answer is correct.