Skip to content

Commit d214fb7

Browse files
committed
[architecture] Adding UartDevice for resumable r/w
1 parent ba23833 commit d214fb7

File tree

2 files changed

+171
-0
lines changed

2 files changed

+171
-0
lines changed
Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
/*
2+
* Copyright (c) 2023, Rasmus Kleist Hørlyck Sørensen
3+
*
4+
* This file is part of the modm project.
5+
*
6+
* This Source Code Form is subject to the terms of the Mozilla Public
7+
* License, v. 2.0. If a copy of the MPL was not distributed with this
8+
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
9+
*/
10+
// ----------------------------------------------------------------------------
11+
12+
#ifndef MODM_INTERFACE_UART_DEVICE_HPP
13+
#define MODM_INTERFACE_UART_DEVICE_HPP
14+
15+
#include "uart.hpp"
16+
#include <modm/processing/timer.hpp>
17+
18+
namespace modm
19+
{
20+
21+
/**
22+
* Base class of an UART Device.
23+
*
24+
* This class provides generic transaction-like semantics
25+
*
26+
* @author Rasmus Kleist Hørlyck Sørensen
27+
* @ingroup modm_architecture_uart_device
28+
*/
29+
template < class Uart, uint8_t NestingLevels = 10 >
30+
class UartDevice : protected modm::NestedResumable< NestingLevels + 1 >
31+
{
32+
public:
33+
UartDevice() :
34+
txTimeout(std::chrono::microseconds(1000)),
35+
rxTimeout(std::chrono::microseconds(10000))
36+
{
37+
}
38+
39+
bool
40+
hasReceived()
41+
{
42+
return Uart::receiveBufferSize() > 0;
43+
}
44+
45+
void
46+
setTxTimeout(ShortPreciseDuration timeout)
47+
{
48+
txTimeout = timeout;
49+
}
50+
51+
void
52+
setRxTimeout(ShortPreciseDuration timeout)
53+
{
54+
rxTimeout = timeout;
55+
}
56+
57+
protected:
58+
modm::ResumableResult<bool>
59+
write(uint8_t data)
60+
{
61+
RF_BEGIN(0);
62+
63+
timeout.restart(txTimeout);
64+
RF_WAIT_UNTIL(Uart::write(data) or timeout.isExpired() or Uart::hasError());
65+
if (timeout.isExpired() or Uart::hasError())
66+
{
67+
Uart::discardTransmitBuffer();
68+
Uart::discardReceiveBuffer();
69+
Uart::clearError();
70+
RF_RETURN(false);
71+
}
72+
RF_END_RETURN(true);
73+
}
74+
75+
modm::ResumableResult<bool>
76+
write(const uint8_t *data, std::size_t length)
77+
{
78+
RF_BEGIN(0);
79+
80+
writeIndex = 0;
81+
timeout.restart(txTimeout);
82+
while (writeIndex < length)
83+
{
84+
if (size_t writeSize = Uart::write(&data[writeIndex], length - writeIndex))
85+
{
86+
writeIndex += writeSize;
87+
timeout.restart(txTimeout);
88+
}
89+
90+
if (timeout.isExpired() or Uart::hasError())
91+
{
92+
Uart::discardReceiveBuffer();
93+
Uart::clearError();
94+
RF_RETURN(false);
95+
}
96+
RF_YIELD();
97+
}
98+
99+
RF_END_RETURN(true);
100+
}
101+
102+
modm::ResumableResult<bool>
103+
read(uint8_t &data)
104+
{
105+
RF_BEGIN(1);
106+
107+
timeout.restart(rxTimeout);
108+
RF_WAIT_UNTIL(Uart::read(data) or timeout.isExpired() or Uart::hasError());
109+
if (timeout.isExpired() or Uart::hasError())
110+
{
111+
Uart::discardReceiveBuffer();
112+
Uart::clearError();
113+
RF_RETURN(false);
114+
}
115+
RF_END_RETURN(true);
116+
}
117+
118+
modm::ResumableResult<bool>
119+
read(uint8_t *buffer, std::size_t length)
120+
{
121+
RF_BEGIN(1);
122+
123+
readIndex = 0;
124+
timeout.restart(rxTimeout);
125+
while (readIndex < length)
126+
{
127+
if (size_t readSize = Uart::read(&buffer[readIndex], length - readIndex))
128+
{
129+
readIndex += readSize;
130+
timeout.restart(rxTimeout);
131+
}
132+
133+
if (timeout.isExpired() or Uart::hasError())
134+
{
135+
Uart::discardReceiveBuffer();
136+
Uart::clearError();
137+
RF_RETURN(false);
138+
}
139+
RF_YIELD();
140+
}
141+
142+
RF_END_RETURN(true);
143+
}
144+
145+
private:
146+
std::size_t readIndex;
147+
std::size_t writeIndex;
148+
149+
ShortPreciseDuration txTimeout;
150+
ShortPreciseDuration rxTimeout;
151+
ShortPreciseTimeout timeout;
152+
};
153+
154+
} // namespace modm
155+
156+
#endif // MODM_INTERFACE_UART_DEVICE_HPP

src/modm/architecture/module.lb

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,20 @@ class Uart(Module):
339339
env.copy("interface/uart.hpp")
340340
# -----------------------------------------------------------------------------
341341

342+
class UartDevice(Module):
343+
def init(self, module):
344+
module.name = "uart.device"
345+
module.description = "UART Devices"
346+
347+
def prepare(self, module, options):
348+
module.depends(":architecture:uart")
349+
return True
350+
351+
def build(self, env):
352+
env.outbasepath = "modm/src/modm/architecture"
353+
env.copy("interface/uart_device.hpp")
354+
# -----------------------------------------------------------------------------
355+
342356
class Unaligned(Module):
343357
def init(self, module):
344358
module.name = "unaligned"
@@ -386,6 +400,7 @@ def prepare(module, options):
386400
module.add_submodule(Spi())
387401
module.add_submodule(SpiDevice())
388402
module.add_submodule(Uart())
403+
module.add_submodule(UartDevice())
389404
module.add_submodule(Unaligned())
390405

391406
return True

0 commit comments

Comments
 (0)