Compare commits

...

5 Commits

Author SHA1 Message Date
iabdalkader
4f346b2f14 boards: Enable CRC module for AE3 and N6.
Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
2025-09-25 10:05:25 +02:00
iabdalkader
8e18e3f96f modules/py_crc: Add hardware-accelerated CRC module.
Optional, small module for testing.

Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
2025-09-25 10:05:25 +02:00
iabdalkader
a37eeefca5 ports/alif: Add support for CRC32.
Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
2025-09-25 10:05:22 +02:00
iabdalkader
cec54bab3e ports/stm32: Add support for CRC32.
Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
2025-09-25 09:49:23 +02:00
iabdalkader
e075aefca4 common/omv_crc: Update CRC support.
- Add support for CRC32 with software fallback.
- Update polynomials and lookup tables.

Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
2025-09-25 09:49:19 +02:00
8 changed files with 365 additions and 114 deletions

View File

@ -174,6 +174,11 @@ MPY_CFLAGS += -DMICROPY_PY_IMU=1
MPY_MKARGS += MICROPY_PY_IMU=1
endif
ifeq ($(MICROPY_PY_CRC), 1)
MPY_CFLAGS += -DMICROPY_PY_CRC=1
MPY_MKARGS += MICROPY_PY_CRC=1
endif
ifeq ($(MICROPY_PY_BTREE), 1)
MPY_CFLAGS += -DMICROPY_PY_BTREE=1
MPY_MKARGS += MICROPY_PY_BTREE=1

View File

@ -20,6 +20,7 @@ MICROPY_PY_TOF = 1
MICROPY_PY_ULAB = 1
MICROPY_PY_DISPLAY = 1
MICROPY_PY_IMU = 1
MICROPY_PY_CRC = 1
MICROPY_PY_AUDIO = 1
MICROPY_PY_ML = 1
MICROPY_PY_ML_TFLM = 1

View File

@ -30,6 +30,7 @@ MICROPY_PY_CSI = 1
MICROPY_PY_CSI_NG = 1
MICROPY_PY_FIR = 1
MICROPY_PY_IMU = 1
MICROPY_PY_CRC = 1
MICROPY_PY_ULAB = 1
MICROPY_PY_DISPLAY = 1
MICROPY_PY_TV = 1

View File

@ -23,64 +23,120 @@
*/
#include "omv_crc.h"
// CRC16 lookup table for polynomial 0xF94F (HD=6, len=135)
static const uint16_t crc16_table[256] = {
0x0000, 0xBAAD, 0xCFF7, 0x755A, 0x2543, 0x9FEE, 0xEAB4, 0x5019,
0x4A86, 0xF02B, 0x8571, 0x3FDC, 0x6FC5, 0xD568, 0xA032, 0x1A9F,
0x950C, 0x2FA1, 0x5AFB, 0xE056, 0xB04F, 0x0AE2, 0x7FB8, 0xC515,
0xDF8A, 0x6527, 0x107D, 0xAAD0, 0xFAC9, 0x4064, 0x353E, 0x8F93,
0x90B5, 0x2A18, 0x5F42, 0xE5EF, 0xB5F6, 0x0F5B, 0x7A01, 0xC0AC,
0xDA33, 0x609E, 0x15C4, 0xAF69, 0xFF70, 0x45DD, 0x3087, 0x8A2A,
0x05B9, 0xBF14, 0xCA4E, 0x70E3, 0x20FA, 0x9A57, 0xEF0D, 0x55A0,
0x4F3F, 0xF592, 0x80C8, 0x3A65, 0x6A7C, 0xD0D1, 0xA58B, 0x1F26,
0x9BC7, 0x216A, 0x5430, 0xEE9D, 0xBE84, 0x0429, 0x7173, 0xCBDE,
0xD141, 0x6BEC, 0x1EB6, 0xA41B, 0xF402, 0x4EAF, 0x3BF5, 0x8158,
0x0ECB, 0xB466, 0xC13C, 0x7B91, 0x2B88, 0x9125, 0xE47F, 0x5ED2,
0x444D, 0xFEE0, 0x8BBA, 0x3117, 0x610E, 0xDBA3, 0xAEF9, 0x1454,
0x0B72, 0xB1DF, 0xC485, 0x7E28, 0x2E31, 0x949C, 0xE1C6, 0x5B6B,
0x41F4, 0xFB59, 0x8E03, 0x34AE, 0x64B7, 0xDE1A, 0xAB40, 0x11ED,
0x9E7E, 0x24D3, 0x5189, 0xEB24, 0xBB3D, 0x0190, 0x74CA, 0xCE67,
0xD4F8, 0x6E55, 0x1B0F, 0xA1A2, 0xF1BB, 0x4B16, 0x3E4C, 0x84E1,
0x8D23, 0x378E, 0x42D4, 0xF879, 0xA860, 0x12CD, 0x6797, 0xDD3A,
0xC7A5, 0x7D08, 0x0852, 0xB2FF, 0xE2E6, 0x584B, 0x2D11, 0x97BC,
0x182F, 0xA282, 0xD7D8, 0x6D75, 0x3D6C, 0x87C1, 0xF29B, 0x4836,
0x52A9, 0xE804, 0x9D5E, 0x27F3, 0x77EA, 0xCD47, 0xB81D, 0x02B0,
0x1D96, 0xA73B, 0xD261, 0x68CC, 0x38D5, 0x8278, 0xF722, 0x4D8F,
0x5710, 0xEDBD, 0x98E7, 0x224A, 0x7253, 0xC8FE, 0xBDA4, 0x0709,
0x889A, 0x3237, 0x476D, 0xFDC0, 0xADD9, 0x1774, 0x622E, 0xD883,
0xC21C, 0x78B1, 0x0DEB, 0xB746, 0xE75F, 0x5DF2, 0x28A8, 0x9205,
0x16E4, 0xAC49, 0xD913, 0x63BE, 0x33A7, 0x890A, 0xFC50, 0x46FD,
0x5C62, 0xE6CF, 0x9395, 0x2938, 0x7921, 0xC38C, 0xB6D6, 0x0C7B,
0x83E8, 0x3945, 0x4C1F, 0xF6B2, 0xA6AB, 0x1C06, 0x695C, 0xD3F1,
0xC96E, 0x73C3, 0x0699, 0xBC34, 0xEC2D, 0x5680, 0x23DA, 0x9977,
0x8651, 0x3CFC, 0x49A6, 0xF30B, 0xA312, 0x19BF, 0x6CE5, 0xD648,
0xCCD7, 0x767A, 0x0320, 0xB98D, 0xE994, 0x5339, 0x2663, 0x9CCE,
0x135D, 0xA9F0, 0xDCAA, 0x6607, 0x361E, 0x8CB3, 0xF9E9, 0x4344,
0x59DB, 0xE376, 0x962C, 0x2C81, 0x7C98, 0xC635, 0xB36F, 0x09C2
0x0000, 0xF94F, 0x0BD1, 0xF29E, 0x17A2, 0xEEED, 0x1C73, 0xE53C,
0x2F44, 0xD60B, 0x2495, 0xDDDA, 0x38E6, 0xC1A9, 0x3337, 0xCA78,
0x5E88, 0xA7C7, 0x5559, 0xAC16, 0x492A, 0xB065, 0x42FB, 0xBBB4,
0x71CC, 0x8883, 0x7A1D, 0x8352, 0x666E, 0x9F21, 0x6DBF, 0x94F0,
0xBD10, 0x445F, 0xB6C1, 0x4F8E, 0xAAB2, 0x53FD, 0xA163, 0x582C,
0x9254, 0x6B1B, 0x9985, 0x60CA, 0x85F6, 0x7CB9, 0x8E27, 0x7768,
0xE398, 0x1AD7, 0xE849, 0x1106, 0xF43A, 0x0D75, 0xFFEB, 0x06A4,
0xCCDC, 0x3593, 0xC70D, 0x3E42, 0xDB7E, 0x2231, 0xD0AF, 0x29E0,
0x836F, 0x7A20, 0x88BE, 0x71F1, 0x94CD, 0x6D82, 0x9F1C, 0x6653,
0xAC2B, 0x5564, 0xA7FA, 0x5EB5, 0xBB89, 0x42C6, 0xB058, 0x4917,
0xDDE7, 0x24A8, 0xD636, 0x2F79, 0xCA45, 0x330A, 0xC194, 0x38DB,
0xF2A3, 0x0BEC, 0xF972, 0x003D, 0xE501, 0x1C4E, 0xEED0, 0x179F,
0x3E7F, 0xC730, 0x35AE, 0xCCE1, 0x29DD, 0xD092, 0x220C, 0xDB43,
0x113B, 0xE874, 0x1AEA, 0xE3A5, 0x0699, 0xFFD6, 0x0D48, 0xF407,
0x60F7, 0x99B8, 0x6B26, 0x9269, 0x7755, 0x8E1A, 0x7C84, 0x85CB,
0x4FB3, 0xB6FC, 0x4462, 0xBD2D, 0x5811, 0xA15E, 0x53C0, 0xAA8F,
0xFF91, 0x06DE, 0xF440, 0x0D0F, 0xE833, 0x117C, 0xE3E2, 0x1AAD,
0xD0D5, 0x299A, 0xDB04, 0x224B, 0xC777, 0x3E38, 0xCCA6, 0x35E9,
0xA119, 0x5856, 0xAAC8, 0x5387, 0xB6BB, 0x4FF4, 0xBD6A, 0x4425,
0x8E5D, 0x7712, 0x858C, 0x7CC3, 0x99FF, 0x60B0, 0x922E, 0x6B61,
0x4281, 0xBBCE, 0x4950, 0xB01F, 0x5523, 0xAC6C, 0x5EF2, 0xA7BD,
0x6DC5, 0x948A, 0x6614, 0x9F5B, 0x7A67, 0x8328, 0x71B6, 0x88F9,
0x1C09, 0xE546, 0x17D8, 0xEE97, 0x0BAB, 0xF2E4, 0x007A, 0xF935,
0x334D, 0xCA02, 0x389C, 0xC1D3, 0x24EF, 0xDDA0, 0x2F3E, 0xD671,
0x7CFE, 0x85B1, 0x772F, 0x8E60, 0x6B5C, 0x9213, 0x608D, 0x99C2,
0x53BA, 0xAAF5, 0x586B, 0xA124, 0x4418, 0xBD57, 0x4FC9, 0xB686,
0x2276, 0xDB39, 0x29A7, 0xD0E8, 0x35D4, 0xCC9B, 0x3E05, 0xC74A,
0x0D32, 0xF47D, 0x06E3, 0xFFAC, 0x1A90, 0xE3DF, 0x1141, 0xE80E,
0xC1EE, 0x38A1, 0xCA3F, 0x3370, 0xD64C, 0x2F03, 0xDD9D, 0x24D2,
0xEEAA, 0x17E5, 0xE57B, 0x1C34, 0xF908, 0x0047, 0xF2D9, 0x0B96,
0x9F66, 0x6629, 0x94B7, 0x6DF8, 0x88C4, 0x718B, 0x8315, 0x7A5A,
0xB022, 0x496D, 0xBBF3, 0x42BC, 0xA780, 0x5ECF, 0xAC51, 0x551E,
};
__attribute__((weak)) void omv_crc_init(void) {
// CRC32 lookup table for polynomial 0xFA567D89
const uint32_t crc32_table[256] = {
0x00000000, 0xFA567D89, 0x0EFA869B, 0xF4ACFB12, 0x1DF50D36, 0xE7A370BF, 0x130F8BAD, 0xE959F624,
0x3BEA1A6C, 0xC1BC67E5, 0x35109CF7, 0xCF46E17E, 0x261F175A, 0xDC496AD3, 0x28E591C1, 0xD2B3EC48,
0x77D434D8, 0x8D824951, 0x792EB243, 0x8378CFCA, 0x6A2139EE, 0x90774467, 0x64DBBF75, 0x9E8DC2FC,
0x4C3E2EB4, 0xB668533D, 0x42C4A82F, 0xB892D5A6, 0x51CB2382, 0xAB9D5E0B, 0x5F31A519, 0xA567D890,
0xEFA869B0, 0x15FE1439, 0xE152EF2B, 0x1B0492A2, 0xF25D6486, 0x080B190F, 0xFCA7E21D, 0x06F19F94,
0xD44273DC, 0x2E140E55, 0xDAB8F547, 0x20EE88CE, 0xC9B77EEA, 0x33E10363, 0xC74DF871, 0x3D1B85F8,
0x987C5D68, 0x622A20E1, 0x9686DBF3, 0x6CD0A67A, 0x8589505E, 0x7FDF2DD7, 0x8B73D6C5, 0x7125AB4C,
0xA3964704, 0x59C03A8D, 0xAD6CC19F, 0x573ABC16, 0xBE634A32, 0x443537BB, 0xB099CCA9, 0x4ACFB120,
0x2506AEE9, 0xDF50D360, 0x2BFC2872, 0xD1AA55FB, 0x38F3A3DF, 0xC2A5DE56, 0x36092544, 0xCC5F58CD,
0x1EECB485, 0xE4BAC90C, 0x1016321E, 0xEA404F97, 0x0319B9B3, 0xF94FC43A, 0x0DE33F28, 0xF7B542A1,
0x52D29A31, 0xA884E7B8, 0x5C281CAA, 0xA67E6123, 0x4F279707, 0xB571EA8E, 0x41DD119C, 0xBB8B6C15,
0x6938805D, 0x936EFDD4, 0x67C206C6, 0x9D947B4F, 0x74CD8D6B, 0x8E9BF0E2, 0x7A370BF0, 0x80617679,
0xCAAEC759, 0x30F8BAD0, 0xC45441C2, 0x3E023C4B, 0xD75BCA6F, 0x2D0DB7E6, 0xD9A14CF4, 0x23F7317D,
0xF144DD35, 0x0B12A0BC, 0xFFBE5BAE, 0x05E82627, 0xECB1D003, 0x16E7AD8A, 0xE24B5698, 0x181D2B11,
0xBD7AF381, 0x472C8E08, 0xB380751A, 0x49D60893, 0xA08FFEB7, 0x5AD9833E, 0xAE75782C, 0x542305A5,
0x8690E9ED, 0x7CC69464, 0x886A6F76, 0x723C12FF, 0x9B65E4DB, 0x61339952, 0x959F6240, 0x6FC91FC9,
0x4A0D5DD2, 0xB05B205B, 0x44F7DB49, 0xBEA1A6C0, 0x57F850E4, 0xADAE2D6D, 0x5902D67F, 0xA354ABF6,
0x71E747BE, 0x8BB13A37, 0x7F1DC125, 0x854BBCAC, 0x6C124A88, 0x96443701, 0x62E8CC13, 0x98BEB19A,
0x3DD9690A, 0xC78F1483, 0x3323EF91, 0xC9759218, 0x202C643C, 0xDA7A19B5, 0x2ED6E2A7, 0xD4809F2E,
0x06337366, 0xFC650EEF, 0x08C9F5FD, 0xF29F8874, 0x1BC67E50, 0xE19003D9, 0x153CF8CB, 0xEF6A8542,
0xA5A53462, 0x5FF349EB, 0xAB5FB2F9, 0x5109CF70, 0xB8503954, 0x420644DD, 0xB6AABFCF, 0x4CFCC246,
0x9E4F2E0E, 0x64195387, 0x90B5A895, 0x6AE3D51C, 0x83BA2338, 0x79EC5EB1, 0x8D40A5A3, 0x7716D82A,
0xD27100BA, 0x28277D33, 0xDC8B8621, 0x26DDFBA8, 0xCF840D8C, 0x35D27005, 0xC17E8B17, 0x3B28F69E,
0xE99B1AD6, 0x13CD675F, 0xE7619C4D, 0x1D37E1C4, 0xF46E17E0, 0x0E386A69, 0xFA94917B, 0x00C2ECF2,
0x6F0BF33B, 0x955D8EB2, 0x61F175A0, 0x9BA70829, 0x72FEFE0D, 0x88A88384, 0x7C047896, 0x8652051F,
0x54E1E957, 0xAEB794DE, 0x5A1B6FCC, 0xA04D1245, 0x4914E461, 0xB34299E8, 0x47EE62FA, 0xBDB81F73,
0x18DFC7E3, 0xE289BA6A, 0x16254178, 0xEC733CF1, 0x052ACAD5, 0xFF7CB75C, 0x0BD04C4E, 0xF18631C7,
0x2335DD8F, 0xD963A006, 0x2DCF5B14, 0xD799269D, 0x3EC0D0B9, 0xC496AD30, 0x303A5622, 0xCA6C2BAB,
0x80A39A8B, 0x7AF5E702, 0x8E591C10, 0x740F6199, 0x9D5697BD, 0x6700EA34, 0x93AC1126, 0x69FA6CAF,
0xBB4980E7, 0x411FFD6E, 0xB5B3067C, 0x4FE57BF5, 0xA6BC8DD1, 0x5CEAF058, 0xA8460B4A, 0x521076C3,
0xF777AE53, 0x0D21D3DA, 0xF98D28C8, 0x03DB5541, 0xEA82A365, 0x10D4DEEC, 0xE47825FE, 0x1E2E5877,
0xCC9DB43F, 0x36CBC9B6, 0xC26732A4, 0x38314F2D, 0xD168B909, 0x2B3EC480, 0xDF923F92, 0x25C4421B,
};
}
__attribute__((weak)) uint16_t omv_crc16_start(const void *buf, size_t len) {
const uint8_t *data = (const uint8_t *) buf;
uint16_t crc = OMV_CRC16_INIT;
__attribute__((weak)) omv_crc_t omv_crc_start(const void *buf, size_t size) {
const uint8_t *data = (const uint8_t *)buf;
omv_crc_t crc = OMV_CRC_INIT;
for (size_t i = 0; i < size; i++) {
for (size_t i = 0; i < len; i++) {
uint8_t index = (crc >> 8) ^ data[i];
crc = (crc << 8) ^ crc16_table[index];
}
return crc;
}
__attribute__((weak)) omv_crc_t omv_crc_update(omv_crc_t crc, const void *buf, size_t size) {
const uint8_t *data = (const uint8_t *)buf;
for (size_t i = 0; i < size; i++) {
__attribute__((weak)) uint16_t omv_crc16_update(uint16_t crc, const void *buf, size_t len) {
const uint8_t *data = (const uint8_t *) buf;
for (size_t i = 0; i < len; i++) {
uint8_t index = (crc >> 8) ^ data[i];
crc = (crc << 8) ^ crc16_table[index];
}
return crc;
}
__attribute__((weak)) uint32_t omv_crc32_start(const void *buf, size_t len) {
const uint8_t *data = (const uint8_t *) buf;
uint32_t crc = OMV_CRC32_INIT;
for (size_t i = 0; i < len; i++) {
uint8_t index = (crc >> 24) ^ data[i];
crc = (crc << 8) ^ crc32_table[index];
}
return crc;
}
__attribute__((weak)) uint32_t omv_crc32_update(uint32_t crc, const void *buf, size_t len) {
const uint8_t *data = (const uint8_t *) buf;
for (size_t i = 0; i < len; i++) {
uint8_t index = (crc >> 24) ^ data[i];
crc = (crc << 8) ^ crc32_table[index];
}
return crc;
}

View File

@ -27,37 +27,74 @@
#include <stddef.h>
#include <stdbool.h>
// 0xBAAD is ironically good - HD=5 up to 108 bits, HD=4 up to 7985 bits
#define OMV_CRC_POLY (0xBAAD)
#define OMV_CRC_INIT (0xFFFF)
#define OMV_CRC_SIZE (16)
typedef uint16_t omv_crc_t;
// CRC size enumeration
typedef enum {
OMV_CRC16 = 16,
OMV_CRC32 = 32
} omv_crc_size_t;
// Initialize CRC hardware (if available)
void omv_crc_init(void);
// HD=6 up to 114 bits
#define OMV_CRC16_POLY (0xF94F)
#define OMV_CRC16_INIT (0xFFFF)
// Start CRC calculation for buffer data
omv_crc_t omv_crc_start(const void *buf, size_t size);
// HD=6 up to 32738 bits (~4K)
#define OMV_CRC32_POLY (0xFA567D89)
#define OMV_CRC32_INIT (0xFFFFFFFF)
// Update CRC with additional buffer data
omv_crc_t omv_crc_update(omv_crc_t crc, const void *buf, size_t size);
// Default software implementations
uint16_t omv_crc16_start(const void *buf, size_t len);
uint16_t omv_crc16_update(uint16_t crc, const void *buf, size_t len);
// Read CRC value from the last 2 bytes of buffer
static inline omv_crc_t omv_crc_read(const void *buf, size_t size) {
const uint8_t *crc_buf = (const uint8_t *)buf + size - 2;
return *((omv_crc_t*) crc_buf);
uint32_t omv_crc32_start(const void *buf, size_t len);
uint32_t omv_crc32_update(uint32_t crc, const void *buf, size_t len);
// Public API functions
static inline uint32_t omv_crc_start(omv_crc_size_t size, const void *buf, size_t len) {
if (size == OMV_CRC16) {
return omv_crc16_start(buf, len);
} else if (size == OMV_CRC32) {
return omv_crc32_start(buf, len);
}
return 0;
}
// Calculate CRC and write it to the last 2 bytes of buffer
static inline void omv_crc_write(void *buf, size_t size) {
omv_crc_t crc = omv_crc_start(buf, size - 2);
uint8_t *crc_buf = (uint8_t *)buf + size - 2;
crc_buf[0] = crc & 0xFF;
crc_buf[1] = (crc >> 8) & 0xFF;
static inline uint32_t omv_crc_update(omv_crc_size_t size, uint32_t crc, const void *buf, size_t len) {
if (size == OMV_CRC16) {
return omv_crc16_update((uint16_t) crc, buf, len);
} else if (size == OMV_CRC32) {
return omv_crc32_update(crc, buf, len);
}
return crc;
}
// Read CRC value from the last bytes of buffer
static inline uint32_t omv_crc_read(omv_crc_size_t crc_size, const void *buf, size_t size) {
const uint8_t *crc_buf = (const uint8_t *) buf + size - (crc_size == OMV_CRC16 ? 2 : 4);
if (crc_size == OMV_CRC16) {
return *((uint16_t *) crc_buf);
} else {
return *((uint32_t *) crc_buf);
}
}
// Calculate CRC and write it to the last bytes of buffer
static inline void omv_crc_write(omv_crc_size_t crc_size, void *buf, size_t size) {
uint32_t crc = omv_crc_start(crc_size, buf, size - (crc_size == OMV_CRC16 ? 2 : 4));
uint8_t *crc_buf = (uint8_t *) buf + size - (crc_size == OMV_CRC16 ? 2 : 4);
if (crc_size == OMV_CRC16) {
crc_buf[0] = crc & 0xFF;
crc_buf[1] = (crc >> 8) & 0xFF;
} else {
crc_buf[0] = crc & 0xFF;
crc_buf[1] = (crc >> 8) & 0xFF;
crc_buf[2] = (crc >> 16) & 0xFF;
crc_buf[3] = (crc >> 24) & 0xFF;
}
}
// Calculate and check if CRC matches the one stored in buffer
static inline bool omv_crc_check(const void *buf, size_t size) {
return omv_crc_read(buf, size) == omv_crc_start(buf, size - 2);
static inline bool omv_crc_check(omv_crc_size_t crc_size, const void *buf, size_t size) {
return omv_crc_read(crc_size, buf, size) == omv_crc_start(crc_size, buf, size - (crc_size == OMV_CRC16 ? 2 : 4));
}
#endif // __OMV_CRC_H__

97
modules/py_crc.c Normal file
View File

@ -0,0 +1,97 @@
/*
* SPDX-License-Identifier: MIT
*
* Copyright (C) 2025 OpenMV, LLC.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* CRC Python module for testing CRC implementations.
*/
#if MICROPY_PY_CRC
#include "py/runtime.h"
#include "py/obj.h"
#include "omv_crc.h"
// CRC16 function
static mp_obj_t py_crc16(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kwargs) {
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_data, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
{ MP_QSTR_value, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
};
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args, pos_args, kwargs, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(args[0].u_obj, &bufinfo, MP_BUFFER_READ);
uint16_t crc;
if (args[1].u_obj == MP_OBJ_NULL) {
crc = omv_crc16_start(bufinfo.buf, bufinfo.len);
} else {
uint16_t prev_crc = mp_obj_get_int_truncated(args[1].u_obj) & 0xFFFF;
crc = omv_crc16_update(prev_crc, bufinfo.buf, bufinfo.len);
}
return mp_obj_new_int_from_uint(crc);
}
static MP_DEFINE_CONST_FUN_OBJ_KW(py_crc16_obj, 1, py_crc16);
// CRC32 function
static mp_obj_t py_crc32(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kwargs) {
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_data, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
{ MP_QSTR_value, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
};
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args, pos_args, kwargs, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(args[0].u_obj, &bufinfo, MP_BUFFER_READ);
uint32_t crc;
if (args[1].u_obj == MP_OBJ_NULL) {
crc = omv_crc32_start(bufinfo.buf, bufinfo.len);
} else {
uint32_t prev_crc = mp_obj_get_int_truncated(args[1].u_obj);
crc = omv_crc32_update(prev_crc, bufinfo.buf, bufinfo.len);
}
return mp_obj_new_int_from_uint(crc);
}
static MP_DEFINE_CONST_FUN_OBJ_KW(py_crc32_obj, 1, py_crc32);
// Module globals table
static const mp_rom_map_elem_t crc_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_crc) },
{ MP_ROM_QSTR(MP_QSTR_crc16), MP_ROM_PTR(&py_crc16_obj) },
{ MP_ROM_QSTR(MP_QSTR_crc32), MP_ROM_PTR(&py_crc32_obj) },
};
static MP_DEFINE_CONST_DICT(crc_module_globals, crc_module_globals_table);
// Define module object
const mp_obj_module_t crc_user_cmodule = {
.base = { &mp_type_module },
.globals = (mp_obj_dict_t *) &crc_module_globals,
};
// Register the module to make it available in Python
MP_REGISTER_MODULE(MP_QSTR_crc, crc_user_cmodule);
#endif // MICROPY_PY_CRC

View File

@ -25,46 +25,77 @@
#include "global_map.h"
#include "omv_crc.h"
#define CRC0 ((CRC_Type *)CRC0_BASE)
#define CRC0 ((CRC_Type *) CRC0_BASE)
static bool crc_initialized = false;
static bool crc32_initialized = false;
static void crc_calculate(CRC_Type *crc, const void *buf, uint32_t len, uint32_t *value);
void omv_crc_init(void) {
crc_clear_config(CRC0);
crc_enable_16bit(CRC0);
crc_enable_custom_poly(CRC0);
crc_set_custom_poly(CRC0, OMV_CRC_POLY);
crc_set_seed(CRC0, OMV_CRC_INIT);
crc_enable(CRC0);
crc_initialized = true;
static void omv_crc32_init(void) {
CRC0->CRC_SEED = OMV_CRC32_INIT;
CRC0->CRC_POLY_CUSTOM = OMV_CRC32_POLY;
CRC0->CRC_CONTROL = CRC_32C |
CRC_CUSTOM_POLY |
CRC_ALGO_32_BIT_SIZE;
crc32_initialized = true;
}
omv_crc_t omv_crc_start(const void *buf, size_t size) {
if (!crc_initialized) {
omv_crc_init();
}
if (size == 0) {
return OMV_CRC_INIT;
}
uint32_t omv_crc32_start(const void *buf, size_t len) {
uint32_t result = 0;
crc_calculate_16bit(CRC0, buf, size, &result);
return (omv_crc_t)result;
}
omv_crc_t omv_crc_update(omv_crc_t crc, const void *buf, size_t size) {
if (!crc_initialized) {
omv_crc_init();
if (!crc32_initialized) {
omv_crc32_init();
}
if (size == 0) {
if (len == 0) {
return OMV_CRC32_INIT;
}
CRC0->CRC_SEED = OMV_CRC32_INIT;
CRC0->CRC_CONTROL |= CRC_INIT_BIT;
crc_calculate(CRC0, buf, len, &result);
return result;
}
uint32_t omv_crc32_update(uint32_t crc, const void *buf, size_t len) {
uint32_t result = 0;
if (!crc32_initialized) {
omv_crc32_init();
}
if (len == 0) {
return crc;
}
// Set current CRC value and calculate incrementally
crc_set_seed(CRC0, crc);
uint32_t result = 0;
crc_calculate_16bit(CRC0, buf, size, &result);
return (omv_crc_t)result;
CRC0->CRC_SEED = OMV_CRC32_INIT;
CRC0->CRC_CONTROL |= CRC_INIT_BIT;
crc_calculate(CRC0, buf, len, &result);
return result;
}
static void crc_calculate(CRC_Type *crc, const void *buf, uint32_t len, uint32_t *value) {
const uint8_t *data = (const uint8_t *) buf;
// Use hardware only if length is multiple of 4, otherwise use pure software
if ((len % 4) == 0) {
// Hardware path - process all data as 32-bit words
const uint32_t *data32 = (const uint32_t *) data;
for (uint32_t i = 0; i < len / 4; i++) {
crc->CRC_DATA_IN_32_0 = data32[i];
}
*value = crc->CRC_OUT;
} else {
// Software path - use lookup table
extern const uint32_t crc32_table[256];
uint32_t result = OMV_CRC32_INIT;
for (uint32_t i = 0; i < len; i++) {
uint8_t index = (result >> 24) ^ data[i];
result = (result << 8) ^ crc32_table[index];
}
*value = result;
}
}

View File

@ -31,43 +31,66 @@
static CRC_HandleTypeDef hcrc = {0};
static bool crc_initialized = false;
void omv_crc_init(void) {
static void omv_crc_init(void) {
hcrc.Instance = CRC;
hcrc.InputDataFormat = CRC_INPUTDATA_FORMAT_BYTES;
hcrc.Init.DefaultPolynomialUse = DEFAULT_POLYNOMIAL_DISABLE;
hcrc.Init.GeneratingPolynomial = OMV_CRC_POLY;
hcrc.Init.DefaultInitValueUse = DEFAULT_INIT_VALUE_DISABLE;
hcrc.Init.InitValue = OMV_CRC_INIT;
hcrc.Init.CRCLength = CRC_POLYLENGTH_16B;
hcrc.Init.InputDataInversionMode = CRC_INPUTDATA_INVERSION_NONE;
hcrc.Init.OutputDataInversionMode = CRC_OUTPUTDATA_INVERSION_DISABLE;
hcrc.InputDataFormat = CRC_INPUTDATA_FORMAT_BYTES;
hcrc.Init.CRCLength = CRC_POLYLENGTH_32B;
hcrc.Init.InitValue = OMV_CRC32_INIT;
hcrc.Init.GeneratingPolynomial = OMV_CRC32_POLY;
HAL_CRC_Init(&hcrc);
crc_initialized = true;
}
omv_crc_t omv_crc_start(const void *buf, size_t size) {
uint16_t omv_crc16_start(const void *buf, size_t len) {
if (!crc_initialized) {
omv_crc_init();
}
if (size == 0) {
return OMV_CRC_INIT;
// Set CRC16 polynomial and length directly
WRITE_REG(hcrc.Instance->POL, OMV_CRC16_POLY);
MODIFY_REG(hcrc.Instance->CR, CRC_CR_POLYSIZE, CRC_POLYLENGTH_16B);
if (len == 0) {
return OMV_CRC16_INIT;
}
return (omv_crc_t) HAL_CRC_Calculate(&hcrc, (uint32_t *)buf, size);
return (uint16_t) HAL_CRC_Calculate(&hcrc, (uint32_t *) buf, len);
}
omv_crc_t omv_crc_update(omv_crc_t crc, const void *buf, size_t size) {
if (!crc_initialized) {
omv_crc_init();
}
if (size == 0) {
uint16_t omv_crc16_update(uint16_t crc, const void *buf, size_t len) {
if (len == 0) {
return crc;
}
return (omv_crc_t) HAL_CRC_Accumulate(&hcrc, (uint32_t *)buf, size);
return (uint16_t) HAL_CRC_Accumulate(&hcrc, (uint32_t *) buf, len);
}
uint32_t omv_crc32_start(const void *buf, size_t len) {
if (!crc_initialized) {
omv_crc_init();
}
// Set CRC32 polynomial and length directly
WRITE_REG(hcrc.Instance->POL, OMV_CRC32_POLY);
MODIFY_REG(hcrc.Instance->CR, CRC_CR_POLYSIZE, CRC_POLYLENGTH_32B);
if (len == 0) {
return OMV_CRC32_INIT;
}
return HAL_CRC_Calculate(&hcrc, (uint32_t *) buf, len);
}
uint32_t omv_crc32_update(uint32_t crc, const void *buf, size_t len) {
if (len == 0) {
return crc;
}
return HAL_CRC_Accumulate(&hcrc, (uint32_t *) buf, len);
}
#endif // STM32F7 || STM32H7 || STM32N6