Вы немного запутались, Keli и IAR это среда разработки. Как и Arduino IDE, как и mbed как и Espruino Web IDE. Если грубо. Плюсы Keli и IAR это превосходные возможности отладки, доступ ко всем ресурсам микроконтроллера, Вы можете сделать все, что возможно сделать на данном микроконтроллере. Минусы требуются серьезные знания. Плюсы Arduino IDE, mbed, Espruino Web IDE легкий старт, не требуются серьезные знания, простая среда разработки. Минусы минимальные возможности отладки, ограниченный доступ к ресурсам. Тут нужно пояснить, по сути, Вы будете ограничены библиотеками которые подготовили разработчики данных сред. Правда, справедливости нужно заметить, большинство возможностей уже поддерживаются. Опять же упрощено. CMSIS - библиотека работы с регистрами, StdPeriph - Standard Peripheral Libraries, библиотеки для работы с стандартной периферией, HAL - High Access Level должны заменить StdPeriph. Если идти по пути Keli, IAR вы разберетесь с документацией, принципами работы со стандартными библиотеками и т.д., так, что да, это значительно упростит знакомство с другими STM32. Если идти по пути Arduino IDE, mbed, Espruino Web IDE, то там все просто. Чего не знаю, того не знаю, когда-то делал сравнение с StdPeriph, может будет полезно. Вам нужно смотреть в сторону Arduino IDE, mbed, Espruino Web IDE, но подсказать, что лучше увы не могу.
Приобрел то что нашел поблизости, а именно "STM32 Value line discovery". Довольно простая учебно-отладочная плата, зато не дорогая и вполне достаточная для начального изучения. Немного покурив тему предварительно, установил связку STM32Cube + Keil. Неожиданно все оказалось проще чем я боялся, все сцепилось и начало работать без бубна с первого раза. Настройка портов в Cube процедура довольно интуитивная, собственный блинк на оба диода сделал почти сразу, причем через адресацию на порты, но оказалось что с помощью HAL все это делается почти так же просто как в Arduino. Второй блинк сделал на прерывании одного из таймеров, это мне показалось еще проще чем на родном AVR! Изменения настроек в Cube меняют текст программы налету, не меняя написанного вручную, а это очень удобно. Третье что успел за вечер - попробовал работу с бортовой кнопкой. Оказалось, что она уже снабжена аппаратным антидребезгом и притянута внешним резистором к земле, а потому PULLUP на ней не работает, а PULLDOWN лишен смысла, в остальном же все отлично. Потом попробую настройку UART, SPI и так далее. Разумеется, такой подход не "тру", суровые мужики все делают вручную (желательно вообще по адресам а не по портам даже, а то и в машинных кодах, чего мелочиться) но в данном случае меня он более чем устраивает. Такой конструктор почти полностью избавляет от мучительного изучения новой (и гораздо более сложной) аппаратной части и позволяет сразу перейти непосредственно к творческому процессу. Что, в общем то и требовалось. Что не понравилось. Если сохранить свой труд и закрыть все инструменты, а потом открыть его сперва в Cube, а не в Keil и нечаянно сгенерировать, то проект станет вновь девственно чистым. Так я потерял свои небольшие тестовые наработки, который не очень то жаль, но перспектива насторожила. Одно неверное движение и начинай все сначала. И второе, тоже на перспективу, бесплатный Keil ограничивает размер кода, по слухам от 32 до 64Кб, во что рано или поздно может упереться работа. А цена на полноценный Keil... лучше бы я ее не узнавал. Альтернатива в виде хваленого CooCox не устраивает, так как экспорт проекта из Cube в него сложен, многоступенчат, утомителен и вообще адский адЪ, любая правка будет наказанием. В целом, на проверку черт оказался не так страшен как казался. Жду платы из заголовка, которые можно использовать в реальных устройствах, правда пока не представляю что это будут за изделия достойные такой вычислительной мощи. Но все же лучше пусть они будут, чем их не будет. )
Нахожусь в небольшом недоумении. Запустил для сравнения одинаковые по сути простейшие тесты производительности на скорость дергания ногой. Дергаем на Atmega328 так: Код (C++): for (uint16_t i = 0; i < 60000; i++) { PORTB |= 1 << 2; PORTB &= ~(1 << 2); } На STM32F100 так: Код (C++): for (uint16_t i = 0; i < 60000; i++) { GPIOC->ODR |= 1<<8; GPIOC->ODR &= ~(1<<8); } То есть максимально быстро на одной и той же частоте - 16МГц. Ну, думаю, посмотрим как ARM сейчас порвет AVR в лоскуты! В результате у AVR 30мс, а у ARM 78мс. Понимаю, что такого быть не должно, а в чем причина не соображу. Что я сделал не так?
Даже если так, почему медленнее в 2,5 раза то? А вообще там 16 ножек на порту. Нет. Но в этом случае использовано прямое обращение к ножке порта без всяких digitalWrite, куда уже короче? Если только в номера регистров, но по сути это тоже самое. Как еще подрыгать ножкой максимально быстро?
Попробуйте простую запись в порт: порт В = FF, порт В = 00 на АВР и, наверно на STM есть аналогичные 16-разрядеы команды. Даже интересно.
На STM тоже самое, только 0xFFFF, например, 16 разрядов же. Думаете всем портом быстрее мигать будет?
При мигании портом время почти сравнялось, у AVR 22мс, у ARM - 20мс. Что еще более странно, т.к. получается, что накладные расходы в виде логики у ARM происходят медленнее? За счет того что пинов 16 а не 8?
Ну вот скорость работы с портами у STM пока что не впечатлила. А ведь это одно из основных деятельностей МК - ножками дрыгать. Понятно, что можно разогнать частотой кварца, но в равных условиях преимуществ не вижу. Надо будет сравнить их на вычислительных процессах, какую нибудь задачку им повесить для работы в уме. Наверное уж тут то Кортекс себя покажет.
Для успокоения сделал еще через HALовские процедуры (типа наших digitalWrite), мало ли, вдруг они знают способ лучше. Вот так: Код (C++): HAL_GPIO_WritePin(GPIOC, GPIO_PIN_8, GPIO_PIN_SET); HAL_GPIO_WritePin(GPIOC, GPIO_PIN_8, GPIO_PIN_RESET); Как и ожидалось, результат перевалил за сотню мс. У них способ хуже. )
Например для AVR (навскидку без дисассемблирования): i++ в цикле -- два такта, т.к. 16-тибитное число i < 60000 сравнение и переход -- два такта сравнение (16-тибитное число) + два такта переход в начало цикла PORTB |= 1 << 2; -- один такт PORTB &= ~(1 << 2); -- один такт итого: 8 тактов, на частоте 16 МГц -- это 500 нсек на одну итерацию цикла или 30 мсек на 60000 итераций. Что там у ARM'а -- надо смотреть. Может ARM'овский компилятор плохо работает с операциями сдвига (типа 1<<8). AVR'ный компилятор (avr-gcc) на этапе компиляции вычислит значение сдвига (1 << 2 = 0x04) и вовремя работы прошивки будет использоваться вычисленное число, а не производится реальный сдвиг (такая вот оптимизация). С использованием цикла этот способ и есть максимально быстрый, точнее обеспечивающий минимальный период. А чего Вы хотели, если у контроллеров частота одинаковая (16 МГц) -- тут как код не оптимизируй, а дрыгать они будут с примерно одинаковой частотой. Частоту надо повышать. Вроде как у STM32F100 максимальная частота 24 МГц против 20 МГц у AVR'ок.
Я так примерно и понял, что как ни крути и дрыгают в прямой зависимости от системной частоты. AVR дергает практически с минимальными задержками, ARM за счет своей 16 биной адресации чуть медленнее. Надо бы их на вычислениях сравнить, тут 32 бита против 8 должны себя показать. Есть готовый кусок кода для погонять в цикле?
Очередной тест. Теперь сравнил скорость работы внутри памяти, в частности сортировка массива пузырьковым способом. Массив в 100 элементов сортируется 60000 раз. Вот такой код: Код (C++): uint8_t swop; uint8_t mass1[100]; PORTB = 0xFF; for (uint16_t i = 0; i < 60000; i++) { for (uint8_t ii = 0; i < 99; i++) { for (uint8_t j = 0; j < 99; j++) { if (mass1[ii] < mass1[j]) { swop = mass1[j]; mass1[j] = mass1[ii]; mass1[ii] = swop; } } } } PORTB = 0; Результаты: Atmega328 - 48,56мс, STM32 - 44,35мс. С перевесом менее 10% побеждает STM. Признаться, ждал большего, раз в несколько. Испытал очередное разочарование. На очереди тест АЦП, пусть хоть тут удивит!
Тест АЦП. В обоих случаях использовалась библиотечная функция, analogRead() и HAL_ADC_GetValue() соответственно. Замер производился 60000 раз одного и того же пина. Результаты: Atmega328 - 3,87с, STM32 - 1,78с. Ура! В два раза быстрее! Но если e AVT слегка ускорить АЦП вот так: Код (C++): #define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit)) #define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit)) void setup() { sbi(ADCSRA, ADPS2) ; cbi(ADCSRA, ADPS1) ; cbi(ADCSRA, ADPS0) ; } То AVR берет попу в горсть и решает задачу за 0,9с, то есть в 4 раза быстрее себя и в 2 раза быстрее чем STM. Разочарование дубль три. (