Жажда скорости — ARM или RISC-V?
В этой короткой заметке я попытаюсь сравнить три разных микроконтроллера по времени реакции на внешнее прерывание. Дело это интересное, просто потому что иногда микроконтроллер должен реально контролировать и желательно по-быстрее. Ну и конечно, хочется оценить работу шины, прерываний и всего остального.
Итак, схема опыта очень проста — будем использовать 3 первые пина порта GPIOA, первый как источник внешнего прерывания (exti0), а 1 и 2 для вывода данных. Хватило бы и одного, но тогда осциллограф, как понимаете, подключать не так удобно -, а на скорости кода это не сказывается. Первый пин и второй, естественно, соединим проводком…
Будем подавать на второй пин высокий уровень, это вызовет прерывание, сработает обработчик. В нем будем просто выводить 0 на все пины порта GPIOA -, а по факту на второй и третий, получается. И цикл повторяется. Код примерно одинаков и для ARM и для RISC-V и приведен ниже.
Да, для опытов у нас будет два процессора ARM, обе stm — так уж вышло, они были под руками — stm32f103 и stm32h750, соответственно, первую запустим на 64 МГц, а вторую на 400 МГц (ну на шине будет всё равно 200 МГц). А вот для RISC-V попалось изделие WCH-IC, а именно ch32v307 и он будет у нас на 144 МГц. Кстати, в нем реализовано железячное переключение при прерывании с сохранением регистров, так что если постараться, то можно несколько еще ускорить код, выбросив пару-тройку тактов.
Однако для эксперимента компилятор был использован с одной и той же опцией оптимизации -Os и никаких трюков не применялось. Код на ассемблере получился примерно похожий, с ньюансами, конечно, но всё же…
Итак, сам код
// это код обработчика для ARM
void EXTI0_IRQHandler(void) {
__HAL_GPIO_EXTI_CLEAR_IT(1);
GPIOA->ODR = 0;
}
// а это для RISC-V
void EXTI0_IRQHandler(void)
{
EXTI->INTFR = EXTI_Line0;
GPIOA->OUTDR = 0;
}
// ну а это код выполняется в главном цикле
for(;;) {
GPIOA->ODR = 6;
__NOP(); // и так далее примерно 100 раз
...
}
Для замеров использовался осциллограф с 1 Gsps, что дает разрешение в 10 нс — вполне для наших целей подходящее. На экране, конечно, череда импульсов — ну это как и ожидалось.
Итак, вот замеры — еще раз подчеркну, что так как точность 10 нс (а цикл шины у h750 всё же 5 нс), то и число округлялись до десяток.
Микроконтроллер | stm32f103 | stm32h750 | ch32v307 |
Архитектура | ARM | ARM | RISC-V |
частота шины, МГц | 64 | 200 | 144 |
время импульса, нс | 610 | 200 | 120 |
Итак, что жы мы видим? Ожидаемо на почти втрое большей частоте шины H750 имеет в три раза меньшее время. Но посмотрите -, а risc-v то при меньшей частоте шины дает вдвое меньшее время! Это очень интересно… А если еще и оптимизировать код, думаю, можно выдать еще на 10–15% меньшее время. Ну тут конечно, надо не забывать о скорости работы самого порта — у всех была выставлено максимальная скорость (это 40 МГц для ARM и 50 МГц для RISC-V), так что по этому параметру надо было бы округлять до 20 нс.
И всё равно, для «быстрых» приложений RISC-V, похоже всухую выигрывает у ARM. Если не согласны, напишите в комментариях, как говорится :)