diff --git a/Core/Src/main.c b/Core/Src/main.c index d604566..62d12fb 100644 --- a/Core/Src/main.c +++ b/Core/Src/main.c @@ -24,6 +24,7 @@ #include "printf.h" #include #include +#include "usart1_it.h" /* USER CODE END Includes */ /* Private typedef -----------------------------------------------------------*/ @@ -111,6 +112,7 @@ int main(void) { Usart2_Init(); Usart6_Init(); + Usart1_Init(); init_printf(NULL, &uart_putc);// connect printf to UART printf("Hello world. This is a Nucleo UART and printf sample with IRQ and ring buffer.\n"); /* USER CODE END 2 */ diff --git a/Core/user/usart1_it.c b/Core/user/usart1_it.c new file mode 100644 index 0000000..060f4c4 --- /dev/null +++ b/Core/user/usart1_it.c @@ -0,0 +1,141 @@ +/***************************************************************************//** +* @file usart1_it.c +* @brief UART with interrupt and ring buffer (USART1) +*//****************************************************************************/ + +#include "stm32f4xx_hal.h" +//------------------------------C library--------------------------------------- +#include +//----------------------------user includes------------------------------------- +#include "usart1_it.h" +#include "usart1_it_cfg.h" +//------------------------------------------------------------------------------ + + + + +/* Private typedefs ----------------------------------------------------------*/ + +/* Private macros ------------------------------------------------------------*/ + +//====== UART buffer defines =================================================== +#define USART1_RXBUF_MASK (USART1_RXBUF_SIZE - 1) +#define USART1_TXBUF_MASK (USART1_TXBUF_SIZE - 1) + +#if ( USART1_RXBUF_SIZE & USART1_RXBUF_MASK ) +#error RX buffer size is not a power of 2! +#endif + +#if ( USART1_TXBUF_SIZE & USART1_TXBUF_MASK ) +#error TX buffer size is not a power of 2! +#endif + + +/* Private variables ---------------------------------------------------------*/ + +//====== Variables for transmitter ============================================= +static uint8_t Usart1TxBuf[USART1_TXBUF_SIZE]; +static uint16_t Usart1TxWrIdx = 0; +static volatile uint16_t Usart1TxRdIdx = 0; + +//====== Variables for Receiver ================================================ +static uint8_t Usart1RxBuf[USART1_RXBUF_SIZE]; +static volatile uint16_t Usart1RxWrIdx = 0; +static volatile uint16_t Usart1RxRdIdx = 0; + + +/* Public variables ----------------------------------------------------------*/ + + +/* Functions -----------------------------------------------------------------*/ + + +/***************************************************************************//** +* @brief USART1 init +*//****************************************************************************/ +void Usart1_Init(void) { + USART1->CR1 |= USART_CR1_RXNEIE; // Enable RX interrupt +} + + +/***************************************************************************//** +* @brief USART1 interrupt handler +*//****************************************************************************/ +void USART1_IRQHandler(void) { + uint32_t statusreg = USART1->SR; // read interrupt flags + + if ((statusreg & USART_SR_RXNE)) { // RX interrupt + uint8_t d = USART1->DR; // read received byte + uint_fast16_t wr = Usart1RxWrIdx; + wr = (wr + 1) & USART1_RXBUF_MASK; // new write index + Usart1RxBuf[wr] = d; // received data to buffer + Usart1RxWrIdx = wr; // Store new index + } + + if ((statusreg & USART_SR_TXE)) { // TX interrupt + uint_fast16_t rd = Usart1TxRdIdx; + uint_fast16_t wr = Usart1TxWrIdx; + if (wr != rd) { // data in buffer + rd = (rd + 1) & USART1_TXBUF_MASK; // new read index + USART1->DR = Usart1TxBuf[rd]; // send data byte + Usart1TxRdIdx = rd; // Store new index + } + if (wr == rd) { // data buffer empty + USART1->CR1 &= ~USART_CR1_TXEIE; // INT disable + } + } +} + + +/***************************************************************************//** +* @brief Send byte to UART +* @param d: byte to send +*//****************************************************************************/ +void Usart1_PutByte(uint8_t d) { + uint_fast16_t wr = Usart1TxWrIdx; + wr = (wr + 1) & USART1_TXBUF_MASK; // new write index + if (wr == Usart1TxRdIdx) { // No free space in buffer (overflow) + return; // drop remaining data (Attention! Buffer overflow not signaled! Use bigger buffer) + } + Usart1TxBuf[wr] = d; // Store data in buffer + Usart1TxWrIdx = wr; // Store new index + USART1->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 Usart1_PutData (void* src, uint16_t n) { + uint8_t* p = src; + uint_fast16_t wr = Usart1TxWrIdx; + while (n) { + wr = (wr + 1) & USART1_TXBUF_MASK; // new write index + if (wr == Usart1TxRdIdx) { // No free space in buffer (overflow) + break; // drop remaining data (Attention! Buffer overflow not signaled! Use bigger buffer) + } + Usart1TxBuf[wr] = *p; // Store data in buffer + p++; + n--; + } + Usart1TxWrIdx = wr; // Store new index + USART1->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 Usart1_GetByte(void) { + uint_fast16_t rd = Usart1RxRdIdx; + if (rd != Usart1RxWrIdx) { // new data in buffer + rd = (rd + 1) & USART1_RXBUF_MASK; // new read index + Usart1RxRdIdx = rd; // store new index + return Usart1RxBuf[rd]; // return with data + }else { + return -1; // buffer empty + } +} + diff --git a/Core/user/usart1_it.h b/Core/user/usart1_it.h new file mode 100644 index 0000000..47d02a2 --- /dev/null +++ b/Core/user/usart1_it.h @@ -0,0 +1,13 @@ +// filepath: c:\projects\STM32CubeIDE\GNSS_Nucleo\Core\user\usart1_it.h +#ifndef __USART1_IT_H__ +#define __USART1_IT_H__ + +#include + +extern void Usart1_Init(void); +extern void Usart1_PutByte(uint8_t d); +extern void Usart1_PutData(void* src, uint16_t n); +extern int16_t Usart1_GetByte(void); + + +#endif diff --git a/Core/user/usart1_it_cfg.h b/Core/user/usart1_it_cfg.h new file mode 100644 index 0000000..4bd5715 --- /dev/null +++ b/Core/user/usart1_it_cfg.h @@ -0,0 +1,8 @@ +// filepath: c:\projects\STM32CubeIDE\GNSS_Nucleo\Core\user\usart1_it_cfg.h +#ifndef __USART1_IT_CFG_H__ +#define __USART1_IT_CFG_H__ + +#define USART1_RXBUF_SIZE 1024 +#define USART1_TXBUF_SIZE 1024 + +#endif // __USART1_IT_CFG_H__