Added lfs_crc32c

crc32c, with a polynomial of 0x11edc6f41, is generally numerically superior
to the more common crc32 standard. Catching more bit errors across
a wider range of message messages (except 2-bit errors) without any changes
to the underlying algorithm.

Philip Koopman has a large body of work exploring optimal polynomials here:
http://users.ece.cmu.edu/~koopman/crc/crc32.html

And from his experiments we know the maximum message size where we can
still detect a given number of bit errors for each polynomial:

                       1          2          3    4    5   6   7  8  9 10 11 12 13 14 15 16 17
  crc32  0x104c11db7 = ∞ 4294967263      91607 2974  268 171  91 57 34 21 12 10 10 10  -  -  -
  crc32c 0x11edc6f41 = ∞ 2147483615 2147483615 5243 5243 177 177 47 47 20 20  8  8  6  6  1  1

So really crc32c should be prefered where possible. Koopman also has
alternative polynomials with slightly different properties, but crc32c
is already popular enough to have a decent amount of hardware support.

---

Another nice feature of crc32c is that its polynomial has even parity.
It turns out that even-parity polynomials give us the nifty property
parity(crc(m)) == parity(m).

A quick proof:

  crc(m) = m(x) x^|P|-1 mod P(x)

  parity(m) = m(x) x mod x+1

  though note: x mod x+1 = 1, by hand
  so:

  parity(m) = m(x)*1 mod x+1
            = m(x) mod x+1

  solving for parity(crc(m)):

  parity(crc(m)) = (m(x) x^|P|-1 mod P(x)) mod x+1

  note: (a mod b) mod c = a mod c, if c divides b,
    aka (a mod b) mod c = a mod c, if b mod c = 0

  so if P(x) mod x+1 = 0,
    aka if parity(P) = 0:

  parity(crc(m)) = m(x) x^|P|-1 mod x+1

  but, like before: x^|P|-1 mod x+1 = 1, by hand
  so:

  parity(crc(m)) = m(x)*1 mod x+1
                 = m(x) mod x+1
                 = parity(m)

  so if parity(P) = 0:

  parity(crc(m)) = parity(m)

This has the potential to replace the 1-bit counter in the metadata tags
with a more general solution that doesn't require extra state.
This commit is contained in:
Christopher Haster
2022-12-17 22:42:07 -06:00
parent 2d272bb62a
commit 0f72d18b14
2 changed files with 129 additions and 0 deletions
+9
View File
@@ -215,6 +215,15 @@ static inline uint32_t lfs_tobe32(uint32_t a) {
// Calculate CRC-32 with polynomial = 0x04c11db7
uint32_t lfs_crc(uint32_t crc, const void *buffer, size_t size);
// Calculate crc32c incrementally
//
// polynomial = 0x11edc6f41
// init = 0xffffffff
// fini = 0xffffffff
//
uint32_t lfs_crc32c(uint32_t crc, const void *buffer, size_t size);
// Allocate memory, only used if buffers are not provided to littlefs
// Note, memory must be 64-bit aligned
static inline void *lfs_malloc(size_t size) {