mirror of
https://github.com/openmv/openmv.git
synced 2025-09-26 23:09:13 +08:00
Compare commits
9 Commits
9b65da9cb7
...
7f439f56de
Author | SHA1 | Date | |
---|---|---|---|
![]() |
7f439f56de | ||
![]() |
00ba887043 | ||
![]() |
1b5da3ebfe | ||
![]() |
9704ed8c62 | ||
![]() |
d1a422174d | ||
![]() |
90dde3289e | ||
![]() |
cec54bab3e | ||
![]() |
e075aefca4 | ||
![]() |
26aa191ad7 |
5
Makefile
5
Makefile
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
136
common/omv_crc.c
136
common/omv_crc.c
@ -23,50 +23,83 @@
|
||||
*/
|
||||
#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)) omv_crc_t omv_crc_start(const void *buf, size_t size) {
|
||||
__attribute__((weak)) uint16_t omv_crc16_start(const void *buf, size_t len) {
|
||||
const uint8_t *data = (const uint8_t *) buf;
|
||||
omv_crc_t crc = OMV_CRC_INIT;
|
||||
uint16_t crc = OMV_CRC16_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];
|
||||
}
|
||||
@ -74,13 +107,36 @@ __attribute__((weak)) omv_crc_t omv_crc_start(const void *buf, size_t size) {
|
||||
return crc;
|
||||
}
|
||||
|
||||
__attribute__((weak)) omv_crc_t omv_crc_update(omv_crc_t crc, const void *buf, size_t size) {
|
||||
__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 < 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)) 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;
|
||||
}
|
||||
|
@ -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;
|
||||
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
97
modules/py_crc.c
Normal 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
|
@ -25,46 +25,78 @@
|
||||
#include "global_map.h"
|
||||
#include "omv_crc.h"
|
||||
|
||||
// There seems to be a mismatch between how the Alif HW CRC32 algorithm
|
||||
// works and the other HW CRCs and the software implementation.
|
||||
// Just leaving this here just in case it works on a different series.
|
||||
#if 0
|
||||
#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_CONTROL = CRC_32C |
|
||||
CRC_CUSTOM_POLY |
|
||||
CRC_ALGO_32_BIT_SIZE;
|
||||
CRC0->CRC_SEED = OMV_CRC32_INIT;
|
||||
CRC0->CRC_POLY_CUSTOM = OMV_CRC32_POLY;
|
||||
crc32_initialized = true;
|
||||
}
|
||||
|
||||
omv_crc_t omv_crc_start(const void *buf, size_t size) {
|
||||
if (!crc_initialized) {
|
||||
omv_crc_init();
|
||||
uint32_t omv_crc32_start(const void *buf, size_t len) {
|
||||
uint32_t result = OMV_CRC32_INIT;
|
||||
|
||||
if (!crc32_initialized) {
|
||||
omv_crc32_init();
|
||||
}
|
||||
|
||||
if (size == 0) {
|
||||
return OMV_CRC_INIT;
|
||||
if (len == 0) {
|
||||
return OMV_CRC32_INIT;
|
||||
}
|
||||
|
||||
uint32_t result = 0;
|
||||
crc_calculate_16bit(CRC0, buf, size, &result);
|
||||
return (omv_crc_t)result;
|
||||
crc_calculate(CRC0, buf, len, &result);
|
||||
return result;
|
||||
}
|
||||
|
||||
omv_crc_t omv_crc_update(omv_crc_t crc, const void *buf, size_t size) {
|
||||
if (!crc_initialized) {
|
||||
omv_crc_init();
|
||||
uint32_t omv_crc32_update(uint32_t crc, const void *buf, size_t len) {
|
||||
uint32_t result = crc;
|
||||
|
||||
if (!crc32_initialized) {
|
||||
omv_crc32_init();
|
||||
}
|
||||
|
||||
if (size == 0) {
|
||||
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;
|
||||
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;
|
||||
|
||||
if ((len % 4) == 0) {
|
||||
// Use hardware only if length is multiple of 4
|
||||
crc->CRC_SEED = *value;
|
||||
crc->CRC_CONTROL |= CRC_INIT_BIT;
|
||||
|
||||
// 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
|
||||
uint32_t result = *value;
|
||||
extern const uint32_t crc32_table[256];
|
||||
|
||||
for (uint32_t i = 0; i < len; i++) {
|
||||
uint8_t index = (result >> 24) ^ data[i];
|
||||
result = (result << 8) ^ crc32_table[index];
|
||||
}
|
||||
*value = result;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -152,6 +152,9 @@ int omv_spi_transfer_start(omv_spi_t *spi, omv_spi_transfer_t *xfer) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// Handle pending events
|
||||
mp_event_handle_nowait();
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -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
|
||||
|
92
tools/gen_crc_table.py
Executable file
92
tools/gen_crc_table.py
Executable file
@ -0,0 +1,92 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# This file is part of the OpenMV project.
|
||||
# Copyright (C) 2025 OpenMV, LLC.
|
||||
#
|
||||
# This work is licensed under the MIT license, see the file LICENSE for details.
|
||||
#
|
||||
# Generate CRC lookup tables for OpenMV CRC implementation
|
||||
|
||||
import argparse
|
||||
|
||||
|
||||
def generate_crc16_table(polynomial):
|
||||
"""Generate CRC16 lookup table"""
|
||||
table = []
|
||||
for i in range(256):
|
||||
crc = i << 8
|
||||
for _ in range(8):
|
||||
if crc & 0x8000:
|
||||
crc = (crc << 1) ^ polynomial
|
||||
else:
|
||||
crc = crc << 1
|
||||
crc &= 0xFFFF
|
||||
table.append(crc)
|
||||
return table
|
||||
|
||||
|
||||
def generate_crc32_table(polynomial):
|
||||
"""Generate CRC32 lookup table"""
|
||||
table = []
|
||||
for i in range(256):
|
||||
crc = i << 24
|
||||
for _ in range(8):
|
||||
if crc & 0x80000000:
|
||||
crc = (crc << 1) ^ polynomial
|
||||
else:
|
||||
crc = crc << 1
|
||||
crc &= 0xFFFFFFFF
|
||||
table.append(crc)
|
||||
return table
|
||||
|
||||
|
||||
def format_c_array(table, name, data_type):
|
||||
"""Format array as C code"""
|
||||
lines = [f"static const {data_type} {name}[256] = {{"]
|
||||
|
||||
for i in range(0, len(table), 8):
|
||||
row = table[i : i + 8]
|
||||
if data_type == "uint16_t":
|
||||
formatted_row = ", ".join(f"0x{val:04X}" for val in row)
|
||||
else: # uint32_t
|
||||
formatted_row = ", ".join(f"0x{val:08X}" for val in row)
|
||||
lines.append(f" {formatted_row},")
|
||||
|
||||
lines.append("};")
|
||||
return "\n".join(lines)
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Generate CRC lookup tables for OpenMV CRC implementation"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--crc16-poly",
|
||||
type=lambda x: int(x, 0),
|
||||
default=0xF94F,
|
||||
help="CRC16 polynomial (default: 0xF94F)",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--crc32-poly",
|
||||
type=lambda x: int(x, 0),
|
||||
default=0xFA567D89,
|
||||
help="CRC32 polynomial (default: 0xFA567D89)",
|
||||
)
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
# Generate CRC16 table
|
||||
crc16_table = generate_crc16_table(args.crc16_poly)
|
||||
|
||||
# Generate CRC32 table
|
||||
crc32_table = generate_crc32_table(args.crc32_poly)
|
||||
|
||||
print(f"// CRC16 lookup table for polynomial 0x{args.crc16_poly:04X}")
|
||||
print(format_c_array(crc16_table, "crc16_table", "uint16_t"))
|
||||
print()
|
||||
print(f"// CRC32 lookup table for polynomial 0x{args.crc32_poly:08X}")
|
||||
print(format_c_array(crc32_table, "crc32_table", "uint32_t"))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
Loading…
Reference in New Issue
Block a user