Does anybody have any experience working with the AVR32 UC3's built-in CRC32 computation engine? I'm hoping to use it to save some code size and complexity performing an integrity check of applications loaded through an in-house bootloader.
I'm working with an AT32UC3A0152. So far, I've tried code that looks like this:
#define AVR32_MSU_STATUS_RESULT_BUSY 1 #define AVR32_MSU_STATUS_RESULT_DONE 0 #define AVR32_MSU_CTRL_OP_NONE 0 #define AVR32_MSU_CTRL_OP_CRC 1 static void wait_for_msu(void) { uint32_t status; do { status = Get_system_register(AVR32_MSU_STATUS); } while ((status & AVR32_MSU_STATUS_RESULT_MASK) == AVR32_MSU_STATUS_RESULT_BUSY); } static void wait_for_msu_done(void) { volatile uint32_t status; do { status = Get_system_register(AVR32_MSU_STATUS); } while ((status & AVR32_MSU_STATUS_RESULT_MASK) != AVR32_MSU_STATUS_RESULT_DONE); } static uint32_t msu_compute_crc(uint32_t start, size_t length, uint32_t initial) { Set_system_register(AVR32_MSU_CTRL, AVR32_MSU_CTRL_OP_NONE); wait_for_msu(); Set_system_register(AVR32_MSU_ADDRHI, 0); Set_system_register(AVR32_MSU_ADDRLO, start); Set_system_register(AVR32_MSU_LENGTH, length); Set_system_register(AVR32_MSU_DATA, initial); Set_system_register(AVR32_MSU_CTRL, AVR32_MSU_CTRL_OP_CRC); wait_for_msu_done(); return Get_system_register(AVR32_MSU_DATA); }
I'm passing in a start address equal to the beginning of my application section (0x80004000) and a length equal to half of the remaining flash in the device (253952).
What I'm finding is that wait_for_msu_done() is getting stuck because the status register is reporting a BUS_ERR condition.
Has anybody worked with this module before? Are there any other hardware modules or clock domains I need to ensure are enabled before I can use it? Where else should I look for pointers on how to work with it correctly?