diff options
author | Oxore <oxore@protonmail.com> | 2023-03-09 01:42:59 +0300 |
---|---|---|
committer | Oxore <oxore@protonmail.com> | 2023-03-09 01:42:59 +0300 |
commit | 34746d3783af1ae601487c88f0a7e44f81842618 (patch) | |
tree | 508a849e81e1f7a83e1df053719579e4452b4e35 | |
parent | 8370de05bb807f02c0077ba59c68053b283671e2 (diff) |
Impl UART buffering (still not tested)
-rw-r--r-- | CMakeLists.txt | 6 | ||||
-rw-r--r-- | app/main.c | 128 | ||||
-rw-r--r-- | app/platform/platform.h | 13 | ||||
-rw-r--r-- | app/platform/stm32f0-gcc/interrupts.cpp | 12 | ||||
-rw-r--r-- | app/platform/stm32f0-gcc/platform.cpp | 140 | ||||
-rw-r--r-- | app/platform/stm32f0-gcc/retarget.cpp | 18 | ||||
-rw-r--r-- | app/platform/stm32f0-gcc/retarget.h | 4 | ||||
-rw-r--r-- | app/platform/stm32f0-gcc/ring_buffer.cpp | 0 | ||||
-rw-r--r-- | app/platform/stm32f0-gcc/ring_buffer.h | 50 | ||||
-rw-r--r-- | app/platform/stm32f0-gcc/uart.cpp | 121 | ||||
-rw-r--r-- | app/platform/stm32f0-gcc/uart.h | 25 | ||||
-rw-r--r-- | third_party/CMSIS/Device/Include/system_stm32f0xx.h | 2 |
12 files changed, 366 insertions, 153 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 224e421..f952ce0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -74,12 +74,14 @@ set(nixie_clock_sources "app/main.c" "app/stm32f0xx_it.c" "app/system_stm32f0xx.c" - "app/platform/stm32f0-gcc/uart.cpp" - "app/platform/stm32f0-gcc/retarget.cpp" "app/platform/stm32f0-gcc/freertos/port.c" + "app/platform/stm32f0-gcc/interrupts.cpp" + "app/platform/stm32f0-gcc/platform.cpp" "app/platform/stm32f0-gcc/startup/handlers_cm.c" "app/platform/stm32f0-gcc/startup/stack.cpp" "app/platform/stm32f0-gcc/startup/startup.cpp" + "app/platform/stm32f0-gcc/retarget.cpp" + "app/platform/stm32f0-gcc/uart.cpp" ) set(newlib_sources @@ -60,7 +60,8 @@ #include "indicate/indicate_modes_task.h" #include "tsl_user.h" #include "time/time.h" -#include "stm32f0xx_usart.h" +#include "platform/platform.h" +#include "unistd.h" /* Private typedefs ----------------------------------------------------------*/ @@ -81,117 +82,12 @@ /* Private functions prototype ---------------------------------------------- */ -static void USART1Init(void) -{ - RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); - RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE); - GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_1); - GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_1); - GPIO_InitTypeDef GPIO_InitStructure; - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_Level_3; - GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; - GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN; - GPIO_Init(GPIOA, &GPIO_InitStructure); - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; - GPIO_Init(GPIOA, &GPIO_InitStructure); - USART_InitTypeDef usart_init = {0}; - usart_init.USART_BaudRate = 115200; - usart_init.USART_WordLength = USART_WordLength_8b; - usart_init.USART_StopBits = USART_StopBits_1; - usart_init.USART_Parity = USART_Parity_No; - usart_init.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; - usart_init.USART_HardwareFlowControl = USART_HardwareFlowControl_None; - USART_Init(USART1, &usart_init); - USART_Cmd(USART1, ENABLE); -} - -static void USART4Init(void) -{ - RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART4, ENABLE); - RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE); - GPIO_PinAFConfig(GPIOA, GPIO_PinSource0, GPIO_AF_4); - GPIO_PinAFConfig(GPIOA, GPIO_PinSource1, GPIO_AF_4); - GPIO_InitTypeDef GPIO_InitStructure; - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_Level_3; - GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; - GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN; - GPIO_Init(GPIOA, &GPIO_InitStructure); - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1; - GPIO_Init(GPIOA, &GPIO_InitStructure); - USART_InitTypeDef usart_init = {0}; - usart_init.USART_BaudRate = 9600; - usart_init.USART_WordLength = USART_WordLength_8b; - usart_init.USART_StopBits = USART_StopBits_1; - usart_init.USART_Parity = USART_Parity_No; - usart_init.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; - usart_init.USART_HardwareFlowControl = USART_HardwareFlowControl_None; - USART_Init(USART4, &usart_init); - USART_Cmd(USART4, ENABLE); -} - -static void WIFI_IO_GPIOInit(void) -{ - RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE); - RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE); - GPIO_InitTypeDef GPIO_InitStructure; - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15; - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_Level_3; - GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; - GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN; - GPIO_Init(GPIOA, &GPIO_InitStructure); - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; - GPIO_Init(GPIOB, &GPIO_InitStructure); - GPIO_SetBits(GPIOB, GPIO_Pin_0); // WIFI_EN - GPIO_ResetBits(GPIOA, GPIO_Pin_15); // WIFI_IO0 -} - -static void USART3Init(void) -{ - RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE); - RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE); - GPIO_PinAFConfig(GPIOB, GPIO_PinSource1, GPIO_AF_4); - GPIO_PinAFConfig(GPIOB, GPIO_PinSource10, GPIO_AF_4); - GPIO_PinAFConfig(GPIOB, GPIO_PinSource11, GPIO_AF_4); - GPIO_PinAFConfig(GPIOB, GPIO_PinSource13, GPIO_AF_4); - GPIO_InitTypeDef GPIO_InitStructure; - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1; - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_Level_3; - GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; - GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN; - GPIO_Init(GPIOB, &GPIO_InitStructure); - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; - GPIO_Init(GPIOB, &GPIO_InitStructure); - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11; - GPIO_Init(GPIOB, &GPIO_InitStructure); - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13; - GPIO_Init(GPIOB, &GPIO_InitStructure); - USART_InitTypeDef usart_init = {0}; - usart_init.USART_BaudRate = 115200; - usart_init.USART_WordLength = USART_WordLength_8b; - usart_init.USART_StopBits = USART_StopBits_1; - usart_init.USART_Parity = USART_Parity_No; - usart_init.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; - usart_init.USART_HardwareFlowControl = USART_HardwareFlowControl_RTS_CTS; - USART_Init(USART3, &usart_init); - USART_Cmd(USART3, ENABLE); -} - // ---------------------------------------------------------------------------- // Инициализация до создания задач // ---------------------------------------------------------------------------- void InitAll ( void ) { - SystemInit(); - WIFI_IO_GPIOInit(); - USART1Init(); - USART3Init(); - USART4Init(); + PlatformInit(); InitLTimers(); LightSensorInit(); NixieDriverInit(); @@ -208,14 +104,18 @@ void InitAll ( void ) static void TestUart(void *arg) { (void) arg; + const int wifi_fd = PlatformGetWiFiFileDescriptor(); while (1) { - if (USART3->ISR & USART_ISR_RXNE) { - const uint16_t data = USART_ReceiveData(USART3); - USART_SendData(USART1, data); - } - if (USART1->ISR & USART_ISR_RXNE) { - const uint16_t data = USART_ReceiveData(USART1); - USART_SendData(USART3, data); + char buf[50]; + const ssize_t rret = read(wifi_fd, buf, sizeof(buf)); + if (rret > 0) { + const size_t rsize = rret; + for (size_t written = 0; written < rsize; written++) { + const ssize_t wret = write(STDOUT_FILENO, buf, rsize - written); + if (wret > 0) { + written += (size_t)wret; + } + } } } } diff --git a/app/platform/platform.h b/app/platform/platform.h new file mode 100644 index 0000000..c28300e --- /dev/null +++ b/app/platform/platform.h @@ -0,0 +1,13 @@ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +void PlatformInit(void); +int PlatformGetWiFiFileDescriptor(void); +int PlatformGetGPSFileDescriptor(void); + +#ifdef __cplusplus +} +#endif diff --git a/app/platform/stm32f0-gcc/interrupts.cpp b/app/platform/stm32f0-gcc/interrupts.cpp new file mode 100644 index 0000000..9136e88 --- /dev/null +++ b/app/platform/stm32f0-gcc/interrupts.cpp @@ -0,0 +1,12 @@ +#include "uart.h" + +extern "C" void USART1_handler() +{ + UARTHandleInterrupt(&g_uart1); +} + +extern "C" void USART_00B3_handler() +{ + UARTHandleInterrupt(&g_uart3); + UARTHandleInterrupt(&g_uart4); +} diff --git a/app/platform/stm32f0-gcc/platform.cpp b/app/platform/stm32f0-gcc/platform.cpp new file mode 100644 index 0000000..00bc391 --- /dev/null +++ b/app/platform/stm32f0-gcc/platform.cpp @@ -0,0 +1,140 @@ +#include "platform/platform.h" +#include "retarget.h" +#include "third_party/CMSIS/Device/Include/system_stm32f0xx.h" +#include "third_party/STM32F0xx_StdPeriph_Driver/inc/stm32f0xx_usart.h" +#include "third_party/STM32F0xx_StdPeriph_Driver/inc/stm32f0xx_rcc.h" +#include "third_party/STM32F0xx_StdPeriph_Driver/inc/stm32f0xx_gpio.h" + +#if defined(__GNUC__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wold-style-cast" +#endif + +static void USART1Init(void) +{ + RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); + RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE); + GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_1); + GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_1); + GPIO_InitTypeDef GPIO_InitStructure; + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_Level_3; + GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; + GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN; + GPIO_Init(GPIOA, &GPIO_InitStructure); + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; + GPIO_Init(GPIOA, &GPIO_InitStructure); + USART_InitTypeDef usart_init{}; + usart_init.USART_BaudRate = 115200; + usart_init.USART_WordLength = USART_WordLength_8b; + usart_init.USART_StopBits = USART_StopBits_1; + usart_init.USART_Parity = USART_Parity_No; + usart_init.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; + usart_init.USART_HardwareFlowControl = USART_HardwareFlowControl_None; + USART_Init(USART1, &usart_init); + USART1->CR1 |= USART_CR1_RXNEIE; + USART1->CR3 |= USART_CR3_OVRDIS; + USART_Cmd(USART1, ENABLE); + // TODO get rid of SPL +} + +static void USART4Init(void) +{ + RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART4, ENABLE); + RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE); + GPIO_PinAFConfig(GPIOA, GPIO_PinSource0, GPIO_AF_4); + GPIO_PinAFConfig(GPIOA, GPIO_PinSource1, GPIO_AF_4); + GPIO_InitTypeDef GPIO_InitStructure; + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_Level_3; + GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; + GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN; + GPIO_Init(GPIOA, &GPIO_InitStructure); + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1; + GPIO_Init(GPIOA, &GPIO_InitStructure); + USART_InitTypeDef usart_init{}; + usart_init.USART_BaudRate = 9600; + usart_init.USART_WordLength = USART_WordLength_8b; + usart_init.USART_StopBits = USART_StopBits_1; + usart_init.USART_Parity = USART_Parity_No; + usart_init.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; + usart_init.USART_HardwareFlowControl = USART_HardwareFlowControl_None; + USART_Init(USART4, &usart_init); + USART4->CR1 |= USART_CR1_RXNEIE; + USART4->CR3 |= USART_CR3_OVRDIS; + USART_Cmd(USART4, ENABLE); + // TODO get rid of SPL +} + +static void WIFI_IO_GPIOInit(void) +{ + RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE); + RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE); + GPIO_InitTypeDef GPIO_InitStructure; + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_Level_3; + GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; + GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN; + GPIO_Init(GPIOA, &GPIO_InitStructure); + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; + GPIO_Init(GPIOB, &GPIO_InitStructure); + GPIO_SetBits(GPIOB, GPIO_Pin_0); // WIFI_EN + GPIO_ResetBits(GPIOA, GPIO_Pin_15); // WIFI_IO0 +} + +static void USART3Init(void) +{ + RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE); + RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE); + GPIO_PinAFConfig(GPIOB, GPIO_PinSource1, GPIO_AF_4); + GPIO_PinAFConfig(GPIOB, GPIO_PinSource10, GPIO_AF_4); + GPIO_PinAFConfig(GPIOB, GPIO_PinSource11, GPIO_AF_4); + GPIO_PinAFConfig(GPIOB, GPIO_PinSource13, GPIO_AF_4); + GPIO_InitTypeDef GPIO_InitStructure; + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_Level_3; + GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; + GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN; + GPIO_Init(GPIOB, &GPIO_InitStructure); + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; + GPIO_Init(GPIOB, &GPIO_InitStructure); + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11; + GPIO_Init(GPIOB, &GPIO_InitStructure); + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13; + GPIO_Init(GPIOB, &GPIO_InitStructure); + USART_InitTypeDef usart_init{}; + usart_init.USART_BaudRate = 115200; + usart_init.USART_WordLength = USART_WordLength_8b; + usart_init.USART_StopBits = USART_StopBits_1; + usart_init.USART_Parity = USART_Parity_No; + usart_init.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; + usart_init.USART_HardwareFlowControl = USART_HardwareFlowControl_RTS_CTS; + USART_Init(USART3, &usart_init); + USART3->CR1 |= USART_CR1_RXNEIE; + USART3->CR3 |= USART_CR3_OVRDIS; + USART_Cmd(USART3, ENABLE); + // TODO get rid of SPL +} + +void PlatformInit(void) +{ + SystemInit(); + WIFI_IO_GPIOInit(); + USART1Init(); + USART3Init(); + USART4Init(); +} + +int PlatformGetWiFiFileDescriptor(void) +{ + return WIFI_FILENO; +} + +int PlatformGetGPSFileDescriptor(void) +{ + return GPS_FILENO; +} diff --git a/app/platform/stm32f0-gcc/retarget.cpp b/app/platform/stm32f0-gcc/retarget.cpp index 8b8160f..a6706d3 100644 --- a/app/platform/stm32f0-gcc/retarget.cpp +++ b/app/platform/stm32f0-gcc/retarget.cpp @@ -31,11 +31,11 @@ struct File static constexpr size_t kFilesCount = 5; static File files[5] { - { FileType::kUART, O_NONBLOCK, reinterpret_cast<void *>(USART1), }, - { FileType::kUART, O_NONBLOCK, reinterpret_cast<void *>(USART1), }, - { FileType::kUARTDirect, 0, reinterpret_cast<void *>(USART1), }, - { FileType::kUART, O_NONBLOCK, reinterpret_cast<void *>(USART3), }, - { FileType::kUART, O_NONBLOCK, reinterpret_cast<void *>(USART4), }, + { FileType::kUART, O_NONBLOCK, reinterpret_cast<void *>(&g_uart1), }, // STDIN_FILENO + { FileType::kUART, O_NONBLOCK, reinterpret_cast<void *>(&g_uart1), }, // STDOUT_FILENO + { FileType::kUARTDirect, 0, reinterpret_cast<void *>(&g_uart1), }, // STDERR_FILENO + { FileType::kUART, O_NONBLOCK, reinterpret_cast<void *>(&g_uart3), }, // WIFI_FILENO + { FileType::kUART, O_NONBLOCK, reinterpret_cast<void *>(&g_uart4), }, // GPS_FILENO }; int errno{}; @@ -91,10 +91,10 @@ extern "C" ssize_t read(int fd, void *buf, size_t nbytes) size_t ret{}; switch (file->type) { case FileType::kUART: - ret = UARTRead(reinterpret_cast<USART_TypeDef*>(file->extra), buf, nbytes); + ret = UARTRead(reinterpret_cast<UART*>(file->extra), buf, nbytes); break; case FileType::kUARTDirect: - ret = UARTReadDirect(reinterpret_cast<USART_TypeDef*>(file->extra), buf, nbytes); + ret = UARTReadDirect(reinterpret_cast<UART*>(file->extra), buf, nbytes); break; } return ret; @@ -110,10 +110,10 @@ extern "C" ssize_t write(int fd, const void *buf, size_t nbytes) size_t ret{}; switch (file->type) { case FileType::kUART: - ret = UARTWrite(reinterpret_cast<USART_TypeDef*>(file->extra), buf, nbytes); + ret = UARTWrite(reinterpret_cast<UART*>(file->extra), buf, nbytes); break; case FileType::kUARTDirect: - ret = UARTWriteDirect(reinterpret_cast<USART_TypeDef*>(file->extra), buf, nbytes); + ret = UARTWriteDirect(reinterpret_cast<UART*>(file->extra), buf, nbytes); break; } return ret; diff --git a/app/platform/stm32f0-gcc/retarget.h b/app/platform/stm32f0-gcc/retarget.h new file mode 100644 index 0000000..5aea11a --- /dev/null +++ b/app/platform/stm32f0-gcc/retarget.h @@ -0,0 +1,4 @@ +#pragma once + +#define WIFI_FILENO 3 +#define GPS_FILENO 4 diff --git a/app/platform/stm32f0-gcc/ring_buffer.cpp b/app/platform/stm32f0-gcc/ring_buffer.cpp new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/app/platform/stm32f0-gcc/ring_buffer.cpp diff --git a/app/platform/stm32f0-gcc/ring_buffer.h b/app/platform/stm32f0-gcc/ring_buffer.h new file mode 100644 index 0000000..1a065ef --- /dev/null +++ b/app/platform/stm32f0-gcc/ring_buffer.h @@ -0,0 +1,50 @@ +#pragma once +#include <cassert> +#include <cstring> + +template <typename T> +class RingBuffer +{ +public: + using UnitType = T; + constexpr explicit RingBuffer(UnitType* buffer, size_t buffer_size) + : _buffer_size(buffer_size), _buffer(buffer) + { + assert(buffer_size); + assert(buffer); + } + constexpr void Push(UnitType item) + { + _buffer[_head] = item; + _head = (_head + 1) % _buffer_size; + } + constexpr void Push(const UnitType *items, size_t nitems) + { + if (items) for (; nitems; items++, nitems--) Push(*items); + } + constexpr UnitType Pop() + { + const auto item = _buffer[_tail]; + _tail = (_tail + 1) % _buffer_size; + return item; + } + constexpr void Pop(UnitType* buf, size_t nitems) + { + if (buf) for (; nitems; nitems--, buf++) *buf = Pop(); + } + constexpr size_t Free() + { + return Size() - Occupied(); + } + constexpr size_t Occupied() + { + return _head - _tail + (_head >= _tail) ? 0 : _buffer_size; + } + constexpr bool IsEmpty() { return _head == _tail; } + constexpr bool IsFull() { return _tail + 1 == _head; } + constexpr size_t Size() { return _buffer_size - 1; } +private: + size_t _buffer_size{}; + UnitType *_buffer{}; + size_t _head{}, _tail{}; +}; diff --git a/app/platform/stm32f0-gcc/uart.cpp b/app/platform/stm32f0-gcc/uart.cpp index 0fa6527..4d9bf5f 100644 --- a/app/platform/stm32f0-gcc/uart.cpp +++ b/app/platform/stm32f0-gcc/uart.cpp @@ -1,33 +1,114 @@ #include "uart.h" +#include "ring_buffer.h" -size_t UARTWrite(USART_TypeDef* uart, const void *data, size_t nbytes) +#if defined(__GNUC__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wold-style-cast" +#endif + +struct UART +{ + USART_TypeDef* usart; + RingBuffer<uint8_t> rx_buffer; + RingBuffer<uint8_t> tx_buffer; +}; + +static constexpr size_t kUART1RxBufferSize = 100; +static constexpr size_t kUART1TxBufferSize = 256; +static constexpr size_t kUART3RxBufferSize = 256; +static constexpr size_t kUART3TxBufferSize = 256; +static constexpr size_t kUART4RxBufferSize = 100; +static constexpr size_t kUART4TxBufferSize = 100; +static uint8_t g_uart1_rx_buffer[kUART1RxBufferSize]{}; +static uint8_t g_uart1_tx_buffer[kUART1TxBufferSize]{}; +static uint8_t g_uart3_rx_buffer[kUART3RxBufferSize]{}; +static uint8_t g_uart3_tx_buffer[kUART3TxBufferSize]{}; +static uint8_t g_uart4_rx_buffer[kUART4RxBufferSize]{}; +static uint8_t g_uart4_tx_buffer[kUART4TxBufferSize]{}; + +UART g_uart1{ + USART1, + RingBuffer<uint8_t>(g_uart1_rx_buffer, kUART1RxBufferSize), + RingBuffer<uint8_t>(g_uart1_tx_buffer, kUART1TxBufferSize), +}; +UART g_uart3{ + USART3, + RingBuffer<uint8_t>(g_uart3_rx_buffer, kUART3RxBufferSize), + RingBuffer<uint8_t>(g_uart3_tx_buffer, kUART3TxBufferSize), +}; +UART g_uart4{ + USART4, + RingBuffer<uint8_t>(g_uart4_rx_buffer, kUART4RxBufferSize), + RingBuffer<uint8_t>(g_uart4_tx_buffer, kUART4TxBufferSize), +}; + +static constexpr Min(size_t a, size_t b) { return (a >= b) ? a : b; } + +size_t UARTWrite(UART* uart, const void *buf, size_t nbytes) +{ + if (uart == nullptr || buf == nullptr) return 0; + const size_t size = Min(nbytes, uart->tx_buffer.Free()); + if (size == 0) return 0; + uart->tx_buffer.Push(reinterpret_cast<const uint8_t*>(buf), size); + uart->usart->CR1 |= USART_CR1_TXEIE; + return size; +} + +size_t UARTWriteDirect(UART* uart, const void *buf, size_t nbytes) { - if (uart == nullptr) return 0; - (void) data; - (void) nbytes; - return 0; + if (uart == nullptr || buf == nullptr) return 0; + const uint8_t *data = reinterpret_cast<const uint8_t *>(buf); + // TODO disable interrupts here + for (size_t i = 0; i < nbytes; i++) { + while (!(uart->usart->ISR & USART_ISR_TXE)); + uart->usart->TDR = data[i]; + } + // TODO restore (not just enable) interrupts here + return nbytes; } -size_t UARTWriteDirect(USART_TypeDef* uart, const void *data, size_t nbytes) +size_t UARTRead(UART* uart, void *buf, size_t nbytes) { - if (uart == nullptr) return 0; - (void) data; - (void) nbytes; - return 0; + if (uart == nullptr || buf == nullptr) return 0; + const size_t size = Min(nbytes, uart->rx_buffer.Occupied()); + uart->rx_buffer.Pop(reinterpret_cast<uint8_t*>(buf), size); + return size; } -size_t UARTRead(USART_TypeDef* uart, void *data, size_t nbytes) +size_t UARTReadDirect(UART* uart, void *buf, size_t nbytes) { - if (uart == nullptr) return 0; - (void) data; - (void) nbytes; - return 0; + if (uart == nullptr || buf == nullptr) return 0; + uint8_t *data = reinterpret_cast<uint8_t *>(buf); + // TODO disable interrupts here + for (size_t i = 0; i < nbytes; i++) { + while (!(uart->usart->ISR & USART_ISR_RXNE)); + data[i] = uart->usart->RDR; + } + // TODO restore (not just enable) interrupts here + return nbytes; } -size_t UARTReadDirect(USART_TypeDef* uart, void *data, size_t nbytes) +void UARTHandleInterrupt(UART* uart) { - if (uart == nullptr) return 0; - (void) data; - (void) nbytes; - return 0; + volatile USART_TypeDef* usart_regs = uart->usart; + const uint32_t cr1 = usart_regs->CR1; + if ((cr1 & USART_CR1_UE) == 0) + return; + for (int _ = 0; _ < 256; _++) { + const uint32_t isr = usart_regs->ISR; + const bool rxne = isr & USART_ISR_RXNE; + const bool txe = isr & USART_ISR_TXE; + if (!rxne && !txe) + break; + if (rxne) { + uart->rx_buffer.Push(usart_regs->RDR); + } + if (txe) { + if (!uart->tx_buffer.IsEmpty()) { + usart_regs->TDR = uart->tx_buffer.Pop(); + } else { + usart_regs->CR1 &= ~USART_CR1_TXEIE; + } + } + } } diff --git a/app/platform/stm32f0-gcc/uart.h b/app/platform/stm32f0-gcc/uart.h index 176f847..1cbc56f 100644 --- a/app/platform/stm32f0-gcc/uart.h +++ b/app/platform/stm32f0-gcc/uart.h @@ -2,11 +2,20 @@ #include <cstddef> #include "stm32f0xx.h" -// Non-blocking buffered write -size_t UARTWrite(USART_TypeDef*, const void *data, size_t nbytes); -// Blocking write directly into data register -size_t UARTWriteDirect(USART_TypeDef*, const void *data, size_t nbytes); -// Non-blocking buffered read -size_t UARTRead(USART_TypeDef*, void *data, size_t nbytes); -// Blocking read directly from data register -size_t UARTReadDirect(USART_TypeDef*, void *data, size_t nbytes); +struct UART; + +/// Non-blocking buffered write +size_t UARTWrite(UART*, const void *buf, size_t nbytes); +/// Blocking write directly into data register +size_t UARTWriteDirect(UART*, const void *buf, size_t nbytes); +/// Non-blocking buffered read +size_t UARTRead(UART*, void *buf, size_t nbytes); +/// Blocking read directly from data register +size_t UARTReadDirect(UART*, void *buf, size_t nbytes); +/// Generic interrupt handler +void UARTHandleInterrupt(UART*); + +extern UART g_uart1; +extern UART g_uart2; +extern UART g_uart3; +extern UART g_uart4; diff --git a/third_party/CMSIS/Device/Include/system_stm32f0xx.h b/third_party/CMSIS/Device/Include/system_stm32f0xx.h index ab76a00..1d6fb8f 100644 --- a/third_party/CMSIS/Device/Include/system_stm32f0xx.h +++ b/third_party/CMSIS/Device/Include/system_stm32f0xx.h @@ -25,6 +25,8 @@ ****************************************************************************** */ +#include <stdint.h> + /** @addtogroup CMSIS * @{ */ |