ВходНаше всё Теги codebook 无线电组件 Поиск Опросы Закон Суббота
3 мая
1515695
Nikolay_Po (01.05.2025 14:08, просмотров: 246)
Опытного эмбеддера не проведёшь! CH32V203, эта сука потребовала барьера между сбросом модуля CRC подачей данных: 

CH32V203, тактовая ядра и HCLK ~77МГц (не предельная, в общем). Вот тут:


uint32_t CRC32calcBlock (uint32_t *Data, unsigned Length) { //Calculate CRC-32 value for a block of uint32_t words
    CRC->CTLR = CRC_CTLR_RESET; //Reset CRC data register before computing new block check value
    asm volatile ("NOP"); //A pause to let the CRC unint actually reset
    for (unsigned WordIdx = 0; WordIdx < Length; WordIdx++) {
        CRC->DATAR = Data[WordIdx];
    }
    return (CRC->DATAR);
}

Пришлось вставить NOP после установки CRC_CTLR_RESET.

В общем, дело было так: стадия проекта близка к финалу (я надеюсь). Вижу, что памяти хватает, а вот скорости никогда много не бывает. Поменял оптимизацию с Os на O3 (LTO всегда включено).

Так вот, у меня перестали проходить проверку только что записанные во флеш данные. Вычисление при записи - одно, вычисление при проверке по тем же данным - другое. Это два блока данных, последнее слово - CRC. Так вот, в первом случае в CRC писалось значение 3088948752, а при проверке во втором, CRC по первым четырём словам, было другое!




Пришлось смотреть ассемблер. Искать разницу. А разница была:

В первом случае, данные из 4 слов, подавались циклом и после CRC_CTLR_RESET, была команда выборки данных по индексу. И между сбросом и записью первого слова в CRC DATAR, проходила минимум одна команда. Работало.

Во втором случае, с неверным результатом, оптимизатор засунул весь пакет данных в регистры и развернул цикл. Так, что сразу за подачей CRC_CTLR_RESET, сразу следовала подача данных в CRC->DATAR. И это ломало работу модуля.

Когда была оптимизация по размеру, Os, в обоих случаях использовался один и тот же код, без разворачивания цикла. А с оптимизацией - один цикл не развернулся, а другой - развернулся.

Что примечательно: в инструкции к CRC, указано, что писать в DATAR можно непрерывно - задержка на время вычисления в 4 такта HCLK обеспечивается автоматически. А вот про RESET такого не было сказано. И модуль CRC не успевал установить своё исходное значение 0xFFFFFFFF до записи новых данных в DATAR.

С одним NOP-ом в качестве барьера, заработало.


UPD: всё же, загрузка слов была не из регистров, а с косвенной адресацией, но уже по готовым смещениям, сразу же с первой инструкции после сброса CRC.