テスト用のあれこれ共用フォルダ
修訂 | c12f9258baee7f46ef7950f09e7734f98ed36b0d (tree) |
---|---|
時間 | 2018-09-22 16:46:15 |
作者 | takemasa <suikan@user...> |
Commiter | takemasa |
Make error handling of the SPI error handling.
All error is now passed to application. And if the error is
unknown, it re-initialize the SPI.
Beside of SPI, some I2C syslog are changed.
@@ -33,7 +33,7 @@ class AbstractSpiMaster:public murasaki::AbstractPeripheral | ||
33 | 33 | * @param timeout_ms Timeout limit [mS] |
34 | 34 | * @return true if transfer complete, false if timeout |
35 | 35 | */ |
36 | - virtual bool TransmitAndReceive(murasaki::AbstractSpiSlaveSpecifier * spi_spec, | |
36 | + virtual SpiStatus TransmitAndReceive(murasaki::AbstractSpiSlaveSpecifier * spi_spec, | |
37 | 37 | const uint8_t * tx_data, |
38 | 38 | uint8_t * rx_data, unsigned int size, |
39 | 39 | murasaki::WaitMilliSeconds timeout_ms = murasaki::kwmsIndefinitely)=0; |
@@ -46,7 +46,6 @@ murasaki::I2cStatus I2cMaster::Transmit( | ||
46 | 46 | const uint8_t* tx_data, |
47 | 47 | unsigned int tx_size, |
48 | 48 | WaitMilliSeconds timeout_ms) { |
49 | - murasaki::I2cStatus result; | |
50 | 49 | |
51 | 50 | I2C_SYSLOG("Enter"); |
52 | 51 |
@@ -90,12 +89,11 @@ murasaki::I2cStatus I2cMaster::Transmit( | ||
90 | 89 | MURASAKI_SYSLOG(kfaI2cMaster, kseEmergency, "Error is not handled") |
91 | 90 | |
92 | 91 | } |
93 | - result = interrupt_status_; | |
94 | 92 | } |
95 | 93 | critical_section_->Leave(); |
96 | 94 | |
97 | 95 | I2C_SYSLOG("Return"); |
98 | - return result; | |
96 | + return interrupt_status_; | |
99 | 97 | } |
100 | 98 | |
101 | 99 | murasaki::I2cStatus I2cMaster::Receive( |
@@ -103,7 +101,6 @@ murasaki::I2cStatus I2cMaster::Receive( | ||
103 | 101 | uint8_t* rx_data, |
104 | 102 | unsigned int rx_size, |
105 | 103 | WaitMilliSeconds timeout_ms) { |
106 | - murasaki::I2cStatus result; | |
107 | 104 | |
108 | 105 | I2C_SYSLOG("Enter"); |
109 | 106 |
@@ -149,13 +146,12 @@ murasaki::I2cStatus I2cMaster::Receive( | ||
149 | 146 | MURASAKI_SYSLOG(kfaI2cMaster, kseEmergency, "Error is not handled") |
150 | 147 | |
151 | 148 | } |
152 | - result = interrupt_status_; | |
153 | 149 | |
154 | 150 | } |
155 | 151 | critical_section_->Leave(); |
156 | 152 | |
157 | 153 | I2C_SYSLOG("Return"); |
158 | - return result; | |
154 | + return interrupt_status_; | |
159 | 155 | } |
160 | 156 | |
161 | 157 | murasaki::I2cStatus I2cMaster::TransmitThenReceive( |
@@ -255,15 +251,11 @@ murasaki::I2cStatus I2cMaster::TransmitThenReceive( | ||
255 | 251 | |
256 | 252 | } |
257 | 253 | |
258 | - result = interrupt_status_; | |
259 | - | |
260 | - | |
261 | - | |
262 | 254 | } |
263 | 255 | critical_section_->Leave(); |
264 | 256 | |
265 | 257 | I2C_SYSLOG("Return"); |
266 | - return result; // return false if timeout | |
258 | + return interrupt_status_; // return false if timeout | |
267 | 259 | } |
268 | 260 | |
269 | 261 | bool I2cMaster::TransmitCompleteCallback(void* ptr) { |
@@ -315,21 +307,21 @@ bool I2cMaster::HandleError(void* ptr) { | ||
315 | 307 | if (peripheral_ == ptr) { |
316 | 308 | // Check error and halde it. |
317 | 309 | if (peripheral_->ErrorCode & HAL_I2C_ERROR_AF) { |
318 | - I2C_SYSLOG("HAL_I2C_ERROR_AF"); | |
310 | + MURASAKI_SYSLOG(kfaI2cMaster, kseWarning, "HAL_I2C_ERROR_AF"); | |
319 | 311 | // This interrupt happen when device doesn't respond or return NAK. |
320 | 312 | interrupt_status_ = murasaki::ki2csNak; |
321 | 313 | // abort the processing |
322 | 314 | sync_->Release(); |
323 | 315 | } |
324 | 316 | else if (peripheral_->ErrorCode & HAL_I2C_ERROR_BERR) { |
325 | - I2C_SYSLOG("HAL_I2C_ERROR_BERR"); | |
317 | + MURASAKI_SYSLOG(kfaI2cMaster, kseWarning, "HAL_I2C_ERROR_BERR"); | |
326 | 318 | // This interrupt happen when device |
327 | 319 | interrupt_status_ = murasaki::ki2csBussError; |
328 | 320 | // abort the processing |
329 | 321 | sync_->Release(); |
330 | 322 | } |
331 | 323 | else if (peripheral_->ErrorCode & HAL_I2C_ERROR_ARLO) { |
332 | - I2C_SYSLOG("HAL_I2C_ERROR_ARLO"); | |
324 | + MURASAKI_SYSLOG(kfaI2cMaster, kseWarning, "HAL_I2C_ERROR_ARLO"); | |
333 | 325 | // This interrupt happen when device |
334 | 326 | interrupt_status_ = murasaki::ki2csArbitrationLost; |
335 | 327 | // abort the processing |
@@ -338,12 +330,8 @@ bool I2cMaster::HandleError(void* ptr) { | ||
338 | 330 | else { |
339 | 331 | MURASAKI_SYSLOG(kfaI2cMaster, kseEmergency, "Error is not handled"); |
340 | 332 | |
341 | - MURASAKI_PRINT_ERROR(peripheral_->ErrorCode & HAL_I2C_ERROR_BERR); // handled in "if" clause | |
342 | - MURASAKI_PRINT_ERROR(peripheral_->ErrorCode & HAL_I2C_ERROR_ARLO); // handled in "if" clause | |
343 | - MURASAKI_PRINT_ERROR(peripheral_->ErrorCode & HAL_I2C_ERROR_AF); // handled in "if" clause | |
344 | 333 | MURASAKI_PRINT_ERROR(peripheral_->ErrorCode & HAL_I2C_ERROR_OVR); // Doesn't occur in master |
345 | 334 | MURASAKI_PRINT_ERROR(peripheral_->ErrorCode & HAL_I2C_ERROR_DMA); // Doesn't occur in this implemenattion |
346 | - MURASAKI_PRINT_ERROR(peripheral_->ErrorCode & HAL_I2C_ERROR_TIMEOUT); // Doesn't occur in this implemenattion | |
347 | 335 | #ifdef HAL_I2C_ERROR_SIZE |
348 | 336 | MURASAKI_PRINT_ERROR(peripheral_->ErrorCode & HAL_I2C_ERROR_SIZE); |
349 | 337 | #endif |
@@ -63,6 +63,15 @@ namespace murasaki { | ||
63 | 63 | * |
64 | 64 | * Both methods can be called from only the task context. If these are called in the ISR |
65 | 65 | * context, the result is unknown. |
66 | + * | |
67 | + * * Note : In case an time out occurs during transmit / receive, this implementation | |
68 | + * casells HAL_I2C_MASTER_ABORT_IT(). But it is unknown whether this is right thing to do. | |
69 | + * The HAL reference of the STM32F7 is not clear for this case. For example, it doesn't tell | |
70 | + * what programmer do to stop the transfer at the middle. And also, it doesn't tell what's happen | |
71 | + * if the HAL_I2C_MASTER_ABORT_IT() is called. | |
72 | + * | |
73 | + * According to the source code of the HAL_I2C_MASTER_ABORT_IT(), no interrupt will be | |
74 | + * raised by this API call. | |
66 | 75 | */ |
67 | 76 | class I2cMaster : public AbstractI2CMaster |
68 | 77 | { |
@@ -208,7 +208,8 @@ enum SpiStatus | ||
208 | 208 | kspisOverflow, //!< Over run. |
209 | 209 | kspisFrameError, //!< Error on TI frame mode. |
210 | 210 | kspisDMA, //!< DMA error |
211 | - kspisErrorFlag //!< Other error flag. | |
211 | + kspisErrorFlag, //!< Other error flag. | |
212 | + kspisAbort //!< Problem in abort process. No way to recover. | |
212 | 213 | }; |
213 | 214 | |
214 | 215 |
@@ -41,13 +41,12 @@ SpiMaster::~SpiMaster() | ||
41 | 41 | |
42 | 42 | } |
43 | 43 | |
44 | -bool SpiMaster::TransmitAndReceive(murasaki::AbstractSpiSlaveSpecifier* spi_spec, | |
44 | +SpiStatus SpiMaster::TransmitAndReceive(murasaki::AbstractSpiSlaveSpecifier* spi_spec, | |
45 | 45 | const uint8_t* tx_data, |
46 | 46 | uint8_t* rx_data, |
47 | 47 | unsigned int size, |
48 | 48 | murasaki::WaitMilliSeconds timeout_ms) |
49 | 49 | { |
50 | - bool result; | |
51 | 50 | |
52 | 51 | SPIM_SYSLOG("Enter"); |
53 | 52 |
@@ -61,6 +60,9 @@ bool SpiMaster::TransmitAndReceive(murasaki::AbstractSpiSlaveSpecifier* spi_spec | ||
61 | 60 | { |
62 | 61 | SPIM_SYSLOG("Start re-configuring SPI master"); |
63 | 62 | |
63 | + // This value will be updated by TransmitAndReceiveCompleteCallback | |
64 | + interrupt_status_ = murasaki::kspisTimeOut; | |
65 | + | |
64 | 66 | // Change the clock porarity & phase |
65 | 67 | // todo is following right? |
66 | 68 | MURASAKI_ASSERT(HAL_SPI_DeInit(peripheral_) == HAL_OK); |
@@ -91,7 +93,28 @@ bool SpiMaster::TransmitAndReceive(murasaki::AbstractSpiSlaveSpecifier* spi_spec | ||
91 | 93 | MURASAKI_ASSERT(HAL_OK == status); |
92 | 94 | |
93 | 95 | // wait for the completion |
94 | - result = sync_->Wait(timeout_ms); // return false if timeout | |
96 | + sync_->Wait(timeout_ms); // return false if timeout | |
97 | + SPIM_SYSLOG("Sync released.") | |
98 | + | |
99 | + // check the status from interrupt | |
100 | + switch (interrupt_status_) | |
101 | + { | |
102 | + case murasaki::kspisOK: | |
103 | + SPIM_SYSLOG("Receive complete successfully") | |
104 | + break; | |
105 | + case murasaki::ki2csTimeOut: | |
106 | + MURASAKI_SYSLOG(kfaSpiMaster, kseWarning, "Receive timeout") | |
107 | + // Abort on-going and not terminated transfer. | |
108 | + HAL_SPI_DMAStop(peripheral_); | |
109 | + break; | |
110 | + default: | |
111 | + MURASAKI_SYSLOG(kfaI2cMaster, kseEmergency, "Error is not handled") | |
112 | + SPIM_SYSLOG("Re-initialize the SPI") | |
113 | + // Desable SPI to try to clear the current error status. Then, re-enable. | |
114 | + HAL_SPI_DeInit(peripheral_); | |
115 | + HAL_SPI_Init(peripheral_); | |
116 | + | |
117 | + } | |
95 | 118 | |
96 | 119 | SPIM_SYSLOG("End SPI master transferring"); |
97 | 120 | } |
@@ -101,7 +124,7 @@ bool SpiMaster::TransmitAndReceive(murasaki::AbstractSpiSlaveSpecifier* spi_spec | ||
101 | 124 | critical_section_->Leave(); |
102 | 125 | |
103 | 126 | SPIM_SYSLOG("Return"); |
104 | - return result; | |
127 | + return interrupt_status_; | |
105 | 128 | |
106 | 129 | } |
107 | 130 |
@@ -114,12 +137,17 @@ bool SpiMaster::TransmitAndReceiveCompleteCallback(void* ptr) | ||
114 | 137 | // if matches, release task |
115 | 138 | if (peripheral_ == ptr) { |
116 | 139 | SPIM_SYSLOG("Release sync"); |
140 | + // report normal completion | |
141 | + interrupt_status_ = murasaki::kspisOK; | |
142 | + // release waiting task | |
117 | 143 | sync_->Release(); |
118 | 144 | SPIM_SYSLOG("Return"); |
145 | + // This interrupt is for this device. | |
119 | 146 | return true; |
120 | 147 | } |
121 | 148 | else { |
122 | 149 | SPIM_SYSLOG("Return"); |
150 | + // This interrupt is not for this device. | |
123 | 151 | return false; |
124 | 152 | } |
125 | 153 | } |
@@ -131,16 +159,57 @@ bool SpiMaster::HandleError(void* ptr) | ||
131 | 159 | MURASAKI_ASSERT(nullptr != ptr) |
132 | 160 | |
133 | 161 | if (peripheral_ == ptr) { |
134 | - // Check error, and print if exist. | |
135 | - MURASAKI_PRINT_ERROR(peripheral_->ErrorCode & HAL_SPI_ERROR_MODF); | |
136 | - MURASAKI_PRINT_ERROR(peripheral_->ErrorCode & HAL_SPI_ERROR_CRC); | |
137 | - MURASAKI_PRINT_ERROR(peripheral_->ErrorCode & HAL_SPI_ERROR_OVR); | |
138 | - MURASAKI_PRINT_ERROR(peripheral_->ErrorCode & HAL_SPI_ERROR_FRE); | |
139 | - MURASAKI_PRINT_ERROR(peripheral_->ErrorCode & HAL_SPI_ERROR_DMA); | |
140 | - MURASAKI_PRINT_ERROR(peripheral_->ErrorCode & HAL_SPI_ERROR_FLAG); | |
162 | + | |
163 | + // Check error and halde it. | |
164 | + if (peripheral_->ErrorCode & HAL_SPI_ERROR_CRC) { | |
165 | + MURASAKI_SYSLOG(kfaSpiMaster, kseWarning, "HAL_SPI_ERROR_CRC"); | |
166 | + // This happens only in the CRC mode | |
167 | + interrupt_status_ = murasaki::kspisModeCRC; | |
168 | + // abort the processing | |
169 | + sync_->Release(); | |
170 | + } | |
171 | + else if (peripheral_->ErrorCode & HAL_SPI_ERROR_OVR) { | |
172 | + MURASAKI_SYSLOG(kfaSpiMaster, kseWarning, "HAL_SPI_ERROR_OVR"); | |
173 | + // This interrupt happen when the DMA is too slow to handle the received data. | |
174 | + interrupt_status_ = murasaki::kspisOverflow; | |
175 | + // abort the processing | |
176 | + sync_->Release(); | |
177 | + } | |
178 | + else if (peripheral_->ErrorCode & HAL_SPI_ERROR_FRE) { | |
179 | + MURASAKI_SYSLOG(kfaSpiMaster, kseWarning, "HAL_SPI_ERROR_FRE"); | |
180 | + // This interrupt is the frame error of the the TI frame mode | |
181 | + interrupt_status_ = murasaki::kspisFrameError; | |
182 | + // abort the processing | |
183 | + sync_->Release(); | |
184 | + } | |
185 | + else if (peripheral_->ErrorCode & HAL_SPI_ERROR_DMA) { | |
186 | + MURASAKI_SYSLOG(kfaSpiMaster, kseWarning, "HAL_SPI_ERROR_DMA"); | |
187 | + // This interrupt emans something happen in DMA unit | |
188 | + interrupt_status_ = murasaki::kspisDMA; | |
189 | + // abort the processing | |
190 | + sync_->Release(); | |
191 | + } | |
192 | + else if (peripheral_->ErrorCode & HAL_SPI_ERROR_FLAG) { | |
193 | + MURASAKI_SYSLOG(kfaSpiMaster, kseWarning, "HAL_SPI_ERROR_FLAG"); | |
194 | + // This interrupt emans something is recorded as error flag. | |
195 | + interrupt_status_ = murasaki::kspisErrorFlag; | |
196 | + // abort the processing | |
197 | + sync_->Release(); | |
198 | + } | |
141 | 199 | #ifdef HAL_SPI_ERROR_ABORT |
142 | - MURASAKI_PRINT_ERROR(peripheral_->ErrorCode & HAL_SPI_ERROR_ABORT); | |
200 | + else if (peripheral_->ErrorCode & HAL_SPI_ERROR_ABORT) { | |
201 | + MURASAKI_SYSLOG(kfaSpiMaster, kseWarning, "HAL_SPI_ERROR_ABORT"); | |
202 | + // This interrupt happen when program causes problem during abort process | |
203 | + // No way to recover. | |
204 | + interrupt_status_ = murasaki::kspisAbort; | |
205 | + // abort the processing | |
206 | + sync_->Release(); | |
207 | + } | |
143 | 208 | #endif |
209 | + else | |
210 | + { | |
211 | + MURASAKI_SYSLOG(kfaSpiMaster, kseWarning, "Unknown error interrupt") | |
212 | + } | |
144 | 213 | SPIM_SYSLOG("Return"); |
145 | 214 | return true; // report the ptr matched |
146 | 215 | } |
@@ -57,6 +57,13 @@ namespace murasaki { | ||
57 | 57 | * |
58 | 58 | * Both methods can be called from only the task context. If these are called in the ISR |
59 | 59 | * context, the result is unknown. |
60 | + * | |
61 | + * Note : The behavior of when the timeout happen is not tested. Actually, it should not happen | |
62 | + * because DMA is taken in SPI transmission. Murasaki stpos internal DMA, interrupt and SPI processing | |
63 | + * internally then, return. | |
64 | + * | |
65 | + * Other error will cause the re-initializing of the SPI master. Murasaki doesn't support | |
66 | + * any of CRC detection, TI frame mode or Multi-master SPI. | |
60 | 67 | * @ingroup MURASAKI_GROUP |
61 | 68 | */ |
62 | 69 | class SpiMaster : public AbstractSpiMaster |
@@ -83,7 +90,7 @@ class SpiMaster : public AbstractSpiMaster | ||
83 | 90 | * from the spi_spec. And then, assert the chips elect through the spi_spec during the |
84 | 91 | * data transfer. |
85 | 92 | */ |
86 | - virtual bool TransmitAndReceive(murasaki::AbstractSpiSlaveSpecifier * spi_spec, | |
93 | + virtual SpiStatus TransmitAndReceive(murasaki::AbstractSpiSlaveSpecifier * spi_spec, | |
87 | 94 | const uint8_t * tx_data, |
88 | 95 | uint8_t * rx_data, unsigned int size, |
89 | 96 | murasaki::WaitMilliSeconds timeout_ms = murasaki::kwmsIndefinitely); |
@@ -116,6 +123,8 @@ class SpiMaster : public AbstractSpiMaster | ||
116 | 123 | SPI_HandleTypeDef * const peripheral_; // SPI peripheral handler. |
117 | 124 | Synchronizer * const sync_; // sync between task and interrupt |
118 | 125 | CriticalSection * const critical_section_; // protect memberfunction |
126 | + private: | |
127 | + SpiStatus interrupt_status_; | |
119 | 128 | }; |
120 | 129 | |
121 | 130 | } /* namespace murasaki */ |
@@ -10,7 +10,6 @@ set WORKAREASIZE 0x8000 | ||
10 | 10 | transport select "hla_swd" |
11 | 11 | |
12 | 12 | set CHIPNAME STM32L152RETx |
13 | -set BOARDNAME NUCLEO-L152RE | |
14 | 13 | |
15 | 14 | # Enable debug when in low power modes |
16 | 15 | set ENABLE_LOW_POWER 1 |