You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

142 lines
5.6 KiB
C

/***************************************************************************//**
* @file usart6_it.c
* @brief UART with interrupt and ring buffer
*//****************************************************************************/
#include "stm32f4xx_hal.h"
//------------------------------C library---------------------------------------
#include <stdlib.h>
//----------------------------user includes-------------------------------------
#include "usart6_it.h"
#include "usart6_it_cfg.h"
//------------------------------------------------------------------------------
/* Private typedefs ----------------------------------------------------------*/
/* Private macros ------------------------------------------------------------*/
//====== UART buffer defines ===================================================
#define USART6_RXBUF_MASK (USART6_RXBUF_SIZE - 1)
#define USART6_TXBUF_MASK (USART6_TXBUF_SIZE - 1)
#if ( USART6_RXBUF_SIZE & USART6_RXBUF_MASK )
#error RX buffer size is not a power of 2!
#endif
#if ( USART6_TXBUF_SIZE & USART6_TXBUF_MASK )
#error TX buffer size is not a power of 2!
#endif
/* Private variables ---------------------------------------------------------*/
//====== Variables for transmitter =============================================
static uint8_t Usart6TxBuf[USART6_TXBUF_SIZE];
static uint16_t Usart6TxWrIdx = 0;
static volatile uint16_t Usart6TxRdIdx = 0;
//====== Variables for Receiver ================================================
static uint8_t Usart6RxBuf[USART6_RXBUF_SIZE];
static volatile uint16_t Usart6RxWrIdx = 0;
static volatile uint16_t Usart6RxRdIdx = 0;
/* Public variables ----------------------------------------------------------*/
/* Functions -----------------------------------------------------------------*/
/***************************************************************************//**
* @brief USART6 init
*//****************************************************************************/
void Usart6_Init(void) {
USART6->CR1 |= USART_CR1_RXNEIE; // Enable RX interrupt
}
/***************************************************************************//**
* @brief USART6 interrupt handler
*//****************************************************************************/
void USART6_IRQHandler(void) {
uint32_t statusreg = USART6->SR; // read interrupt flags
if ((statusreg & USART_SR_RXNE)) { // RX interrupt
uint8_t d = USART6->DR; // read received byte
uint_fast16_t wr = Usart6RxWrIdx;
wr = (wr + 1) & USART6_RXBUF_MASK; // new write index
Usart6RxBuf[wr] = d; // received data to buffer
Usart6RxWrIdx = wr; // Store new index
}
if ((statusreg & USART_SR_TXE)) { // TX interrupt
uint_fast16_t rd = Usart6TxRdIdx;
uint_fast16_t wr = Usart6TxWrIdx;
if (wr != rd) { // data in buffer
rd = (rd + 1) & USART6_TXBUF_MASK; // new read index
USART6->DR = Usart6TxBuf[rd]; // send data byte
Usart6TxRdIdx = rd; // Store new index
if (wr == rd) { // data buffer empty
USART6->CR1 &= ~USART_CR1_TXEIE; // INT disable
}
}
}
}
/***************************************************************************//**
* @brief Send byte to UART
* @param d: byte to send
*//****************************************************************************/
void Usart6_PutByte(uint8_t d) {
uint_fast16_t wr = Usart6TxWrIdx;
wr = (wr + 1) & USART6_TXBUF_MASK; // new write index
if (wr == Usart6TxRdIdx) { // No free space in buffer (overflow)
return; // drop remaining data (Attention! Buffer overflow not signaled! Use bigger buffer)
}
Usart6TxBuf[wr] = d; // Store data in buffer
Usart6TxWrIdx = wr; // Store new index
USART6->CR1 |= USART_CR1_TXEIE; // Interrupt enable (start send)
}
/***************************************************************************//**
* @brief Send more data to UART
* @param src: data to send
* @param n: count of data
*//****************************************************************************/
void Usart6_PutData (void* src, uint16_t n) {
uint8_t* p = src;
uint_fast16_t wr = Usart6TxWrIdx;
while (n) {
wr = (wr + 1) & USART6_TXBUF_MASK; // new write index
if (wr == Usart6TxRdIdx) { // No free space in buffer (overflow)
break; // drop remaining data (Attention! Buffer overflow not signaled! Use bigger buffer)
}
Usart6TxBuf[wr] = *p; // Store data in buffer
p++;
n--;
}
Usart6TxWrIdx = wr; // Store new index
USART6->CR1 |= USART_CR1_TXEIE; // Interrupt enable (start send)
}
/***************************************************************************//**
* @brief Read data from UART RX buffer
* @return received character, -1: no data in RX buffer
*//****************************************************************************/
int16_t Usart6_GetByte(void) {
uint_fast16_t rd = Usart6RxRdIdx;
if (rd != Usart6RxWrIdx) { // new data in buffer
rd = (rd + 1) & USART6_RXBUF_MASK; // new read index
Usart6RxRdIdx = rd; // store new index
return Usart6RxBuf[rd]; // return with data
}else {
return -1; // buffer empty
}
}