halx
読み取り中…
検索中…
一致する文字列を見つけられません
uart_dma.hpp
[詳解]
1#pragma once
2
3#include <atomic>
4#include <cstddef>
5#include <cstdint>
6#include <vector>
7
8#include "halx/core.hpp"
9
10#include "common.hpp"
11
12namespace halx::peripheral {
13
14template <UART_HandleTypeDef *Handle> class UartTxDma {
15public:
17 stm32cubemx_helper::set_context<Handle, UartTxDma>(this);
18 HAL_UART_RegisterCallback(
19 Handle, HAL_UART_TX_COMPLETE_CB_ID, [](UART_HandleTypeDef *) {
20 auto tx = stm32cubemx_helper::get_context<Handle, UartTxDma>();
21 tx->notifier_.set(0x1);
22 });
23 HAL_UART_RegisterCallback(
24 Handle, HAL_UART_ERROR_CB_ID, [](UART_HandleTypeDef *) {
25 auto tx = stm32cubemx_helper::get_context<Handle, UartTxDma>();
26 tx->notifier_.set(0x2);
27 });
28 };
29
31 HAL_UART_AbortTransmit(Handle);
32 HAL_UART_UnRegisterCallback(Handle, HAL_UART_TX_COMPLETE_CB_ID);
33 HAL_UART_UnRegisterCallback(Handle, HAL_UART_ERROR_CB_ID);
34 stm32cubemx_helper::set_context<Handle, UartTxDma>(nullptr);
35 }
36
37 bool transmit(const uint8_t *data, size_t size, uint32_t timeout) {
38 notifier_.reset();
39 if (HAL_UART_Transmit_DMA(Handle, data, size) != HAL_OK) {
40 HAL_UART_AbortTransmit(Handle);
41 return false;
42 }
43 if (notifier_.wait(0x1 | 0x2, timeout) != 0x1) {
44 HAL_UART_AbortTransmit(Handle);
45 return false;
46 }
47 return true;
48 }
49
50private:
51 core::Notifier notifier_;
52
53 UartTxDma(const UartTxDma &) = delete;
54 UartTxDma &operator=(const UartTxDma &) = delete;
55};
56
57template <UART_HandleTypeDef *Handle> class UartRxDma {
58public:
59 UartRxDma(size_t buf_size) : buf_(buf_size) {
60 stm32cubemx_helper::set_context<Handle, UartRxDma>(this);
61 HAL_UART_RegisterCallback(
62 Handle, HAL_UART_ERROR_CB_ID,
63 [](UART_HandleTypeDef *huart) { HAL_UART_AbortReceive_IT(huart); });
64 HAL_UART_RegisterCallback(
65 Handle, HAL_UART_ABORT_RECEIVE_COMPLETE_CB_ID,
66 [](UART_HandleTypeDef *huart) {
67 auto rx = stm32cubemx_helper::get_context<Handle, UartRxDma>();
68 HAL_UART_Receive_DMA(huart, rx->buf_.data(), rx->buf_.size());
69 rx->read_idx_.store(0, std::memory_order_relaxed);
70 });
71 HAL_UART_Receive_DMA(Handle, buf_.data(), buf_.size());
72 }
73
75 HAL_UART_AbortReceive(Handle);
76 HAL_UART_UnRegisterCallback(Handle, HAL_UART_ERROR_CB_ID);
77 HAL_UART_UnRegisterCallback(Handle, HAL_UART_ABORT_RECEIVE_COMPLETE_CB_ID);
78 stm32cubemx_helper::set_context<Handle, UartRxDma>(nullptr);
79 }
80
81 bool receive(uint8_t *data, size_t size, uint32_t timeout) {
82 core::TimeoutHelper timeout_helper{timeout};
83 while (available() < size) {
84 if (timeout_helper.is_timeout()) {
85 return false;
86 }
88 }
89 for (size_t i = 0; i < size; ++i) {
90 data[i] = buf_[read_idx_];
91 advance(1);
92 }
93 return true;
94 }
95
96 void flush() { advance(available()); }
97
98 size_t available() const {
99 size_t write_idx = buf_.size() - __HAL_DMA_GET_COUNTER(Handle->hdmarx);
100 size_t read_idx = read_idx_.load(std::memory_order_relaxed);
101 return (buf_.size() + write_idx - read_idx) % buf_.size();
102 }
103
104private:
105 std::vector<uint8_t> buf_;
106 std::atomic<size_t> read_idx_{0};
107
108 UartRxDma(const UartRxDma &) = delete;
109 UartRxDma &operator=(const UartRxDma &) = delete;
110
111 void advance(size_t len) {
112 size_t read_idx = read_idx_.load(std::memory_order_relaxed);
113 while (true) {
114 if (read_idx_.compare_exchange_weak(
115 read_idx, (read_idx + len) % buf_.size(),
116 std::memory_order_relaxed, std::memory_order_relaxed)) {
117 break;
118 }
119 }
120 }
121};
122
123} // namespace halx::peripheral
Definition notifier.hpp:11
Definition timeout.hpp:9
void flush()
Definition uart_dma.hpp:96
bool receive(uint8_t *data, size_t size, uint32_t timeout)
Definition uart_dma.hpp:81
size_t available() const
Definition uart_dma.hpp:98
~UartRxDma()
Definition uart_dma.hpp:74
UartRxDma(size_t buf_size)
Definition uart_dma.hpp:59
Definition uart_dma.hpp:14
bool transmit(const uint8_t *data, size_t size, uint32_t timeout)
Definition uart_dma.hpp:37
UartTxDma()
Definition uart_dma.hpp:16
~UartTxDma()
Definition uart_dma.hpp:30
void yield()
Definition common.hpp:46
Definition can.hpp:13