Аппаратный CRC32 на весь объём флешки

ejsanyo

Active member
В составе нашего контроллера имеется весьма неплохой блок для аппаратного подсчёта CRC32, причём позволяющий очень гибко настроить параметры под любой из популярных алгоритмов. Однако в текущей версии HAL-овской функции длина обрабатываемой последовательности ограничена размером аппаратного буфера CRC-блока. А можно ли её увеличить? В частности, посчитать CRC на всю длину кода прошивки, ну или хотя бы грубо - на всю ёмкость флешки? Попробуем слегка исправить HAL-овскую функцию и сделать это:
C:
CRC_HandleTypeDef hcrc;

__HAL_PCC_CRC32_CLK_ENABLE();
    hcrc.Instance = CRC;
    hcrc.Poly = 0x04C11DB7; //параметры для разновидности CRC32b
    hcrc.Init = 0xFFFFFFFF;
    hcrc.InputReverse = CRC_REFIN_TRUE;
    hcrc.OutputReverse = CRC_REFOUT_TRUE;
    hcrc.OutputInversion = CRC_OUTPUTINVERSION_ON;
    HAL_CRC_Init(&hcrc);
    .
    .
    .
    .
//считает CRC по всей ёмкости флешки
//закомментить в HAL_CRC_WriteData() строку HAL_CRC_SetInit(hcrc);
uint32_t CalcCRC(void)
{
    //в каких пределах считать CRC32
    #define crc_start 0x80000000
    #define crc_capacity 1048576

    uint8_t* crc_pointer;
    uint32_t crc_result;
    uint32_t i;

    HAL_CRC_SetInit(&hcrc);
    crc_pointer = (uint8_t *)crc_start;
    for (i = 0; i < (crc_capacity - CRC_MAX_BYTES); i += CRC_MAX_BYTES)
    {
        HAL_CRC_WriteData(&hcrc, crc_pointer, CRC_MAX_BYTES);
        HAL_CRC_WaitBusy(&hcrc);
        crc_pointer += CRC_MAX_BYTES;
    }
    HAL_CRC_WriteData(&hcrc, crc_pointer, (crc_capacity - i));
    HAL_CRC_WaitBusy(&hcrc);
    return HAL_CRC_ReadCRC(&hcrc);
}
Да, в оригинале HAL_CRC_WriteData() каждый раз переписывает начальное значение в блоке CRC, но нам это не нужно, поэтому убираем.
И такой ещё вопрос: а возможно ли каким-либо образом получить информацию о реальной ёмкости запаянной флешки, когда код прошивки выполняется непосредственно с неё? Чтобы не вбивать константу каждый раз. Я вот попробовал давать команды 0x90 и 0x9F через HAL_SPIFI_SendCommand(), но контроллер на этом месте сразу подвисает. Похоже, "отстреливаю себе ногу".
 

mscs

Member
Получить информацию о реальной ёмкости запаянной ИМС Flash-памяти возможно. В моей программе это делается с помощью команды 0x9F. HAL не использую, работаю с регистрами:
Код:
        lui        a5, 0x70            # a5 = 70000h (SPIFI controller base address)
        lui        a1, 0x9F200
        c.addi     a1, 3
        c.sw       a1, 4(a5)           # SPIFI_CMD = 9F200003h (Read JEDEC ID)

        c.li       a4, 25              # Timeout counter initialization
                                       # Waiting for SPIFI readyness subroutine
2:      c.lw       a3, 0x1C(a5)        # a3 = SPIFI_STA
        andi       a3, a3, 0x20        # If command execution has been completed,
        c.bnez     a3, 3f              # jump to label 3

        c.addi     a4, -1              # If timeout is expired, jump to label Fault
        c.beqz     a4, Fault

        c.j        2b                  # Otherwise, jump to label 2

3:      c.sw       a3, 0x1C(a5)        # SPIFI_STA = 20h (clear interrupt request)

        lbu        a0, 0x14(a5)        # a0 = SPIFI_DATA (the first byte of ID)
        lbu        a1, 0x14(a5)        # a1 = SPIFI_DATA (the second byte of ID)
        lbu        a2, 0x14(a5)        # a2 = SPIFI_DATA (the third byte of ID)
 
Последнее редактирование:

ejsanyo

Active member
Суровый ассемблерный код... :censored: Но, так понимаю, выполняется он у вас НЕ с флешки? Потому и выполняется нормально.
 

mscs

Member
Да, все верно. Согдасно документации МК, контроллер SPIFI может работать в двух режимах: режим работы с периферией и режим работы с памятью (в котором выбираются команды). Для чтения ID необходимо перейти в режим работы с периферией, что подразумевает прекращение выборки команд.
 
Последнее редактирование:

mscs

Member
Также и при выполнении процедуры записи Flash-памяти кода выборка команд невозможна. Поэтому код подпрограммы записи копируется в ОЗУ. Так делается в STM-ках, в Миландр-ах, и так же должно делаться в К1948ВК018.
 
Сверху