@@ -31,6 +31,14 @@ static cyhal_crc_t cy_crc;
31
31
static crc_algorithm_t cy_crc_cfg ;
32
32
static bool cy_crc_initialized = false;
33
33
34
+ // Reverses width least significant bits of 32 bit input. Any bits more
35
+ // significant than width are dropped.
36
+ static uint32_t reverse (uint8_t width , uint32_t in )
37
+ {
38
+ MBED_ASSERT (width <= 32 );
39
+ return __RBIT (in ) >> (32 - width );
40
+ }
41
+
34
42
void hal_crc_compute_partial_start (const crc_mbed_config_t * config )
35
43
{
36
44
if (!cy_crc_initialized ) {
@@ -46,9 +54,17 @@ void hal_crc_compute_partial_start(const crc_mbed_config_t *config)
46
54
cy_crc_cfg .polynomial = config -> polynomial ;
47
55
cy_crc_cfg .lfsrInitState = config -> initial_xor ;
48
56
cy_crc_cfg .dataXor = 0 ;
49
- cy_crc_cfg .remXor = config -> final_xor ;
50
57
cy_crc_cfg .dataReverse = config -> reflect_in ? 1 : 0 ;
51
58
cy_crc_cfg .remReverse = config -> reflect_out ? 1 : 0 ;
59
+
60
+ // There is an incongruity between what MBeds CRC spec expects and what
61
+ // PSoC6 hardware actually performs when it comes to the final XOR and
62
+ // remainder reversal: MBed expects the final remainder to be reversed then
63
+ // XORed with remXor while PSoC6s CRC, however, performs the final XOR with
64
+ // remXor then reverses the resulting value. Since Rev(A) XOR B == Rev( A
65
+ // XOR Rev(B) ), a simple fix is to reverse remXor if reflect_out is true.
66
+ cy_crc_cfg .remXor = config -> reflect_out ? reverse (config -> width , config -> final_xor ) : config -> final_xor ;
67
+
52
68
if (CY_RSLT_SUCCESS != cyhal_crc_start (& cy_crc , & cy_crc_cfg )) {
53
69
MBED_ERROR (MBED_MAKE_ERROR (MBED_MODULE_DRIVER , MBED_ERROR_CODE_FAILED_OPERATION ), "cyhal_crc_start" );
54
70
}
0 commit comments