Mongoose_Arduino_RadioHead/src/STM32ArduinoCompat/HardwareSerial.cpp

350 lines
10 KiB
C++

// ArduinoCompat/HardwareSerial.cpp
//
// Author: mikem@airspayce.com
#include <RadioHead.h>
#if (RH_PLATFORM == RH_PLATFORM_STM32STD)
#include <HardwareSerial.h>
#include <stm32f4xx_usart.h>
// Preinstantiated Serial objects
HardwareSerial Serial1(USART1);
HardwareSerial Serial2(USART2);
HardwareSerial Serial3(USART3);
HardwareSerial Serial4(UART4);
HardwareSerial Serial5(UART5);
HardwareSerial Serial6(USART6);
///////////////////////////////////////////////////////////////
// RingBuffer
///////////////////////////////////////////////////////////////
RingBuffer::RingBuffer()
: _head(0),
_tail(0),
_overruns(0),
_underruns(0)
{
}
bool RingBuffer::isEmpty()
{
return _head == _tail;
}
bool RingBuffer::isFull()
{
return ((_head + 1) % ARDUINO_RINGBUFFER_SIZE) == _tail;
}
bool RingBuffer::write(uint8_t ch)
{
if (isFull())
{
_overruns++;
return false;
}
_buffer[_head] = ch;
if (++_head >= ARDUINO_RINGBUFFER_SIZE)
_head = 0;
return true;
}
uint8_t RingBuffer::read()
{
if (isEmpty())
{
_underruns++;
return 0; // What else can we do?
}
uint8_t ret = _buffer[_tail];
if (++_tail >= ARDUINO_RINGBUFFER_SIZE)
_tail = 0;
return ret;
}
///////////////////////////////////////////////////////////////
// HardwareSerial
///////////////////////////////////////////////////////////////
// On STM32F4 Discovery, USART 1 is not very useful conflicts with the Green lED
HardwareSerial::HardwareSerial(USART_TypeDef* usart)
: _usart(usart)
{
}
void HardwareSerial::begin(unsigned long baud)
{
USART_InitTypeDef USART_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure_TX;
GPIO_InitTypeDef GPIO_InitStructure_RX;
// Common GPIO structure init:
GPIO_InitStructure_TX.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure_TX.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure_TX.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure_TX.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_InitStructure_RX.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure_RX.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure_RX.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure_RX.GPIO_PuPd = GPIO_PuPd_UP;
// CTS or SCLK outputs are not supported.
USART_InitStructure.USART_BaudRate = baud * 25/8; // Why?
// Only 8N1 is currently supported
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
// Different for each USART:
if (_usart == USART1)
{
// Initialise the clocks for this USART and its RX, TX pins port
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_USART1);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_USART1);
GPIO_InitStructure_TX.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure_RX.GPIO_Pin = GPIO_Pin_10;
GPIO_Init(GPIOA, &GPIO_InitStructure_TX);
GPIO_Init(GPIOA, &GPIO_InitStructure_RX);
// Initialise the USART
USART_Init(USART1, &USART_InitStructure);
// Enable the RXNE interrupt
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
// Enable global interrupt
NVIC_EnableIRQ(USART1_IRQn);
}
else if (_usart == USART2)
{
// Initialise the clocks for this USART and its RX, TX pins port
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_USART2);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource3, GPIO_AF_USART2);
GPIO_InitStructure_TX.GPIO_Pin = GPIO_Pin_2;
GPIO_InitStructure_RX.GPIO_Pin = GPIO_Pin_3;
GPIO_Init(GPIOA, &GPIO_InitStructure_TX);
GPIO_Init(GPIOA, &GPIO_InitStructure_RX);
// Initialise the USART
USART_Init(USART2, &USART_InitStructure);
// Enable the RXNE interrupt
USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);
// Enable global interrupt
NVIC_EnableIRQ(USART2_IRQn);
}
else if (_usart == USART3)
{
// Initialise the clocks for this USART and its RX, TX pins port
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);
GPIO_PinAFConfig(GPIOD, GPIO_PinSource8, GPIO_AF_USART3);
GPIO_PinAFConfig(GPIOD, GPIO_PinSource9, GPIO_AF_USART3);
GPIO_InitStructure_TX.GPIO_Pin = GPIO_Pin_8;
GPIO_InitStructure_RX.GPIO_Pin = GPIO_Pin_9;
GPIO_Init(GPIOD, &GPIO_InitStructure_TX);
GPIO_Init(GPIOD, &GPIO_InitStructure_RX);
// Initialise the USART
USART_Init(USART3, &USART_InitStructure);
// Enable the RXNE interrupt
USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);
// Enable global interrupt
NVIC_EnableIRQ(USART3_IRQn);
}
else if (_usart == UART4)
{
// Initialise the clocks for this USART and its RX, TX pins port
RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART4, ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource0, GPIO_AF_UART4);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource1, GPIO_AF_UART4);
GPIO_InitStructure_TX.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure_RX.GPIO_Pin = GPIO_Pin_1;
GPIO_Init(GPIOA, &GPIO_InitStructure_TX);
GPIO_Init(GPIOA, &GPIO_InitStructure_RX);
// Initialise the USART
USART_Init(UART4, &USART_InitStructure);
// Enable the RXNE interrupt
USART_ITConfig(UART4, USART_IT_RXNE, ENABLE);
// Enable global interrupt
NVIC_EnableIRQ(UART4_IRQn);
}
else if (_usart == UART5)
{
// Initialise the clocks for this USART and its RX, TX pins port
RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART5, ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOD, ENABLE);
GPIO_PinAFConfig(GPIOC, GPIO_PinSource12, GPIO_AF_UART5);
GPIO_PinAFConfig(GPIOD, GPIO_PinSource2, GPIO_AF_UART5);
GPIO_InitStructure_TX.GPIO_Pin = GPIO_Pin_12;
GPIO_InitStructure_RX.GPIO_Pin = GPIO_Pin_2;
GPIO_Init(GPIOC, &GPIO_InitStructure_TX);
GPIO_Init(GPIOD, &GPIO_InitStructure_RX);
// Initialise the USART
USART_Init(UART5, &USART_InitStructure);
// Enable the RXNE interrupt
USART_ITConfig(UART5, USART_IT_RXNE, ENABLE);
// Enable global interrupt
NVIC_EnableIRQ(UART5_IRQn);
}
else if (_usart == USART6)
{
// Initialise the clocks for this USART and its RX, TX pins port
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART6, ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);
GPIO_PinAFConfig(GPIOC, GPIO_PinSource6, GPIO_AF_USART6);
GPIO_PinAFConfig(GPIOC, GPIO_PinSource7, GPIO_AF_USART6);
GPIO_InitStructure_TX.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStructure_RX.GPIO_Pin = GPIO_Pin_7;
GPIO_Init(GPIOC, &GPIO_InitStructure_TX);
GPIO_Init(GPIOC, &GPIO_InitStructure_RX);
// Initialise the USART
USART_Init(USART6, &USART_InitStructure);
// Enable the RXNE interrupt
USART_ITConfig(USART6, USART_IT_RXNE, ENABLE);
// Enable global interrupt
NVIC_EnableIRQ(USART6_IRQn);
}
USART_Cmd(_usart, ENABLE);
}
void HardwareSerial::end()
{
USART_Cmd(_usart, DISABLE);
USART_DeInit(_usart);
}
int HardwareSerial::available(void)
{
return !_rxRingBuffer.isEmpty();
}
int HardwareSerial::read(void)
{
return _rxRingBuffer.read();
}
size_t HardwareSerial::write(uint8_t ch)
{
_txRingBuffer.write(ch); // Queue it
USART_ITConfig(_usart, USART_IT_TXE, ENABLE); // Enable the TX interrupt
return 1;
}
extern "C"
{
void USART1_IRQHandler(void)
{
if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
{
Serial1._rxRingBuffer.write(USART_ReceiveData(USART1));
}
if (USART_GetITStatus(USART1, USART_IT_TXE) != RESET)
{
// Transmitter is empty, maybe send another char?
if (Serial1._txRingBuffer.isEmpty())
USART_ITConfig(USART1, USART_IT_TXE, DISABLE); // No more to send, disable the TX interrupt
else
USART_SendData(USART1, Serial1._txRingBuffer.read());
}
}
void USART2_IRQHandler(void)
{
if (USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)
{
// Newly received char, try to put it in our rx buffer
Serial2._rxRingBuffer.write(USART_ReceiveData(USART2));
}
if (USART_GetITStatus(USART2, USART_IT_TXE) != RESET)
{
// Transmitter is empty, maybe send another char?
if (Serial2._txRingBuffer.isEmpty())
USART_ITConfig(USART2, USART_IT_TXE, DISABLE); // No more to send, disable the TX interrupt
else
USART_SendData(USART2, Serial2._txRingBuffer.read());
}
}
void USART3_IRQHandler(void)
{
if (USART_GetITStatus(USART3, USART_IT_RXNE) != RESET)
{
// Newly received char, try to put it in our rx buffer
Serial3._rxRingBuffer.write(USART_ReceiveData(USART3));
}
if (USART_GetITStatus(USART3, USART_IT_TXE) != RESET)
{
// Transmitter is empty, maybe send another char?
if (Serial3._txRingBuffer.isEmpty())
USART_ITConfig(USART3, USART_IT_TXE, DISABLE); // No more to send, disable the TX interrupt
else
USART_SendData(USART3, Serial3._txRingBuffer.read());
}
}
void UART4_IRQHandler(void)
{
if (USART_GetITStatus(UART4, USART_IT_RXNE) != RESET)
{
// Newly received char, try to put it in our rx buffer
Serial4._rxRingBuffer.write(USART_ReceiveData(UART4));
}
if (USART_GetITStatus(UART4, USART_IT_TXE) != RESET)
{
// Transmitter is empty, maybe send another char?
if (Serial4._txRingBuffer.isEmpty())
USART_ITConfig(UART4, USART_IT_TXE, DISABLE); // No more to send, disable the TX interrupt
else
USART_SendData(UART4, Serial4._txRingBuffer.read());
}
}
void UART5_IRQHandler(void)
{
if (USART_GetITStatus(UART5, USART_IT_RXNE) != RESET)
{
// Newly received char, try to put it in our rx buffer
Serial5._rxRingBuffer.write(USART_ReceiveData(UART5));
}
if (USART_GetITStatus(UART5, USART_IT_TXE) != RESET)
{
// Transmitter is empty, maybe send another char?
if (Serial5._txRingBuffer.isEmpty())
USART_ITConfig(UART5, USART_IT_TXE, DISABLE); // No more to send, disable the TX interrupt
else
USART_SendData(UART5, Serial5._txRingBuffer.read());
}
}
void USART6_IRQHandler(void)
{
if (USART_GetITStatus(USART6, USART_IT_RXNE) != RESET)
{
// Newly received char, try to put it in our rx buffer
Serial6._rxRingBuffer.write(USART_ReceiveData(USART6));
}
if (USART_GetITStatus(USART6, USART_IT_TXE) != RESET)
{
// Transmitter is empty, maybe send another char?
if (Serial6._txRingBuffer.isEmpty())
USART_ITConfig(USART6, USART_IT_TXE, DISABLE); // No more to send, disable the TX interrupt
else
USART_SendData(USART6, Serial6._txRingBuffer.read());
}
}
}
#endif