19
19
#include " drivers/TableCRC.h"
20
20
#include " hal/crc_api.h"
21
21
#include " platform/mbed_assert.h"
22
+ #include " platform/SingletonPtr.h"
23
+ #include " platform/PlatformMutex.h"
22
24
23
25
/* This is invalid warning from the compiler for below section of code
24
26
if ((width < 8) && (NULL == _crc_table)) {
@@ -45,6 +47,7 @@ namespace mbed {
45
47
* ROM polynomial tables for supported polynomials (:: crc_polynomial_t) will be used for
46
48
* software CRC computation, if ROM tables are not available then CRC is computed runtime
47
49
* bit by bit for all data input.
50
+ * @note Synchronization level: Thread safe
48
51
*
49
52
* @tparam polynomial CRC polynomial value in hex
50
53
* @tparam width CRC polynomial width
@@ -79,21 +82,22 @@ namespace mbed {
79
82
* uint32_t crc = 0;
80
83
*
81
84
* printf("\nPolynomial = 0x%lx Width = %d \n", ct.get_polynomial(), ct.get_width());
82
- *
83
85
* ct.compute_partial_start(&crc);
84
86
* ct.compute_partial((void *)&test, 4, &crc);
85
87
* ct.compute_partial((void *)&test[4], 5, &crc);
86
88
* ct.compute_partial_stop(&crc);
87
- *
88
89
* printf("The CRC of data \"123456789\" is : 0x%lx\n", crc);
89
90
* return 0;
90
91
* }
91
92
* @endcode
92
93
* @ingroup drivers
93
94
*/
94
95
96
+ extern SingletonPtr<PlatformMutex> mbed_crc_mutex;
97
+
95
98
template <uint32_t polynomial = POLY_32BIT_ANSI, uint8_t width = 32 >
96
99
class MbedCRC {
100
+
97
101
public:
98
102
enum CrcMode
99
103
{
@@ -104,7 +108,6 @@ class MbedCRC {
104
108
BITWISE
105
109
};
106
110
107
- public:
108
111
typedef uint64_t crc_data_size_t ;
109
112
110
113
/* * Lifetime of CRC object
@@ -113,7 +116,7 @@ class MbedCRC {
113
116
* @param final_xor Final Xor value
114
117
* @param reflect_data
115
118
* @param reflect_remainder
116
- * @note Default constructor without any arguments is valid only for supported CRC polynomials. :: crc_polynomial_t
119
+ * @note Default constructor without any arguments is valid only for supported CRC polynomials. :: crc_polynomial_t
117
120
* MbedCRC <POLY_7BIT_SD, 7> ct; --- Valid POLY_7BIT_SD
118
121
* MbedCRC <0x1021, 16> ct; --- Valid POLY_16BIT_CCITT
119
122
* MbedCRC <POLY_16BIT_CCITT, 32> ct; --- Invalid, compilation error
@@ -135,6 +138,8 @@ class MbedCRC {
135
138
}
136
139
137
140
/* * Compute CRC for the data input
141
+ * Compute CRC performs the initialization, computation and collection of
142
+ * final CRC.
138
143
*
139
144
* @param buffer Data bytes
140
145
* @param size Size of data
@@ -144,52 +149,73 @@ class MbedCRC {
144
149
int32_t compute (void *buffer, crc_data_size_t size, uint32_t *crc)
145
150
{
146
151
MBED_ASSERT (crc != NULL );
147
- int32_t status;
148
- if (0 != (status = compute_partial_start (crc))) {
149
- *crc = 0 ;
152
+ int32_t status = 0 ;
153
+
154
+ status = compute_partial_start (crc);
155
+ if (0 != status) {
156
+ unlock ();
150
157
return status;
151
158
}
152
- if (0 != (status = compute_partial (buffer, size, crc))) {
153
- *crc = 0 ;
159
+
160
+ status = compute_partial (buffer, size, crc);
161
+ if (0 != status) {
162
+ unlock ();
154
163
return status;
155
164
}
156
- if (0 != (status = compute_partial_stop (crc))) {
157
- *crc = 0 ;
158
- return status;
165
+
166
+ status = compute_partial_stop (crc);
167
+ if (0 != status) {
168
+ *crc = 0 ;
159
169
}
160
- return 0 ;
170
+
171
+ return status;
172
+
161
173
}
162
174
163
175
/* * Compute partial CRC for the data input.
164
176
*
165
177
* CRC data if not available fully, CRC can be computed in parts with available data.
166
- * Previous CRC output should be passed as argument to the current compute_partial call.
167
- * @pre: Call \ref compute_partial_start to start the partial CRC calculation.
168
- * @post: Call \ref compute_partial_stop to get the final CRC value.
178
+ *
179
+ * In case of hardware, intermediate values and states are saved by hardware and mutex
180
+ * locking is used to serialize access to hardware CRC.
181
+ *
182
+ * In case of software CRC, previous CRC output should be passed as argument to the
183
+ * current compute_partial call. Please note the intermediate CRC value is maintained by
184
+ * application and not the driver.
185
+ *
186
+ * @pre: Call `compute_partial_start` to start the partial CRC calculation.
187
+ * @post: Call `compute_partial_stop` to get the final CRC value.
169
188
*
170
189
* @param buffer Data bytes
171
190
* @param size Size of data
172
191
* @param crc CRC value is intermediate CRC value filled by API.
173
192
* @return 0 on success or a negative error code on failure
174
- * @note: CRC as output in compute_partial is not final CRC value, call @ref compute_partial_stop
193
+ * @note: CRC as output in compute_partial is not final CRC value, call ` compute_partial_stop`
175
194
* to get final correct CRC value.
176
195
*/
177
196
int32_t compute_partial (void *buffer, crc_data_size_t size, uint32_t *crc)
178
197
{
198
+ int32_t status = 0 ;
199
+
179
200
switch (_mode) {
180
201
#ifdef DEVICE_CRC
181
202
case HARDWARE:
182
203
hal_crc_compute_partial ((uint8_t *)buffer, size);
183
204
*crc = 0 ;
184
- return 0 ;
205
+ break ;
185
206
#endif
186
207
case TABLE:
187
- return table_compute_partial (buffer, size, crc);
208
+ status = table_compute_partial (buffer, size, crc);
209
+ break ;
188
210
case BITWISE:
189
- return bitwise_compute_partial (buffer, size, crc);
211
+ status = bitwise_compute_partial (buffer, size, crc);
212
+ break ;
213
+ default :
214
+ status = -1 ;
215
+ break ;
190
216
}
191
217
192
- return - 1 ;
218
+ return status ;
193
219
}
194
220
195
221
/* * Compute partial start, indicate start of partial computation
@@ -200,14 +226,15 @@ class MbedCRC {
200
226
* @param crc Initial CRC value set by the API
201
227
* @return 0 on success or a negative in case of failure
202
228
* @note: CRC is an out parameter and must be reused with compute_partial
203
- * and compute_partial_stop without any modifications in application.
229
+ * and ` compute_partial_stop` without any modifications in application.
204
230
*/
205
231
int32_t compute_partial_start (uint32_t *crc)
206
232
{
207
233
MBED_ASSERT (crc != NULL );
208
234
209
235
#ifdef DEVICE_CRC
210
236
if (_mode == HARDWARE) {
237
+ lock ();
211
238
crc_mbed_config_t config;
212
239
config.polynomial = polynomial;
213
240
config.width = width;
@@ -218,7 +245,7 @@ class MbedCRC {
218
245
219
246
hal_crc_compute_partial_start (&config);
220
247
}
221
- #endif // DEVICE_CRC
248
+ #endif
222
249
223
250
*crc = _initial_value;
224
251
return 0 ;
@@ -239,6 +266,7 @@ class MbedCRC {
239
266
#ifdef DEVICE_CRC
240
267
if (_mode == HARDWARE) {
241
268
*crc = hal_crc_get_result ();
269
+ unlock ();
242
270
return 0 ;
243
271
}
244
272
#endif
@@ -252,6 +280,7 @@ class MbedCRC {
252
280
} else {
253
281
*crc = (reflect_remainder (p_crc) ^ _final_xor) & get_crc_mask ();
254
282
}
283
+ unlock ();
255
284
return 0 ;
256
285
}
257
286
@@ -281,6 +310,28 @@ class MbedCRC {
281
310
uint32_t *_crc_table;
282
311
CrcMode _mode;
283
312
313
+ /* * Acquire exclusive access to CRC hardware/software
314
+ */
315
+ void lock ()
316
+ {
317
+ #ifdef DEVICE_CRC
318
+ if (_mode == HARDWARE) {
319
+ mbed_crc_mutex->lock ();
320
+ }
321
+ #endif
322
+ }
323
+
324
+ /* * Release exclusive access to CRC hardware/software
325
+ */
326
+ virtual void unlock ()
327
+ {
328
+ #ifdef DEVICE_CRC
329
+ if (_mode == HARDWARE) {
330
+ mbed_crc_mutex->unlock ();
331
+ }
332
+ #endif
333
+ }
334
+
284
335
/* * Get the current CRC data size
285
336
*
286
337
* @return CRC data size in bytes
0 commit comments