diff --git a/ion/Makefile b/ion/Makefile index b21aab92c..595b2a67a 100644 --- a/ion/Makefile +++ b/ion/Makefile @@ -1,2 +1,6 @@ SFLAGS += -Iion/include -DKD_CONFIG_H=1 include ion/src/$(PLATFORM)/Makefile + +tests += $(addprefix ion/test/,\ + crc32.cpp\ +) diff --git a/ion/include/ion.h b/ion/include/ion.h index 77de5fb56..7bcd82748 100644 --- a/ion/include/ion.h +++ b/ion/include/ion.h @@ -8,6 +8,8 @@ #include #include #include +#include +#include /* ION is not your regular library. It is a library you link against, but it @@ -26,6 +28,10 @@ void usleep(long us); /* CAUTION: This is a complete reset! */ void reset(); +// CRC32 : non xor-ed, non reversed, direct, polynomial 4C11DB7 +// Only accepts whole 32bit values +uint32_t crc32(const uint32_t * data, size_t length); + } #endif diff --git a/ion/src/device/device.cpp b/ion/src/device/device.cpp index 74fac25cb..91f706b93 100644 --- a/ion/src/device/device.cpp +++ b/ion/src/device/device.cpp @@ -26,6 +26,21 @@ void Ion::usleep(long us) { } } +uint32_t Ion::crc32(const uint32_t * data, size_t length) { + bool initialCRCEngineState = RCC.AHB1ENR()->getCRCEN(); + RCC.AHB1ENR()->setCRCEN(true); + CRC.CR()->setRESET(true); + + const uint32_t * end = data + length; + while (data < end) { + CRC.DR()->set(*data++); + } + + uint32_t result = CRC.DR()->get(); + RCC.AHB1ENR()->setCRCEN(initialCRCEngineState); + return result; +} + void Ion::reset() { CM4.AIRCR()->requestReset(); } diff --git a/ion/src/device/regs/crc.h b/ion/src/device/regs/crc.h new file mode 100644 index 000000000..6ae4a2c10 --- /dev/null +++ b/ion/src/device/regs/crc.h @@ -0,0 +1,27 @@ +#ifndef REGS_CRC_H +#define REGS_CRC_H + +#include "register.h" + +class CRC { +public: + class DR : public Register32 { + }; + + class CR : Register32 { + public: + REGS_BOOL_FIELD(RESET, 0); + }; + + constexpr CRC() {}; + REGS_REGISTER_AT(DR, 0x00); + REGS_REGISTER_AT(CR, 0x08); +private: + constexpr uint32_t Base() const { + return 0x40023000; + }; +}; + +constexpr CRC CRC; + +#endif diff --git a/ion/src/device/regs/regs.h b/ion/src/device/regs/regs.h index f030ac281..c37219c36 100644 --- a/ion/src/device/regs/regs.h +++ b/ion/src/device/regs/regs.h @@ -2,6 +2,7 @@ #define REGS_REGS_H #include "adc.h" +#include "crc.h" #include "exti.h" #include "cm4.h" #include "fsmc.h" diff --git a/ion/src/shared/crc32.cpp b/ion/src/shared/crc32.cpp new file mode 100644 index 000000000..9f2e93d53 --- /dev/null +++ b/ion/src/shared/crc32.cpp @@ -0,0 +1,23 @@ +#include + +constexpr uint32_t polynomial = 0x04C11DB7; + +static uint32_t crc32(uint32_t crc, uint8_t data) { + crc ^= data << 24; + for (int i=8; i--;) { + crc = crc & 0x80000000 ? ((crc<<1)^polynomial) : (crc << 1); + } + return crc; +} + +uint32_t Ion::crc32(const uint32_t * data, size_t length) { + uint32_t crc = 0xFFFFFFFF; + for (int i=0; i> 24) & 0xFF)); + crc = ::crc32(crc, (uint8_t)((data[i] >> 16) & 0xFF)); + crc = ::crc32(crc, (uint8_t)((data[i] >> 8) & 0xFF)); + crc = ::crc32(crc, (uint8_t)(data[i] & 0xFF)); + } + return crc; +} diff --git a/ion/src/simulator/Makefile b/ion/src/simulator/Makefile index d2e5f6ab2..964468a1d 100644 --- a/ion/src/simulator/Makefile +++ b/ion/src/simulator/Makefile @@ -4,6 +4,9 @@ objs += $(addprefix ion/src/simulator/, \ battery.o\ init.o\ ) +objs += $(addprefix ion/src/shared/, \ + crc32.o\ +) objs += $(addprefix ion/src/simulator/boot/, main.o) objs += $(addprefix ion/src/simulator/display/, fltklcd.o) objs += $(addprefix ion/src/simulator/keyboard/, fltkkbd.o) diff --git a/ion/test/crc32.cpp b/ion/test/crc32.cpp new file mode 100644 index 000000000..be5cb1f65 --- /dev/null +++ b/ion/test/crc32.cpp @@ -0,0 +1,10 @@ +#include +#include +#include + +QUIZ_CASE(ion_crc32) { + uint32_t input[] = { 0x48656C6C, 0x6F2C2077 }; + assert(Ion::crc32(input, 1) == 0x93591FFD); + assert(Ion::crc32(input, 2) == 0x72EAD3FB); +} +