cancel
Showing results for 
Search instead for 
Did you mean: 

Serial data from GPS to Bluetooth via STM32F103

michele77
Associate II
Posted on February 09, 2012 at 11:18

Hi all,

I am looking for suggestions on how to design the data forwarding between a GPS receiver and a BT transceiver. It is a 

https://picasaweb.google.com/111166516525827756469/Rappen10LogBt&sharp5705024027986934322

 where I have no flow-control available.

The first version I implemented does a pure data forwarding from GPS to BT (there is no parser of what comes from the GPS or BT yet) by simply polling on RXNE on USART3 (GPS) and TXE on USART1 (BT). It works well when the data rate is well below 115200bps but fails (it locks, I suspect it overruns) when the data rate goes higher.

As a matter of fact, the polling example of the STM default peripheral library is done at 9600bps. So does the interrupt example.

Did anyone experience similar behaviour when processing high (>115200) data rates from USARTs?

Should I look at DMA to transfer quickly from one USART to another? Peripheral to peripheral or passing through memory, especially thinking that I will need parsing the GPS data at some point soon?

Best regards,

Michele

#stm32
4 REPLIES 4
Posted on February 09, 2012 at 19:44

Forwarding full-duplex between two USARTs at 115200 is achievable without DMA, using some simple FIFO buffering. It could probably go much faster, my application didn't require that.

DMA on the STM32 does not lending itself to the mechanism you want. Rx DMA is probably more grief than you need. Tx DMA could certainly off-load work, and reduce the 1 interrupt per byte loading. Larger run-lengths will however come with higher latency.

The USARTs on the STM32 are also pretty simplistic implementations, and could have done with some hardware FIFOs.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
michele77
Associate II
Posted on February 10, 2012 at 09:35

Clive1, thank you very much for the valuable feedback... so in your opinion a loop like this:

while
(1) {
if
(RdyToRecFromGps()) {
if
(!IsFullFifo(&fGpsBt)) {
PushToFifo(&fGpsBt, RecvFromGps() & 0xFF);
}
}
if
(!IsEmptyFifo(&fGpsBt)) {
SendToBt(PopFromFifo(&fGpsBt));
while
(!DoneSendToBt());
}
if
(RdyToRecFromBt()) {
if
(!IsFullFifo(&fBtGps)) {
PushToFifo(&fBtGps, RecvFromBt() & 0xFF);
}
}
if
(!IsEmptyFifo(&fBtGps)) {
SendToGps(PopFromFifo(&fBtGps));
while
(!DoneSendToGps());
}
}

where the functions are defined as

FlagStatus RdyToRecFromGps( 
void
) {
return
(USART_GetFlagStatus(GPSUSART_PORT, USART_FLAG_RXNE) != RESET);
}
uint16_t RecvFromGps( 
void
) {
return
USART_ReceiveData(GPSUSART_PORT);
}
FlagStatus DoneSendToGps( 
void
) {
return
(USART_GetFlagStatus(GPSUSART_PORT, USART_FLAG_TXE) != RESET);
}
void
SendToGps(uint16_t _uiData) {
USART_SendData(GPSUSART_PORT, _uiData);
}
FlagStatus RdyToRecFromBt( 
void
) {
return
(USART_GetFlagStatus(BTUART_PORT, USART_FLAG_RXNE) != RESET);
}
uint16_t RecvFromBt( 
void
) {
return
USART_ReceiveData(BTUART_PORT);
}
FlagStatus DoneSendToBt( 
void
) {
return
(USART_GetFlagStatus(BTUART_PORT, USART_FLAG_TXE) != RESET);
}
void
SendToBt(uint16_t _uiData) {
USART_SendData(BTUART_PORT, _uiData);
}

and the FIFO interface looks like this:

int
IsEmptyFifo(fifobuff_t *_pBuff) {
if
((_pBuff->iCount) <= 0) 
return
1;
return
0;
}
int
IsFullFifo(fifobuff_t *_pBuff) {
if
((_pBuff->iCount) >= FIFOBUFF_SIZE) 
return
1;
return
0;
}
void
PushToFifo(fifobuff_t *_pBuff, 
char
_cVal) {
int
iIdx = ((_pBuff->iBeginIdx) + (_pBuff->iCount)) % FIFOBUFF_SIZE;
if
((_pBuff->iCount) >= FIFOBUFF_SIZE) 
return
;
_pBuff->pMem[iIdx] = _cVal;
_pBuff->iCount++;
}
char
PopFromFifo(fifobuff_t *_pBuff) {
char
cVal = _pBuff->pMem[(_pBuff->iBeginIdx)];
if
((_pBuff->iCount) <= 0) 
return
0;
_pBuff->pMem[(_pBuff->iBeginIdx)] = 0;
_pBuff->iBeginIdx = (_pBuff->iBeginIdx + 1) % FIFOBUFF_SIZE;
_pBuff->iCount--;
return
cVal;
}

Should never hang up and if it does it is because of something else? Would you have any suggestions on how to make this all more efficient/robust? Cheers, Michele
Posted on February 10, 2012 at 15:33

Spin loops within the loop is bad, it's basically going to hang up and prevent the FIFO from being elastic.

while(1) {
if (RdyToRecFromGps()) {
if (!IsFullFifo(&fGpsBt)) {
PushToFifo(&fGpsBt, RecvFromGps() & 0xFF);
}
}
if (DoneSendToBt() && !IsEmptyFifo(&fGpsBt)) {
SendToBt(PopFromFifo(&fGpsBt));
}
if (RdyToRecFromBt()) {
if (!IsFullFifo(&fBtGps)) {
PushToFifo(&fBtGps, RecvFromBt() & 0xFF);
}
}
if (DoneSendToGps() && !IsEmptyFifo(&fBtGps)) {
SendToGps(PopFromFifo(&fBtGps));
}
}

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
michele77
Associate II
Posted on February 13, 2012 at 10:22

Dear Clive1,

Thanks again for the valuable suggestion.

In the weekend I followed your technique for another board where the GPS is connected to Xbee and spent half day to understand that the problem was the embarrassingly slow speed of Xbees (much lower than 115200) rather than the USARTs on STM32.

On the board with Bluetooth everything works well now.

I also managed to re-flash my STM32F103xB using Xbee/Bluetooth (at 9600bps, 8E1) connected to USART1, the STM32 embedded bootloader, and the ST flash utility 

http://www.st.com/internet/com/SOFTWARE_RESOURCES/SW_COMPONENT/SW_DEMO/um0462.zip

.  

All the best,

Michele

P.S.: I guess a simple bootloader with USB exposing the STM32 flash as a mass storage device (or even a virtual serial port) if USB is connected at start-up would be nice, but I have not found any such firmware from the community or STM yet.