forked from suikan4github/murasaki
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdebuggeruart.hpp
216 lines (202 loc) · 9.12 KB
/
debuggeruart.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
/**
* \file debuggeruart.hpp
*
* \date 2018/09/23
* \author takemasa
* @brief UART. Thread safe and blocking IO
*/
#ifndef DEBUGGER_UART_HPP_
#define DEBUGGER_UART_HPP_
#include <synchronizer.hpp>
#include <uartstrategy.hpp>
#include "criticalsection.hpp"
// Check if CubeMX generates UART module
#ifdef HAL_UART_MODULE_ENABLED
namespace murasaki {
/**
* @ingroup MURASAKI_HELPER_GROUP
* \brief Logging dedicated UART class
* \details
*
* The Uart class is the wrapper of the UART controller. To use the DebuggerUart class,
* make an instance with UART_HandleTypeDef * type pointer. For example, to create
* an instance for the UART3 peripheral :
* \code
* my_uart3 = new murasaki::DebuggerUart(&huart3);
* \endcode
* Where huart3 is the handle generated by CubeMX for UART3 peripheral. To use this class,
* the UART peripheral have to be configured to use the DMA functionality. The baud rate,
* length and flow control should be configured by the CubeMX.
*
* In addition to the instantiation, we need to prepare an interrupt callback.
* \code
* void HAL_UART_TxCpltCallback(UART_HandleTypeDef * huart)
* {
* my_uart3->TransmitCompleteCallback(huart);
* }
* \endcode
* Where HAL_UART_TxCpltCallback is a predefined name of the UART interrupt handler.
* This is invoked by system whenever a DMA baed UART transmission is complete.
* Becuase the default function is weakly bound, above definition will overwride the
* default one.
*
* Note that above callback is invoked for any UARTn where n is 1, 2, 3... To avoid the
* confusion, Uart::TransmitCompleteCallback() method chckes whether given parameter
* matches with its UART_HandleTypeDef * pointer ( which was passed to constructor ).
* And only when both matches, the member function execute the interrupt termination process.
*
* As same as Tx, RX needs HAL_UART_TxCpltCallback().
*
* Once the instance and callbacks are correctly prepared, we can use the Tx/Rx member function.
*
* The @ref Uart::Transmit() member function is a blocking function. A programmer can specify the
* timeout by timeout_ms parameter. By default, this parameter is set by kwmsIndefinitely
* which specifes never time out.
*
* The @ref Uart::Receive() member function is a blocking function. A programmer can specify the
* timeout by timeout_ms parameter. By default, this parameter is set by kwmsIndefinitely
* which specifes never time out.
*
* Both methods can be called from only the task context. If these are called in the ISR
* context, the result is unknown.
*/
class DebuggerUart : public UartStrategy
{
public:
/**
* \brief Constructor
* \param uart Pointer to a UART control struct. This device have to be configured to use DMA and interrupt for both Tx and Rx.
* \details
* Store the given uart pointer into the internal variable. This pointer is passed to the STM32 HAL UART functions when needed.
*
*/
DebuggerUart(UART_HandleTypeDef * uart);
/**
* \brief Destructor. Delete internal variables.
*/
virtual ~DebuggerUart();
/**
* \brief Set the behavior of the hardware flow control
* \param control The control mode.
* \details
* Before calling this method, all transmission and recevie activites have to be finished.
* This is responsibility of the programmer.
*
* Note this method is NOT re-etnrant.
* In other word, this member function can be called from both task and interrupt context.
*/
virtual void SetHardwareFlowControl(UartHardwareFlowControl control);
/**
* @brief Set the BAUD rate
* @param baud_rate BAUD rate ( 110, 300,... 57600,... )
* \details
* Before calling this method, all transmission and recevie activites have to be finished.
* This is responsibility of the programmer.
*
* Note this method is NOT re-etnrant.
* In other word, this member function can be called from both task and interrupt context.
*/
virtual void SetSpeed(unsigned int baud_rate);
/**
* \brief Transmit raw data through an UART by blocking mode.
* \param data Data buffer to be transmitted.
* \param size The count of the data ( byte ) to be transfered. Must be smaller than 65536
* \param timeout_ms Time out limit by milliseconds.
* \return Always returns OK
* \details
* Transmit given data buffer through an UART device.
*
* The transmission mode is blocking. That means, function returns when all data has been transmitted, except timeout.
* Passing \ref murasaki::kwmsIndefinitely to the parameter timeout_ms orders not to return until complete transmission. Other value of
* timeout_ms parameter specifies the time out by millisecond. If time out happen, function returns false. If not happen, it returns true.
*
* This function is exclusive. Internally the function is guarded by mutex. Then this function is thread safe.
* This function is forbiddedn to call from ISR.
*/
virtual murasaki::UartStatus Transmit(
const uint8_t * data,
unsigned int size,
WaitMilliSeconds timeout_ms);
/**
* \brief Receive raw data through an UART by blocking mode.
* \param data Data buffer to place the received data..
* \param count The count of the data ( byte ) to be transfered. Must be smaller than 65536
* \param transfered_count This parameter is ignored.
* \param uart_timeout This parameter is ignored
* \param timeout_ms Time out limit by milliseconds.
* \return Always returns OK
* \details
* Receive to given data buffer through an UART device.
*
* The receiving mode is blocking. That means, function returns when specified number of data has been received, except timeout.
* Passing \ref murasaki::kwmsIndefinitely to the parameter timeout_ms orders not to return until complete receiving. Other value of
* timeout_ms parameter specifies the time out by millisecond.
* If time out happen, function returns false. If not happen, it returns true.
*
* This function is exclusive. Internally this function is guarded by mutex. Then this function is thread safe.
* This function is forbiddedn to call from ISR.
*/
virtual murasaki::UartStatus Receive(
uint8_t * data,
unsigned int count,
unsigned int * transfered_count,
UartTimeout uart_timeout,
WaitMilliSeconds timeout_ms);
/**
* \brief Call back for entire block transfer completion.
* \param ptr Pointer to UART_HandleTypeDef struct.
* \return true: ptr matches with UART device and handle the call back. false : doesn't match.
* \details
* A call back to notify the end of entire block transfer.
* This is considered as the end of DMA based transmission.
* The context have to be interrupt.
*
* This member function checks whether the given ptr parameter matches its own device, and if matched,
* Release the waiting task and return true. If it doesn't match, just return false.
*
* This method have to be called from HAL_UART_TxCpltCallback(). See STM32F7 HAL manual for detail
*/
virtual bool TransmitCompleteCallback(void * const ptr);
/**
* \brief Call back for entire block transfer completion.
* \param ptr Pointer to UART_HandleTypeDef struct.
* \return true: ptr matches with UART device and handle the call back. false : doesn't match.
* \details
* A call back to notify the end of entire block transfer.
* This is considered as the end of DMA based receiving.
* The context have to be interrupt.
*
* This member function checks whether the given ptr parameter matches its own device, and if matched,
* Release the waiting task and return true. If it doesn't match, just return false.
*
* This method have to be called from HAL_UART_RxCpltCallback(). See STM32F7 HAL manual for detail */
virtual bool ReceiveCompleteCallback(void* const ptr);
/**
* @brief Error handling
* @param ptr Pointer to UART_HandleTypeDef struct.
* \return true: ptr matches with UART device and handle the error. false : doesn't match.
* @details
* A handle to print out the error message.
*
* Checks whether handle has error and if there is, print appropriate error. Then return.
*/
virtual bool HandleError(void * const ptr);
protected:
UART_HandleTypeDef* const peripheral_;
Synchronizer * const tx_sync_;
Synchronizer * const rx_sync_;
CriticalSection * const tx_critical_section_;
CriticalSection * const rx_critical_section_;
private:
/**
* @brief Return the Platform dependent device control handle.
* @return Handle of device.
* @details
* The handle is the pointer ( or some ID ) which specify the control data of
* specific device.
*/
virtual void * GetPeripheralHandle();
};
} /* namespace platform */
#endif // HAL_UART_MODULE_ENABLED
#endif /* DEBUGGER_UART_HPP_ */