aboutsummaryrefslogtreecommitdiff
path: root/src/crc32.c
diff options
context:
space:
mode:
authorPaul Fertser2013-04-14 21:55:32 +0400
committerGareth McMullin2013-04-14 11:35:23 -0700
commit91b481731d14789a87b9e5db29e7b715bcbc618b (patch)
tree0971c94a2c8bab1770bb4e0cb7f0098c3dd2a302 /src/crc32.c
parent7db6e3e00c1419fd9c470dc743bdfaf20b197f91 (diff)
stm32f1/stm32f4: fix hardware CRC calculation
This was real-life tested on stm32f1 hardware including computation for odd-sized ranges. Signed-off-by: Paul Fertser <fercerpav@gmail.com>
Diffstat (limited to 'src/crc32.c')
-rw-r--r--src/crc32.c31
1 files changed, 20 insertions, 11 deletions
diff --git a/src/crc32.c b/src/crc32.c
index d5c8732..810a9dd 100644
--- a/src/crc32.c
+++ b/src/crc32.c
@@ -113,26 +113,35 @@ uint32_t generic_crc32(struct target_s *target, uint32_t base, int len)
uint32_t generic_crc32(struct target_s *target, uint32_t base, int len)
{
uint32_t data;
- uint8_t byte;
+ uint32_t crc;
+ size_t i;
- CRC_CR |= CRC_CR_RESET;
+ CRC_CR |= CRC_CR_RESET;
- while (len >3) {
- if (target_mem_read_words(target, &data, base, 1) != 0)
+ while (len > 3) {
+ if (target_mem_read_words(target, &data, base, 4) != 0)
return -1;
- CRC_DR = data;
- base+=4;
- len -= 4;
+ CRC_DR = __builtin_bswap32(data);
+ base += 4;
+ len -= 4;
}
+
+ crc = CRC_DR;
+
while (len--) {
- if (target_mem_read_bytes(target, &byte, base, 1) != 0)
+ if (target_mem_read_bytes(target, (uint8_t *)&data, base++, 1) != 0)
return -1;
- CRC_DR = byte;
- base++;
+ crc ^= data << 24;
+ for (i = 0; i < 8; i++) {
+ if (crc & 0x80000000)
+ crc = (crc << 1) ^ 0x4C11DB7;
+ else
+ crc <<= 1;
+ }
}
- return CRC_DR;
+ return crc;
}
#endif