В этой короткой заметке я попытаюсь сравнить три разных микроконтроллера по времени реакции на внешнее прерывание. Дело это интересное, просто потому что иногда микроконтроллер должен реально контролировать и желательно по-быстрее. Ну и конечно, хочется оценить работу шины, прерываний и всего остального.
Итак, схема опыта очень проста - будем использовать 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. Если не согласны, напишите в комментариях, как говорится :)