summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOxore <oxore@protonmail.com>2023-03-09 01:42:59 +0300
committerOxore <oxore@protonmail.com>2023-03-09 01:42:59 +0300
commit34746d3783af1ae601487c88f0a7e44f81842618 (patch)
tree508a849e81e1f7a83e1df053719579e4452b4e35
parent8370de05bb807f02c0077ba59c68053b283671e2 (diff)
Impl UART buffering (still not tested)
-rw-r--r--CMakeLists.txt6
-rw-r--r--app/main.c128
-rw-r--r--app/platform/platform.h13
-rw-r--r--app/platform/stm32f0-gcc/interrupts.cpp12
-rw-r--r--app/platform/stm32f0-gcc/platform.cpp140
-rw-r--r--app/platform/stm32f0-gcc/retarget.cpp18
-rw-r--r--app/platform/stm32f0-gcc/retarget.h4
-rw-r--r--app/platform/stm32f0-gcc/ring_buffer.cpp0
-rw-r--r--app/platform/stm32f0-gcc/ring_buffer.h50
-rw-r--r--app/platform/stm32f0-gcc/uart.cpp121
-rw-r--r--app/platform/stm32f0-gcc/uart.h25
-rw-r--r--third_party/CMSIS/Device/Include/system_stm32f0xx.h2
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
diff --git a/app/main.c b/app/main.c
index 352d766..3ac4ab0 100644
--- a/app/main.c
+++ b/app/main.c
@@ -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
* @{
*/