テスト用のあれこれ共用フォルダ
修訂 | a7de957107e3b23ebb1b8a3954d2761728d1bbea (tree) |
---|---|
時間 | 2018-09-23 16:21:31 |
作者 | takemasa <suikan@user...> |
Commiter | takemasa |
The uart.* are copied to the debuggeruart.*.
The current uart.* usage in the logger is not allowed to use the SYSLOG.
Then, the debuggeruart.* was copied from the uart.* and left as dedicated
to the logging.
The uart.* will be modified to implement the advance usage.
@@ -0,0 +1,194 @@ | ||
1 | +/* | |
2 | + * debuggerart.cpp | |
3 | + * | |
4 | + * Created on: 2018/09/23 | |
5 | + * Author: takemasa | |
6 | + */ | |
7 | + | |
8 | +#include "debuggeruart.hpp" | |
9 | +#include "murasaki_defs.hpp" | |
10 | +#include "murasaki_assert.hpp" | |
11 | + | |
12 | +// Check if CubeMX generates UART module | |
13 | +#ifdef HAL_UART_MODULE_ENABLED | |
14 | + | |
15 | + | |
16 | +namespace murasaki { | |
17 | + | |
18 | +DebuggerUart::DebuggerUart(UART_HandleTypeDef * const uart) | |
19 | + : peripheral_(uart), | |
20 | + tx_sync_(new murasaki::Synchronizer), | |
21 | + rx_sync_(new murasaki::Synchronizer), | |
22 | + tx_critical_section_( new murasaki::CriticalSection), | |
23 | + rx_critical_section_(new murasaki::CriticalSection) | |
24 | +{ | |
25 | + // Setup internal variable with given uart structure. | |
26 | + | |
27 | + MURASAKI_ASSERT(nullptr != uart) | |
28 | + MURASAKI_ASSERT(nullptr != tx_sync_) | |
29 | + MURASAKI_ASSERT(nullptr != rx_sync_) | |
30 | + MURASAKI_ASSERT(nullptr != tx_critical_section_) | |
31 | + MURASAKI_ASSERT(nullptr != rx_critical_section_) | |
32 | + | |
33 | +} | |
34 | + | |
35 | +DebuggerUart::~DebuggerUart() | |
36 | +{ | |
37 | + | |
38 | + if (nullptr != tx_sync_) | |
39 | + delete tx_sync_; | |
40 | + | |
41 | + if (nullptr != rx_sync_) | |
42 | + delete rx_sync_; | |
43 | + | |
44 | + if (nullptr != tx_critical_section_) | |
45 | + delete tx_critical_section_; | |
46 | + | |
47 | + if (nullptr != tx_critical_section_) | |
48 | + delete rx_critical_section_; | |
49 | +} | |
50 | + | |
51 | +void DebuggerUart::SetHardwareFlowControl(UartHardwareFlowControl control) | |
52 | +{ | |
53 | + // stop UART activity. This is required by UART HAL specification. | |
54 | + int result = HAL_UART_DeInit(peripheral_); | |
55 | + MURASAKI_ASSERT(result == HAL_OK); | |
56 | + | |
57 | + | |
58 | + // Change the Hardware flow control | |
59 | + switch (control) { | |
60 | + case kuhfcCts : // Control CTS only ( Flow control on TX ) | |
61 | + peripheral_->Init.HwFlowCtl = UART_HWCONTROL_CTS; | |
62 | + break; | |
63 | + case kuhfcRts : // Control RTS only ( Flow control on RX ) | |
64 | + peripheral_->Init.HwFlowCtl = UART_HWCONTROL_RTS; | |
65 | + break; | |
66 | + case kuhfcCtsRts : // Control CTS and RTS ( Flow control on TX and RX ) | |
67 | + peripheral_->Init.HwFlowCtl = UART_HWCONTROL_RTS_CTS; | |
68 | + break; | |
69 | + default: // Nor hardware flow control. | |
70 | + peripheral_->Init.HwFlowCtl = UART_HWCONTROL_NONE; | |
71 | + break; | |
72 | + | |
73 | + } | |
74 | + // restart UART acitivty. | |
75 | + result = HAL_UART_Init(peripheral_); | |
76 | + MURASAKI_ASSERT(result == HAL_OK); | |
77 | +} | |
78 | + | |
79 | +bool DebuggerUart::Transmit(const uint8_t * data, unsigned int size, | |
80 | + WaitMilliSeconds timeout_ms) | |
81 | +{ | |
82 | + bool ret_val; | |
83 | + | |
84 | + MURASAKI_ASSERT(nullptr != data) | |
85 | + MURASAKI_ASSERT(65536 > size); | |
86 | + | |
87 | + // make this methold re-entrant in task context. | |
88 | + tx_critical_section_->Enter(); | |
89 | + { | |
90 | + // Keep coherency between the L2 and cache before DMA | |
91 | + murasaki::InvalidateDataCacheByAddress(const_cast<uint8_t *>(data), | |
92 | + size); | |
93 | + | |
94 | + HAL_StatusTypeDef status = HAL_UART_Transmit_DMA(peripheral_, | |
95 | + const_cast<uint8_t *>(data), size); | |
96 | + MURASAKI_ASSERT(HAL_OK == status); | |
97 | + | |
98 | + ret_val = tx_sync_->Wait(timeout_ms); | |
99 | + } | |
100 | + tx_critical_section_->Leave(); | |
101 | + | |
102 | + return ret_val; // true if Semaphore taken without timeout ( mean, transfered without timeout ) | |
103 | +} | |
104 | + | |
105 | +bool DebuggerUart::TransmitCompleteCallback(void* const ptr) | |
106 | +{ | |
107 | + MURASAKI_ASSERT(nullptr != ptr) | |
108 | + | |
109 | + if (ptr == peripheral_) { | |
110 | + tx_sync_->Release(); | |
111 | + return true; | |
112 | + } | |
113 | + else { | |
114 | + return false; | |
115 | + } | |
116 | +} | |
117 | + | |
118 | +bool DebuggerUart::Receive(uint8_t * data, unsigned int size, WaitMilliSeconds timeout_ms) | |
119 | +{ | |
120 | + bool ret_val; | |
121 | + | |
122 | + MURASAKI_ASSERT(nullptr != data); | |
123 | + MURASAKI_ASSERT(65536 > size); | |
124 | + | |
125 | + // make this methold re-entrant in task context. | |
126 | + rx_critical_section_->Enter(); | |
127 | + { | |
128 | + // Keep coherency between the L2 and cache before DMA | |
129 | + murasaki::InvalidateDataCacheByAddress(data, size); | |
130 | + | |
131 | + HAL_StatusTypeDef status = HAL_UART_Receive_DMA(peripheral_, data, size); | |
132 | + MURASAKI_ASSERT(HAL_OK == status); | |
133 | + | |
134 | + ret_val = rx_sync_->Wait(timeout_ms); | |
135 | + } | |
136 | + rx_critical_section_->Leave(); | |
137 | + | |
138 | + return ret_val; // true if Semaphore taken without timeout ( mean, transfered without timeout ) | |
139 | +} | |
140 | + | |
141 | +void DebuggerUart::SetSpeed(unsigned int baud_rate) | |
142 | +{ | |
143 | + // stop UART activity. This is required by UART HAL specification. | |
144 | + int result = HAL_UART_DeInit(peripheral_); | |
145 | + MURASAKI_ASSERT(result == HAL_OK); | |
146 | + | |
147 | + // Change the Speed | |
148 | + peripheral_->Init.BaudRate = baud_rate; | |
149 | + | |
150 | + // restart UART acitivty. | |
151 | + result = HAL_UART_Init(peripheral_); | |
152 | + MURASAKI_ASSERT(result == HAL_OK); | |
153 | + | |
154 | +} | |
155 | + | |
156 | +bool DebuggerUart::ReceiveCompleteCallback(void* const ptr) | |
157 | +{ | |
158 | + MURASAKI_ASSERT(nullptr != ptr) | |
159 | + | |
160 | + if (peripheral_ == ptr) { | |
161 | + rx_sync_->Release(); | |
162 | + return true; | |
163 | + } | |
164 | + else { | |
165 | + return false; | |
166 | + } | |
167 | +} | |
168 | + | |
169 | +bool DebuggerUart::HandleError(void* const ptr) | |
170 | +{ | |
171 | + MURASAKI_ASSERT(nullptr != ptr) | |
172 | + | |
173 | + if (peripheral_ == ptr) { | |
174 | + // Check error, and print if exist. | |
175 | + MURASAKI_PRINT_ERROR(peripheral_->ErrorCode & HAL_UART_ERROR_DMA); | |
176 | + MURASAKI_PRINT_ERROR(peripheral_->ErrorCode & HAL_UART_ERROR_PE); | |
177 | + MURASAKI_PRINT_ERROR(peripheral_->ErrorCode & HAL_UART_ERROR_NE); | |
178 | + MURASAKI_PRINT_ERROR(peripheral_->ErrorCode & HAL_UART_ERROR_FE); | |
179 | + MURASAKI_PRINT_ERROR(peripheral_->ErrorCode & HAL_UART_ERROR_ORE); | |
180 | + MURASAKI_PRINT_ERROR(peripheral_->ErrorCode & HAL_UART_ERROR_DMA); | |
181 | + return true; // report the ptr matched | |
182 | + } | |
183 | + else { | |
184 | + return false; // report the ptr doesn't match | |
185 | + } | |
186 | +} | |
187 | + | |
188 | +void* DebuggerUart::GetPeripheralHandle() { | |
189 | + return peripheral_; | |
190 | +} | |
191 | + | |
192 | +} /* namespace platform */ | |
193 | + | |
194 | +#endif // HAL_UART_MODULE_ENABLED |
@@ -0,0 +1,207 @@ | ||
1 | +/** | |
2 | + * \file debuggeruart.hpp | |
3 | + * | |
4 | + * \date 2018/09/23 | |
5 | + * \author takemasa | |
6 | + * @brief UART. Thread safe and blocking IO | |
7 | + */ | |
8 | + | |
9 | +#ifndef DEBUGGER_UART_HPP_ | |
10 | +#define DEBUGGER_UART_HPP_ | |
11 | + | |
12 | +#include <synchronizer.hpp> | |
13 | +#include "abstractuart.hpp" | |
14 | +#include "criticalsection.hpp" | |
15 | + | |
16 | +// Check if CubeMX generates UART module | |
17 | +#ifdef HAL_UART_MODULE_ENABLED | |
18 | + | |
19 | +namespace murasaki { | |
20 | + | |
21 | +/** | |
22 | + * \ingroup MURASAKI_GROUP | |
23 | + * \brief Concrete implementation of UART controller. Based on the STM32 HAL DMA Transfer. | |
24 | + * \details | |
25 | + * | |
26 | + * The Uart class is the wrapper of the UART controller. To use the Uart class, | |
27 | + * make an instance with UART_HandleTypeDef * type pointer. For example, to create | |
28 | + * an instance for the UART3 peripheral : | |
29 | + * \code | |
30 | + * my_uart3 = new murasaki::Uart(&huart3); | |
31 | + * \endcode | |
32 | + * Where huart3 is the handle generated by CubeMX for UART3 peripheral. To use this class, | |
33 | + * the UART peripheral have to be configured to use the DMA functionality. The baud rate, | |
34 | + * length and flow control should be configured by the CubeMX. | |
35 | + * | |
36 | + * In addition to the instantiation, we need to prepare an interrupt callback. | |
37 | + * \code | |
38 | + * void HAL_UART_TxCpltCallback(UART_HandleTypeDef * huart) | |
39 | + * { | |
40 | + * my_uart3->TransmitCompleteCallback(huart); | |
41 | + * } | |
42 | + * \endcode | |
43 | + * Where HAL_UART_TxCpltCallback is a predefined name of the UART interrupt handler. | |
44 | + * This is invoked by system whenever a DMA baed UART transmission is complete. | |
45 | + * Becuase the default function is weakly bound, above definition will overwride the | |
46 | + * default one. | |
47 | + * | |
48 | + * Note that above callback is invoked for any UARTn where n is 1, 2, 3... To avoid the | |
49 | + * confusion, Uart::TransmitCompleteCallback() method chckes whether given parameter | |
50 | + * matches with its UART_HandleTypeDef * pointer ( which was passed to constructor ). | |
51 | + * And only when both matches, the member function execute the interrupt termination process. | |
52 | + * | |
53 | + * As same as Tx, RX needs HAL_UART_TxCpltCallback(). | |
54 | + * | |
55 | + * Once the instance and callbacks are correctly prepared, we can use the Tx/Rx member function. | |
56 | + * | |
57 | + * The @ref Uart::Transmit() member function is a blocking function. A programmer can specify the | |
58 | + * timeout by timeout_ms parameter. By default, this parameter is set by kwmsIndefinitely | |
59 | + * which specifes never time out. | |
60 | + * | |
61 | + * The @ref Uart::Receive() member function is a blocking function. A programmer can specify the | |
62 | + * timeout by timeout_ms parameter. By default, this parameter is set by kwmsIndefinitely | |
63 | + * which specifes never time out. | |
64 | + * | |
65 | + * Both methods can be called from only the task context. If these are called in the ISR | |
66 | + * context, the result is unknown. | |
67 | + */ | |
68 | +class DebuggerUart : public AbstractUart | |
69 | +{ | |
70 | + public: | |
71 | + /** | |
72 | + * \brief Constructor | |
73 | + * \param uart Pointer to a UART control struct. This device have to be configured to use DMA and interrupt for both Tx and Rx. | |
74 | + * \details | |
75 | + * Store the given uart pointer into the internal variable. This pointer is passed to the STM32 HAL UART functions when needed. | |
76 | + * | |
77 | + */ | |
78 | + DebuggerUart(UART_HandleTypeDef * uart); | |
79 | + /** | |
80 | + * \brief Destructor. Delete internal variables. | |
81 | + */ | |
82 | + virtual ~DebuggerUart(); | |
83 | + /** | |
84 | + * \brief Set the behavior of the hardware flow control | |
85 | + * \param control The control mode. | |
86 | + * \details | |
87 | + * Before calling this method, all transmission and recevie activites have to be finished. | |
88 | + * This is responsibility of the programmer. | |
89 | + * | |
90 | + * Note this method is NOT re-etnrant. | |
91 | + * In other word, this member function can be called from both task and interrupt context. | |
92 | + */ | |
93 | + virtual void SetHardwareFlowControl(UartHardwareFlowControl control); | |
94 | + /** | |
95 | + * @brief Set the BAUD rate | |
96 | + * @param baud_rate BAUD rate ( 110, 300,... 57600,... ) | |
97 | + * \details | |
98 | + * Before calling this method, all transmission and recevie activites have to be finished. | |
99 | + * This is responsibility of the programmer. | |
100 | + * | |
101 | + * Note this method is NOT re-etnrant. | |
102 | + * In other word, this member function can be called from both task and interrupt context. | |
103 | + */ | |
104 | + virtual void SetSpeed(unsigned int baud_rate); | |
105 | + | |
106 | + /** | |
107 | + * \brief Transmit raw data through an UART by blocking mode. | |
108 | + * \param data Data buffer to be transmitted. | |
109 | + * \param size The count of the data ( byte ) to be transfered. Must be smaller than 65536 | |
110 | + * \param timeout_ms Time out limit by milliseconds. | |
111 | + * \return True if all data transfered completely. False if time out happen. | |
112 | + * \details | |
113 | + * Transmit given data buffer through an UART device. | |
114 | + * | |
115 | + * The transmission mode is blocking. That means, function returns when all data has been transmitted, except timeout. | |
116 | + * Passing \ref murasaki::kwmsIndefinitely to the parameter timeout_ms orders not to return until complete transmission. Other value of | |
117 | + * timeout_ms parameter specifies the time out by millisecond. If time out happen, function returns false. If not happen, it returns true. | |
118 | + * | |
119 | + * This function is exclusive. Internally the function is guarded by mutex. Then this function is thread safe. | |
120 | + * This function is forbiddedn to call from ISR. | |
121 | + */ | |
122 | + virtual bool Transmit(const uint8_t * data, unsigned int size, | |
123 | + WaitMilliSeconds timeout_ms = kwmsIndefinitely); | |
124 | + /** | |
125 | + * \brief Receive raw data through an UART by blocking mode. | |
126 | + * \param data Data buffer to place the received data.. | |
127 | + * \param count The count of the data ( byte ) to be transfered. Must be smaller than 65536 | |
128 | + * \param timeout_ms Time out limit by milliseconds. | |
129 | + * \return True if all data transfered completely. False if time out happen. | |
130 | + * \details | |
131 | + * Receive to given data buffer through an UART device. | |
132 | + * | |
133 | + * The receiving mode is blocking. That means, function returns when specified number of data has been received, except timeout. | |
134 | + * Passing \ref murasaki::kwmsIndefinitely to the parameter timeout_ms orders not to return until complete receiving. Other value of | |
135 | + * timeout_ms parameter specifies the time out by millisecond. | |
136 | + * If time out happen, function returns false. If not happen, it returns true. | |
137 | + * | |
138 | + * This function is exclusive. Internally this function is guarded by mutex. Then this function is thread safe. | |
139 | + * This function is forbiddedn to call from ISR. | |
140 | + */ | |
141 | + virtual bool Receive(uint8_t * data, unsigned int count, WaitMilliSeconds timeout_ms = kwmsIndefinitely); | |
142 | + /** | |
143 | + * \brief Call back for entire block transfer completion. | |
144 | + * \param ptr Pointer to UART_HandleTypeDef struct. | |
145 | + * \return true: ptr matches with UART device and handle the call back. false : doesn't match. | |
146 | + * \details | |
147 | + * A call back to notify the end of entire block transfer. | |
148 | + * This is considered as the end of DMA based transmission. | |
149 | + * The context have to be interrupt. | |
150 | + * | |
151 | + * This member function checks whether the given ptr parameter matches its own device, and if matched, | |
152 | + * Release the waiting task and return true. If it doesn't match, just return false. | |
153 | + * | |
154 | + * This method have to be called from HAL_UART_TxCpltCallback(). See STM32F7 HAL manual for detail | |
155 | + */ | |
156 | + | |
157 | + virtual bool TransmitCompleteCallback(void * const ptr); | |
158 | + /** | |
159 | + * \brief Call back for entire block transfer completion. | |
160 | + * \param ptr Pointer to UART_HandleTypeDef struct. | |
161 | + * \return true: ptr matches with UART device and handle the call back. false : doesn't match. | |
162 | + * \details | |
163 | + * A call back to notify the end of entire block transfer. | |
164 | + * This is considered as the end of DMA based receiving. | |
165 | + * The context have to be interrupt. | |
166 | + * | |
167 | + * This member function checks whether the given ptr parameter matches its own device, and if matched, | |
168 | + * Release the waiting task and return true. If it doesn't match, just return false. | |
169 | + * | |
170 | + * This method have to be called from HAL_UART_RxCpltCallback(). See STM32F7 HAL manual for detail */ | |
171 | + | |
172 | + virtual bool ReceiveCompleteCallback(void* const ptr); | |
173 | + /** | |
174 | + * @brief Error handling | |
175 | + * @param ptr Pointer to UART_HandleTypeDef struct. | |
176 | + * \return true: ptr matches with UART device and handle the error. false : doesn't match. | |
177 | + * @details | |
178 | + * A handle to print out the error message. | |
179 | + * | |
180 | + * Checks whether handle has error and if there is, print appropriate error. Then return. | |
181 | + */ | |
182 | + virtual bool HandleError(void * const ptr); | |
183 | +protected: | |
184 | + UART_HandleTypeDef* const peripheral_; | |
185 | + | |
186 | + Synchronizer * const tx_sync_; | |
187 | + Synchronizer * const rx_sync_; | |
188 | + | |
189 | + CriticalSection * const tx_critical_section_; | |
190 | + CriticalSection * const rx_critical_section_; | |
191 | +private: | |
192 | + /** | |
193 | + * @brief Return the Platform dependent device control handle. | |
194 | + * @return Handle of device. | |
195 | + * @details | |
196 | + * The handle is the pointer ( or some ID ) which specify the control data of | |
197 | + * specific device. | |
198 | + */ | |
199 | + virtual void * GetPeripheralHandle(); | |
200 | + | |
201 | +}; | |
202 | + | |
203 | +} /* namespace platform */ | |
204 | + | |
205 | +#endif // HAL_UART_MODULE_ENABLED | |
206 | + | |
207 | +#endif /* DEBUGGER_UART_HPP_ */ |
@@ -37,6 +37,7 @@ | ||
37 | 37 | |
38 | 38 | // Peripherals |
39 | 39 | #include "uart.hpp" |
40 | +#include "debuggeruart.hpp" | |
40 | 41 | #include "spimaster.hpp" |
41 | 42 | #include "spislavespecifier.hpp" |
42 | 43 | #include "i2cmaster.hpp" |
@@ -12,8 +12,8 @@ | ||
12 | 12 | <targetDefinitions> |
13 | 13 | <board id="nucleo-l152re"> |
14 | 14 | <name>NUCLEO-L152RE</name> |
15 | - <dbgIF>SWD</dbgIF> | |
16 | 15 | <dbgIF>JTAG</dbgIF> |
16 | + <dbgIF>SWD</dbgIF> | |
17 | 17 | <dbgDEV>ST-Link</dbgDEV> |
18 | 18 | <mcuId>stm32l152retx</mcuId> |
19 | 19 | </board> |
@@ -66,11 +66,18 @@ void InitPlatform() | ||
66 | 66 | // UART device setting for console interface. |
67 | 67 | // On Nucleo, the port connected to the USB port of ST-Link is |
68 | 68 | // referred here. |
69 | - murasaki::platform.uart_console = new murasaki::Uart(&huart2); | |
69 | + murasaki::platform.uart_console = new murasaki::DebuggerUart(&huart2); | |
70 | 70 | // UART is used for logging port. |
71 | 71 | // At least one logger is needed to run the debugger class. |
72 | 72 | murasaki::platform.logger = new murasaki::UartLogger(murasaki::platform.uart_console); |
73 | 73 | |
74 | + // Setting the debugger | |
75 | + murasaki::debugger = new murasaki::Debugger(murasaki::platform.logger); | |
76 | + // Set the debugger as AutoRePrint mode, for the easy operation. | |
77 | + murasaki::debugger->AutoRePrint(); // type any key to show history. | |
78 | + | |
79 | + | |
80 | + | |
74 | 81 | // For demonstration, one GPIO LED port is reserved. |
75 | 82 | // The port and pin names are defined by CubeMX. |
76 | 83 |
@@ -98,11 +105,6 @@ void InitPlatform() | ||
98 | 105 | murasaki::platform.u2_m95010 = |
99 | 106 | new murasaki::SpiSlaveSpecifier(0, 0, SPI_CS_GPIO_Port, SPI_CS_Pin); // POL=0, PHA=0 |
100 | 107 | |
101 | - // Setting the debugger | |
102 | - murasaki::debugger = new murasaki::Debugger(murasaki::platform.logger); | |
103 | - // Set the debugger as AutoRePrint mode, for the easy operation. | |
104 | - murasaki::debugger->AutoRePrint(); // type any key to show history. | |
105 | - | |
106 | 108 | } |
107 | 109 | |
108 | 110 | #define M24128_ADDR 0x50 |
@@ -10,6 +10,7 @@ set WORKAREASIZE 0x8000 | ||
10 | 10 | transport select "hla_swd" |
11 | 11 | |
12 | 12 | set CHIPNAME STM32L152RETx |
13 | +set BOARDNAME NUCLEO-L152RE | |
13 | 14 | |
14 | 15 | # Enable debug when in low power modes |
15 | 16 | set ENABLE_LOW_POWER 1 |