Куда пропали процессоры stm32
STM32 vs MDR32 – счет не в нашу пользу.
В соответствии с программой импортозамещения, введенной в России с 2014 года, предполагалось по возможности заменить ЭРИ иностранного производства на отечественные аналоги. Выпущенная АО «ПКК Миландр» серия ИМС 1986ВЕ9х – ARM микроконтроллеров на базе ядра Cortex M3 является ближайшим аналогом микроконтроллера STM32F10x европейской фирмы ST Microelectronics, и поэтому должна существовать возможность применить с некоторыми доработками российский аналог там, где уже успешно работает STM32. Именно этой задачей я и занялся, а именно начал внедрять ИМС К1986ВЕ92QI в устройство силовой электроники в качестве управляющего контроллера. Изначально устройство разрабатывалось на микроконтроллере STM32F10x, программное обеспечение было написано на GNU ARM Assembler, так как требовалось большое быстродействие, а встроенный «сишный» компилятор Keil этого не обеспечивал. Из периферийных блоков использовались TIMER, ADC, DMA, UART, NVIC и EXTI. Далее будут рассмотрены все сложности, которые возникли в процессе адаптации устройства к ИМС К1986ВЕ92QI, а также описаны основные отличия периферийных узлов.
Ядро, что у одного, что у другого – Cortex M3, RISC ядро ARM архитектуры, разработанное британской корпорацией ARM Limited. АО «ПКК Миландр» приобрело лицензию на данное ядро в 2008 году, и впоследствии реализовало его в серии микроконтроллеров 1986ВЕ9х. ST Microelectronics выпускает микроконтроллеры на базе Cortex M3 с 2007 года, в том числе серию F1, и является лидером по соотношению цена/качество.
Если в STM32F10x реализовано три вида 16-битных таймеров: самые простые (Basic Timers), таймеры общего назначения (General Purpose Timers) и таймер с расширенными возможностями (Advanced Control Timers), то разработчики АО «ПКК Миландр» пошли иным путём – они сделали три таймера с расширенным функционалом, хотя и назвали их «Таймеры общего назначения». По сравнению с другими периферийными устройствами таймеры в 1986ВЕ9х довольно неплохие. Не получилось реализовать в проекте только синхронный запуск двух таймеров по событию третьего таймера и самостоятельную перезагрузку при захвате фронта для организации циклической работы, так, чтобы отслеживать периодичность фронтов сигнала, и, в случае если фронт не успел, уходить в прерывание счетчика при CNT равном ARR. Вдобавок обнаружилась проблема с прерываниями таймера MDR_TIMER1, но винить в этом только таймер неправильно, поскольку проблема может быть на стороне NVIC, подробнее об этом я напишу ниже. Также к таймерам относятся SysTick и Watchdog, первый входит в состав ядра и является простейшим вычитающим счетчиком, а вторые (IWDG и WWDG) ничем не отличаются от STM32F10x.
АЦП в обоих вариантах сдвоенное и имеет одинаковую скорость преобразования – 512 тысяч выборок в секунду, но по функциональности и удобству отечественному периферийному блоку далеко до иностранного аналога. Возможность запускать преобразование АЦП от внешних событий в STM32F10x позволяет синхронизировать несколько периферийных блоков без отрыва ядра от текущей задачи и производить выборку в нужный момент на кривой измеряемого сигнала. Это во многом облегчает и упрощает работу с STM32 и является его большим плюсом. В 1986ВЕ9х по каким-то причинам это не реализовали. Иностранный аналог имеет возможность объединять измеряемые каналы в группы (инжектированные или регулярные) и измерять их в разных последовательностях, при том, если применять инжектированную группу (в которую входит до 4 каналов), то каждый результат будет находиться в своём регистре. Таким образом, результаты преобразований не перезатираются внутри группы, как это происходит при использовании регулярной группы, где регистр результата один на все каналы. В 1986ВЕ9х сделали подобие регулярной группы, при том, что синхронно разные каналы измерять невозможно. Синхронно можно измерять только одни и те же каналы для увеличения скорости преобразования.
Вот здесь у 1986ВЕ9х начинается “мрак”. Этот блок после многоразового прочтения документации и анализа его работы поверг меня в уныние. Один вопрос гложет меня до сих пор: «Зачем городить такой DMA, если он не может работать без участия ядра?». Из всего описания DMA в документации самое нужное написано в глубине раздела, цитирую: «После выполнения контроллером N передач, контроллер устанавливает значение поля cycle_ctrl в b000, делая тем самым channel_cfg данные “неправильными”. Это позволяет избежать повторения выполненной передачи DMA». Из этого следует, что, перед приходом запроса DMA, например, от любого периферийного блока, коих там не много, cycle_ctrl должен содержать значение «Режим работы при выполнении цикла DMA» не равное b000, а, так как после выполнения предыдущего цикла данные в том месте обнулились, то для нормального функционирования нужно останавливать ядро в текущей задаче и успевать вносить данные (b001 – основной режим, b010 – режим авто-запрос или b011 – режим пинг-понг) в то самое поле cycle_ctrl. Преклоняюсь перед “гениальностью” разработчиков данного DMA! В STM32F10x все просто, доступно и легко, переправляешь данные куда душе угодно по запросам DMA без участия ядра.
Проблем не возникло, все работало, как надо. Это единственный периферийный блок в творении АО «ПКК Миландр», который у меня не вызвал нареканий. Из плюсов можно отметить: у STM32F10x имеется режим SmartCard и поддерживается сеть LIN; у 1986ВЕ9х присутствуют буферы FIFO, как на передачу, так и на приём. В остальном все примерно одинаково, кроме того, что в микроконтроллерах ST Microelectronics число блоков UART от двух до пяти, а в серии 1986ВЕ9х их только два.
NVIC реализован в ядре Cortex M3 и предназначен для организации прерываний, как от внутренних блоков, так и от внешних линий (EXTI). В зависимости от конкретной реализации он может поддерживать до 240 линий запросов прерываний. В микроконтроллерах STM32F10x из 240 задействовано 60 прерываний, а у ИМС 1986ВЕ9х их всего 32. Это явный показатель того, что развитость периферийной инфраструктуры отечественного микроконтроллера отстаёт от зарубежного аналога.
В микроконтроллерах 1986ВЕ9х такого блока в принципе нет, у них четыре линии с NVIC напрямую идут на ножки микроконтроллера, поэтому он может различать только присутствие или отсутствие логического уровня. Если этот уровень установился (логическая ‘1’), то вызывается обработчик прерывания, и если к моменту выхода из обработчика прерывания уровень не изменится (станет логическим ‘0’), то мы тут же опять попадем в тот самый обработчик прерывания. Совсем по-иному сделали в STM32F10x, где прерывания возможны почти с любой ножки, и отслеживаются не уровни, а фронты и/или срезы сигналов. Зачастую в программе нужно отследить изменение сигнала и вызвать при этом обработчик прерывания только один раз, а не так, как нам это предлагает АО «ПКК Миландр». На весь блок EXTI в иностранном аналоге отведено 7 линий в NVIC, поэтому несколько выводов микроконтроллера сгруппированы и прерывания с них попадают в один обработчик.
Микроконтроллеры ST Microelectronics самые распространенные из всех с ядром Cortex M3. Причин этому несколько: недорогие отладочные платы, сами микроконтроллеры дешевые, доступная и понятная документация, и т.д. Основным документом при работе с STM32F10x является RM0008 «Reference manual», где подробно и ясно, хоть и не на родном языке, описаны принципы функционирования и представлены необходимые при программировании данные. Совсем иначе дела обстоят у АО «ПКК Миландр», основным документом является «Миландр. Спецификация на серию 1986ВЕ9x, версия (на момент написания статьи) 3.14.0 от 12.10.2018» и качество его оставляет желать лучшего. Ошибки и опечатки везде, к примеру: основные таймеры сначала были 32-битные, затем нормализовались и стали 16-битными, в описании DMA, где и без того все путанно и туманно, одно и то же фигурирует под разными именами (на рисунке 131 области памяти обозначены как: Control, Destination End Pointer и Source End Pointer в тексте на следующей странице они уже фигурируют под другими именами: channel_cfg, dst_data_end_ptr и src_data_end_ptr соответственно), поэтому разработчик, который собрался применить данный периферийный блок, должен каким-то образом сопоставить эти имена. И так перечислять можно еще долго. В основную документацию для чего-то поместили раздел «Система команд» ассемблера, хотя это относится конкретно к ядру Cortex M3, и абсолютному большинству разработчиков не требуется так, как пишут на «Си». Создается впечатление, что документацию на серию 1986ВЕ9x писали студенты–практиканты, мало чего понимающие в том, что излагают, и проверить их никто не удосужился.
Программаторы и среды разработки
Так как STM32F10x широко распространены, средств программирования и отладки тоже хватает. Сама ST Microelectronics выпускает недорогой ST-Link v2, а также программаторы многих сторонних производителей поддерживают STM32, например J-LINK. Среды разработки так же в достатке: Keil, IAR, CooCox, Eclipse, Atollic, и т.д. ST Microelectronics даже выпустила специализированный софт «STM32CubeMX», который генерирует «сишный» код под конкретную конфигурацию. 1986ВЕ9x присутствуют только в Keil, а программатор в моем случае подошел только отечественный «ChipProg-481» фирмы «Phyton».
Помехоустойчивость и «баги»
В реализуемом устройстве необходимо было производить измерения АЦП в середине импульса таймера (ШИМ), в STM32F10x для этого имеется необходимая инфраструктура, а именно возможность запуска преобразования АЦП по событию обновления счетчика. По причине того, что в 1986ВЕ9x такая инфраструктура отсутствует, пришлось осуществлять запуск преобразования АЦП из прерывания обновления счетчика MDR_TIMER1, вот здесь и обнаружился «баг». Прерывания происходили, как это и требовалось, при каждом обновлении таймера, но также появлялись “блуждающие” прерывания в хаотичном порядке, когда не происходило обновления счетчика. Эти ложные прерывания могли либо в период ШИМ появляться по нескольку раз, либо вообще отсутствовать на протяжении нескольких периодов. Очевидно, что этот «баг» таймера MDR_TIMER1, либо NVIC, или вообще где-то между таймером и NVIC (линии связи). В итоге продолжительных и безрезультатных изысканий решено было прекратить адаптацию 1986ВЕ9x в устройстве и оставить STM32F10x на своем месте, где он безотказно исполняет свои функции и по сей день.
Ведущие фирмы-производители микроконтроллеров для освобождения процессорного времени внедряют разные методы коммуникаций между периферийными блоками: ST Microelectronics связывают блоки отдельными линиями; Microchip сделал специальный блок «EVENT SYSTEM» для коммутирования событий. В отечественных микроконтроллерах 1986ВЕ9x периферийные блоки существуют отдельно друг от друга, имея линии связи только с ядром. Мною было затронуто далеко не всё, что имеется на «борту» серии 1986ВЕ9x, но я уверен, что есть разработчики, которые углубились дальше и нашли больше. О причинах того, почему у АО «ПКК Миландр» такие микроконтроллеры, я могу только догадываться, ведь талантливыми инженерами всегда славилась Родина. Видимо, все они трудятся в другой сфере, либо вообще на другое государство. Ну, а мы имеем то, что имеем, поэтому нам остается только надеяться, верить и ждать, что, все-таки, состояние дел в этой высокотехнологичной области изменится в лучшую сторону.
Данная статья, которая является еще одним "быстрым стартом" в освоении ARM-контроллеров, возможно поможет сделать первые шаги в освоении 32-битных контроллеров ARM на базе ядра Cortex-M3 - STM32F1xxx серии. Возможно данная статья (которых на эту тему появляется как грибов после дождя) станет для кого-то полезной.
33 thoughts on “Контроллеры от GigaDevice GD32F103xxxx. Попытка миграции с STM32F103xxxx”
Ну… как бы гигадевайс это вполне себе бренд. Только раньше они флеш делали. Это раз. Во вторых, гд32 превосходит стм32 почти во всем. По крайней мере в этих семействах. Ну третье… стм32 сейчас купить просто нельзя. Нигде их тупо нет. Вообще. Везде срок ожидания от года и цена при этом космическая.
А F0 семейство? Оно же посвежее чем F1 и должно быть более доступно при схожих характеристиках.
Также, ЕМНИП, потоньше техпроцесс там.
Полного совпадения по ногам и периферии нет. А проблемы с доступностью есть :)
Кроме как на Али их можно у Элтеха купить. Они в РФ дистрибьютеры
А в STM32Cube с этими камнями работать тоже можно?
По идее да, но может не заоаботать что-то из-за таймингов. Ну и отлаживать придется переброской проекта в эмбитз или делать в кейле с плагином.
А в STM32Cube с этими камнями работать тоже можно?
Можно, но из-за таймингов не все может работать. Т.к. хз как индусы там написали эти библиотеки.
Можно. Работаю. Только там подкрутить надо одну настройку, чтобы Куб и чужого ребенка распознал. Высплюсь, дам ссылку на подкрутку.
Самое для меня смешное, что у них есть девайсы из которого Cortex M достали, RISC-V засунули, а всю обвязку не тронули вообще. Очень смешные кадаврики получились. Вроде и RISC-V а вся периферия, вообще вся, STM32-совместимая.
Я видел. Но я пока не понимаю профитов, кроме скорости. На него линух можно будет натянуть?
Нет. Это ровно тот же контроллер, только вместо CM-3 там RV32 чего-то там.
А камни от Nuvoton не пробовали? Тот же ARM.
Коротко: бинарник для STM32F103VET запустился на GD32F103VET на ура за исключением I2C. Когда начал разбираться, показалось, что GD и вправду почистил errata STM32 I2C в некоторых местах, но и добавил своё. Не буду вдаваться в подробности, но скажу, что устанавливать биты POS и/или BUFIE еще до начала передачи адреса (ID) I2C периферии в GD32F нельзя: бит SB (старт) не сбрасывается после передачи адреса (ID), и логика (прерывание) зацикливается. Это странно, т.к. POS или BUFIE никак не связаны с передачей адреса, а лишь перемещают NAK и разрешают прерывание по приему, что правильно работает на STM32F1хх. К счастью, логику можно построить с установкой POS/BUFIE и после передачи адреса, что работает как на GD32F1xx, так и на STM32F1xx. Ноги предыдущей логики росли с давних времен (примерно 2009) и базировались на примерах для STM32.
Еще интересен момент, что бинарник прекрасно работает и на GD32F303VET, который внутри имеет Cortex-M4.
Ага, еще по ADC. Температурный датчик (канал ADC) всегда показывает 0xFFF. Но это при нормальном питании в 3.3V. Случайно обнаружил, что при 3.2V все работает правильно; на 303 такого эффекта нет.
В некоторых форумах на иностранных языках было упоминание, почему GD шустрее STM: якобы, GD, на самом деле, всегда работает из теневого (дополнительного) RAM, куда при старте копируется содержимое… SPI-Flash, которая и есть та странная насадка на основной кристалл. То есть, по крайней мере GD32F1хх — это такой гибрид.
Я пока не занимался проверкой этого утверждения, но я точно заметил, что запись во flash из самой программы работает явно медленнее (по ощущениям — на 30-40%), чем на STM32F, а камень в целом шустрее.
Сейчас жду образцы GD32F130K8U6, которые по пинам и всему есть аналог STM32F051K8U (используем во многих проектах), но в GD ядро -M3, а не -M0.
Как и обещал для STMCubeIDE цитата с одного форума:
Yes, hate the blue pill with clone MCU on it. In my case I have a CKS32F103… instead of STM32F103…
However, if you do end up with one, there is a way to get it working with OpenOCD. >>
1. Use OpenOCD as your debugger (GDB will not work)
2. Find the config file : stm32f1x.cfg
Location is similar to this : >>
C:\ST\STM32CubeIDE_1.3.0\STM32CubeIDE\plugins\com.st.stm32cube.ide.mcu.debug.openocd_1.3.0.202002181050\resources\openocd\st_scripts\target
3. Add the following near the top of stm32f1x.cfg (before the first If – statement):
set CPUTAPID 0
The zero tells OpenOCD to ignore id numbers, which means all clones or genuine MCUs will work.
4. Save the changes. Now your flash and debug should work.
Note: If you change to OpenOCD without changing “stm32f1x.cfg”, you will get the following Error: “UNEXPECTED idcode: 0x2ba01477…. Expected: 0x1ba01477”, and you will again be stuck.
Шаблонное метапрограммирование.
По мере изучения С++, я вижу, что все пути ведут туда. Но пока я не способен (легко) понимать такой код, а уж тем более написать.
У меня к такой библиотеке вопросы:
1. Полностью ли абстрагирует эта конкретная библиотека железо, во всей его сложности? Вопрос шире. Пусть не эта конкретная, а в принципе, можно ли с помощью шаблонного метапрограммирования написать библиотеку, с помощью которой можно включить железо в любом описанном в datasheet режиме?
Не будем брать GPIO, возьмем АЦП. Какой-нибудь сложный режим совместного использования отдельных модулей АЦП, с пересылкой по DMA, запуском по таймеру. Повторюсь, простая периферия не интересует, интересует сложная в извращенных режимах.
Если кто-то из гуру положительно ответит на этот вопрос, буду расти в ту сторону.
2. Вот пишу я код в таком стиле, ухожу из конторы. Сколько будет стоить специалист, способный поддерживать такой код? Как легко его будет найти?
Хорошо, допустим можно написать на шаблонах вообще все, что угодно, во всей полноте. Что мы видим? С помощью достаточно сложного в применении языка шаблонов мы заставляем компилятор сгенерировать нужный нам код.
Почему бы не взять для генерации исходников более мощный язык, предназначенный для манипулирования текстом? Perl, Python, Javascript и так далее.
Описать в декларативном стиле (a-la QML) в JSON формате, что нам нужно от периферии. Парсим этот файл, генерируем C++ исходник, в котором классы периферии имеют простое АPI, минимально необходимое в конкретной задаче.
Методы класса наш генератор реализует напрямую регистрами максимально эффективно.
Генератор должен не давать использовать одну периферию в разных местах, GPIO, задействованные в АЦП не задействовать для ШИМ.
Отсюда плавно приходит в голову использовать GUI для генерации JSON файла описателя.
Та-дам! Вот и он — STM32CubeMx.
Для меня, пока, круг замкнулся. Тот Cube, который сейчас есть, пускать в свой код нельзя, только для быстрого старта — сгенерил, посмотрел, взял в свой код, навел порядок.
Тот Cube, который я хотел бы видеть:
открытый исходный код — чтобы тысячи эмбеддеров совместно развивали проект (тысячи бесплатных тестировщиков!),
гибкий, настраиваемый — чтобы код генерился в моем стиле, раскиданный по мной описанному заголовочному файлу.
Введение
Почему ARM?
1. Есть из чего выбрать (разными производителями сегодня выпускается более 240 ARM-контроллеров)
2. Низкая цена (например за 1$ можно получить 37хI / O, 16K Flash, 4K RAM, 2xUART, 10x12bitADC, 6x16bitPWM).
А начнем нашу работу с контроллеров фирмы ST Microelectronics. Контроллеры на основе ядра ARM Cortex-M3 характеризуются широким набором периферии, высоким уровнем рабочих характеристик, низкой цене
P.S. В самом начале создается впечатление, что ARM'ы это какие-то страшные (в пайке, разводке, программировании) существа. Но это только на первый взгляд :) и вы в этом сами убедитесь.
Итак, изучать ARMы будем на примере контроллеров STM32F1. Одновременно эта серия имеет несколько линеек:
- Value line STM32F100 - 24 МГц CPU, motor control, CEC.
- Access line STM32F101 - 36 МГц CPU, до 1 Mб Flash
- USB access line STM32F102 - 48 МГц CPU with USB FS
- Performance line STM32F103 - 72 МГц, до 1 Mб Flash, motor control, USB, CAN
- Connectivity line STM32F105/107 - 72 МГц CPU, Ethernet MAC, CAN, USB 2.0 OTG
Также существует следующая классификация:
STM32F101xx, STM32F102xx, STM32F103xx
STM32F101xx, STM32F102xx, STM32F103xx
Connectivity line devices
Придется часто лазить здесь
Еще скажу несколько слов об этом ресурсе. Ясное дело, выбираем нужный контроллер и попадаем на страницу с кучей файлов в формате. рdf. (вкладка Design support). Можно читать все, но достаточно ознакомиться с такими файлами:
1. REFERENCE MANUAL (содержит полную спецификацию на контроллер).
2. ERRATA SHEET (содержит описание ошибок, которые могут возникать при работе с периферией).
3. Остальные документы содержат примеры работы с периферией, вопросы, связанные с программированием, описание некоторых библиотек, а с самого низа страницы можно найти EVARM-проекты демоплат и подобное ПО.
Комментарии ( 125 )
Значит я плохо написал. Спор не про HAL — пользоваться или нет. Уровень абстракции периферии нужен. Вопрос в том, как его создать — универсальный (библиотека, которая может все) или каждый раз читая даташит и реализуя свой простенький API.
Хочется универсального. Но не получается.
mbed видел, пользовался, сейчас в проекте, буду избавляться. GPIO абстрагирует хорошо, спору нет. А вот хотя бы PWM — не может. Как чуть чего то посложнее хочется от ШИМ лезем внутрь и правим.
В mbed мне нравится (меньше всего не нравится, вернее так), что сделана проверка — можно ли назначить на эту ногу такую альтернативную функцию и интерфейсы классов.
Хм. А еще никто не начал разработку опенсорсного интерактивного парсера даташитов? Чтобы тадам- и выдал тебе приложение, в котором гуи с интерактивной настройкой всей периферии желаемого мк и кнопкой «сгенерировать код» на любом доступном языке.
Можно обобщить информацию из ПДФ
чтобы по крайней мере сделать удобную кросс-ссылочную справку
но тут в голову приходит мысль, что сначала правильнее обобщить имена/фамилии/явки из заголовочных файлов, чтобы не напороться больно на опечатки или ошибки в книжках…
и тут понимаешь, что надо понять и простить 963 процессора…
чтобы потом сделать интерактивный помощник генератор кода на любой вкус… как в Дельфи — хош под Винду, хош под Андроид, хощ под ёпл. (хал/спл/регистр)
но тут нежданно негаданно приходит лето…
У ARM, специально не для людей, а для роботов программ (IDE, плагинов, визардов), в составе стандарта CMSIS есть подстандарт на файлы SVD — огромные даташиты, описывающие всю периферию чипа, в формате xml.
По сути, хедер-мегапортянка описания периферии из состава фирменной либы CMSIS — это просто текстовая отрыжка для гуманоидов этого xml-даташита, сгенерированная программкой SVDConv.exe и обработанная затем руками несчастных программерных негров — Doxygen, причесывание, комментарии и т.п. тупая работа. Видимо в фирмах на эту черную и тяжелую работу бросают самых молодых или самых тупых/провинившихся — это как на флоте раньше заставляли скрести ножами или осколками стекл палубу и точить напильником якорь, чтобы блестели.
Никто даже не сделал считыватель желаний напрямую из мозга.
Подумал — тадам и устройство работает.
Не надо никаких ГУИ-ШМУИ и кнопок для языков.
Andy Brown неплохой блог, но он как бы на продажу нацелен. поэтому и выглид и содержание поддерживает.
А вообще, я думаю, что будущее embedded контроллеров за связкой [простое быстрое ядро]+[быстрая плис]+[матрица аналоговой периферии] на кристалле. А периферия программно подгружаемая (покупаемая).
И приложение для генерирования.
Возможностей будет куда больше.
Так это уже как 5 лет есть PSoC от Cypress. Но что там у них не заладилось — видимо никому это не надо. Может мне повезло, но собственно железо у меня занимает 5% от кода. Алгоритмы обработки гораздо более сложный вопрос. Тот же ST жмётся дать исходники для osMotion… — уже вторую неделю ковыряю. Да еще лицензии придумали. Наивные.
Попробую высказать свою точку зрения.
STM32 — это относительно более сложный МК, по сравнению с AVR-ками и MSP430. Это очевидно и не требует доказательств.
Разработчики, не первый год работающие с разными МК, привыкли к простеньким МК, и когда на рынке появились доступные Кортексы, оказалось, что люди не готовы их воспринимать как сложные изделия. Люди по инерции мышления (не задумываясь) пытались воспринимать эти новые МК как такие же простые МК, на подобие ATMEGA и MSP430. Ну, то есть люди ожидали, что они новые МК будут чуточку по-сложнее тех, с чем они имели дело до этого.
На деле, оказалось, что STM32 сложнее не «чуть-чуть», а на порядок. Во всяком случае сложнее значительно. Сложнее, чем ожидалось!
Сама по себе относительная сложность STM32 ничего не значит. В природе бывает ещё более сложные изделия. Другое дело, что STM32 как бы «не оправдал» негласных ожиданий разработчиков.
Ну, не оправдал и и фиг с ним! Но душа разработчика просит упрощения свалившейся внезапно сложности. Отсюда и всякие желания создать универсальную библиотеку.
Несбыточность желания создать такую библиотеку заключается в том, что:
БОРОТЬСЯ СО СЛОЖНОСТЬЮ МОЖНО ТОЛЬКО ОТКИДЫВАНИЕМ ФУНКЦИОНАЛЬНОСТИ
Прошу прощения за капс! Прочтите еще раз и вдумайтесь в сказанное, я его не зря выделил!
На Казусе перетирается тема «почему здесь не любят ардуинщиков?». Дак за то их и не любят, что Ардуино упростило жизнь разработчикам (я бы сказал — недо-разработчикам) за счет того, что скрыло от разработчика целый пласт возможностей процессора. Ардуино упростило сложность системы за счет откидывания функциональности.
И на самом деле — пока создаваемое устройство на базе Ардуино минимально по своей функциональности, оно вписывается в концепцию — простота и удобство. Но стоит начать писать на Ардуино сложный проект, как вся магическая сила Ардуино превращается в кошмар. Проект получается ничуть не проще, чем если бы он создавался на чистом Си.
Резюме. Нельзя из изначально сложной системы создать более простую путем перестановки акцентов. На выходе получатся те же яйца! При замене одной сложной сущности на другую, сложность не уменьшается, а увеличивается! Уменьшить сложность можно только за счет отказа от чего-либо. Упростить можно только пожертвовав какими-то не очень нужными вещами (функциональностью). И обязательно нужно что-нибудь принести в жертву. Например — объем кода, быстродействие, ещё что-нибудь.
Чудо не в том, что где-то сущетсвует волшебная палочка. Чудо в том, этой палочкой мы — разработчики — умеем пользоваться. Для других — это просто палка. И как бы мы эту палочку не разрисовывали разными узорами для них (других людей) она так и останется обычной палкой.
Я предпочитаю по старинке юзать CMSIS и управлять периферией с помощью регистров. По крайней мере у меня всегда твёрдая почва под ногами, и я знаю, что делает мой код. Череда выпущенных библиотек — это всего лишь отвлекающие игрушки для «гуглеров». Игрушки подменяющие одну сложность на другую с потерей чего-либо в качестве необходимой сакральной жертвы.
Это не так. Бороться со сложностью можно (и нужно) повышением уровня абстракции. Собственно, именно так работает человеческое мышление. Иначе говоря, абстрагирование это выработанный миллионами лет эволюции механизм, позволяющий нам оперировать понятиями весьма высокой сложности. Почему вместо того, что бы использовать этот инструмент надо пытаться упростить отбрасыванием функциональности, я не понимаю.
Резюме. Нельзя из изначально сложной системы создать более простую путем перестановки акцентов. На выходе получатся те же яйца! При замене одной сложной сущности на другую, сложность не уменьшается, а увеличивается! Уменьшить сложность можно только за счет отказа от чего-либо. Упростить можно только пожертвовав какими-то не очень нужными вещами (функциональностью).
Из неправильной посылки получается неправильный вывод. Упрощать можно разными способами, и не все они связаны с жертвами или потерями. Это особенно заметно в ПО, где львиную долю сложности составляют связи и зависимости между частями программы, а не собственно код как таковой. В этом случае можно сильно уменьшить сложность изолируя отдельные части программы путем локализации связей, объединяя небольшие кусочки данных с кодом, который с ними работает. Замечу, что жертвовать при этом ничем не приходится.
P.S. особенно порадовала фраза «Проект получается ничуть не проще, чем если бы он создавался на чистом Си.» применительно к ардуине. ардуина и написана на «чистом С» и уровень сложности и абстрактности там ровно такой же как и в любой другой либе подобного уровня (тот же libmaple).
В общем случае — это именно так. У меня нет возражений.
Но как Вы себе представляете повышение абстракции тех же портов? Повышение абстракции у USART-ов? Повышение абстракции у таймеров? А что будем делать с обработчиками прерываний, они-то как впишутся в концепцию повышения абстракции?
Ровным счётом, я не вижу ни малейшего способа избавить разработчика-программиста от знаний регистров и битов периферийных устройств МК.
На каком-то этапе создания абстактной программной модели МК может быть и удастся избавиться от регистров и битов, от той кучи знаний как это хозяйство работает и взаимодействует друг с другом. Но, мне кажется, наступит момент, когда кто-нибудь вытащит самую нижнюю карту и домик начнет падать. Скорее всего получится так, что автор абстрактной модели выкатит её со словами «Вот это избавит вас от необходимости нырять глубоко. Но если вам нужно более гибкое управление, то вам всё-таки придется изучать регистры и биты.»
И что мы имеем в итоге? А в итоге разработчик будет нести двойную нагрузку. Ему нужно будет знать абстрактную модель, и — как ни крути — ему придётся всё равно погрузиться в пучину регистров и битов. Единственным шансом на успех будет надежда на то, что это (в смысле — необходимость изучать регистры и биты) произойдёт не для всей используемой в проекте периферии, а только в каком-то отдельном модуле. Но по мере работы с разными проектами, программисту так или иначе придётся «погружаться» то по одному, то по другому периферийному модулю, и всё равно программист будет вынужден изучить работу большей части (если не все!) регистров МК.
Оставаться же на высоком уровне абстракции и не опускаться вниз до битов-регистров в отношении МК вряд ли получится. В отношении компов этот фокус канает только лишь потому, что вычислительная мощность (размер памяти, скорость работы процессора) значительно превосходят требования большинства «тяжелых» программ. Но микроконтроллеры мы обычно выбираем с очень небольшим запасом по мощности.
К стати, на рынке ведь имеются АРМ-ы с аппаратной Джавой (Jazelle) на борту! Почему они мало распространены? Ведь, казалось бы, берешь такой проц, заливаешь в него прогу (электронные часы + термометр или еще какую!) и радуешься жизни. Что не так?
P.S. особенно порадовала фраза «Проект получается ничуть не проще, чем если бы он создавался на чистом Си.» применительно к ардуине. ардуина и написана на «чистом С» и уровень сложности и абстрактности там ровно такой же как и в любой другой либе подобного уровня (тот же libmaple).
Я имел в виду, что человек, который пишет стретчи для Ардуино, он пишет только инициализацию модулей и бизнес-логику. За всё остальное, которое остается за кадром, отвечает библиотечный код Ардуины. В результате для ардуинщика откидывается целый пласт знаний (информации) как оно там под капотом всё работает. То есть для ардуинщика процесс написания программы для управления динамической индикацией в часах окажется проще, чем если бы точно такая же по функциональности программ была написана с нуля на чистом Си. Вот, что я имел в виду.
Но стоит попросить ардинщика написать прогу для более сложных устройств, то скорее всего ничего не получится. Хотя бы по тому, что апааратно помахать ножкой в Ардуино получается чуть ли не в 10 раз медленнее, чем если бы это было сделано на Си.
И да! Я думаю, Вы заметили, что в Ардуино для достижения чуть более высокого уровня абстракции были привнесены в жертву и размер доступной для пользователя памяти, и скорость работы.
Возможно, я ошибаюсь. Возможно, чего-то не вижу. Но мне кажется, что до тех пор, пока мы не получим МК с избыточной памятью и избыточным быстродействием, говорить о повышении уровня абстракции как-то не логично. Хотя…
… да! Можно, например, взять STMF4xx и собрать на этом камне какую-нибудь светодиодоморгалку. Написать код на какой-нибудь высокоуровневой системе (библиотеке). И, я уверен, это заработает. Но какова цена вопроса? А с другой стороны — объёмы памяти у МК растут, скорости растут, а цена снижается. Неисключено, что через деясток лет какой-нибудь продвинутый программист из кагорты гуглер-копипастер выберет МК с объемом памяти в 1 ГБайт для создания супер-пупер часы-термометр на неонках с синей светодиодной подсветкой. И это будет считаться верхом творчества.
Так мы в этом направлении толкаем мир?
Вы путаете два совершенно ортогональных процесса, отсюда и скептицизм. Абстрагирование нужно не для того, что бы «избавиться от той кучи знаний, как это хозяйство работает и как взаимодействует друг с другом». Оно нужно для того, что бы не держать эти знания постоянно в голове в процессе работы над, собственно, бизнес-логикой. И да, в некоторых случаях прийдется спускаться в эти детали и под конкретный проект и чип дописывать необходимые части. Вопрос больше в том, что делать это («поднимать капот и чинить мотор») вполне может делать кто-то другой. Ровно так же, как в программировании компов давно (я бы даже сказал очень давно) произошло разделение специализаций программистов на «системщиков» и «прикладников», так же вполне может произойти и в эмбеде.
По поводу ресурсов: компы не обладают таким уж большим запасом мощности. Обычно когда говорят, что в компах есть этот запас, рассматривается только одна программа. Но это давно уже не является обычным режимом работы. Вместо этого мы часто имеем дело с десятками, а то и сотнями процессов работающих одновременно.
По поводу Jazelle: во-первых, Java вовсе не признак высокого уровня абстракции. Во-вторых, продавцы Jazelle хотят изрядно денег, так что ожидать массового распространения не стоит, пока ситуация не изменится.
Насчет ардуино: рассматривать ардуино с точки зрения «эпик фейл повышения уровня абстракции» не учитывая а) целей, которые преследовали разработчики и б) целевой аудитории — некорректно. Для своих целей и для своей аудитории ардуино отлично доказывает, что повышение уровня абстракции может реально помочь решению множества задач. И да, именно в этом случае из-за выбора подходов и инструментов решение потребовало ресурсов. Но это совершенно не обязательное условие. И на каких-нибудь STM32F0 с минимальными ресурсами либы типа stm32plus позволяют получить достаточно высокий уровень абстракции и, одновременно, оверхед меньший, чем у SPL.
Насчет «цены вопроса»: думаю, на тот момент она будет в районе 10-ки баксов или что-то около того. Вы беспокоитесь о ресурсах МК, хотя это всего лишь кусок обработанного кремния, в массовом производстве он стоит копейки. Куда более важный и значительно более дорогой ресурс — время программиста. Вот для того, что бы рационально использовать этот ресурс и нужно повышение уровня абстракции.
Введение
Почему ARM?
1. Есть из чего выбрать (разными производителями сегодня выпускается более 240 ARM-контроллеров)
2. Низкая цена (например за 1$ можно получить 37хI / O, 16K Flash, 4K RAM, 2xUART, 10x12bitADC, 6x16bitPWM).
А начнем нашу работу с контроллеров фирмы ST Microelectronics. Контроллеры на основе ядра ARM Cortex-M3 характеризуются широким набором периферии, высоким уровнем рабочих характеристик, низкой цене
P.S. В самом начале создается впечатление, что ARM'ы это какие-то страшные (в пайке, разводке, программировании) существа. Но это только на первый взгляд :) и вы в этом сами убедитесь.
Итак, изучать ARMы будем на примере контроллеров STM32F1. Одновременно эта серия имеет несколько линеек:
- Value line STM32F100 - 24 МГц CPU, motor control, CEC.
- Access line STM32F101 - 36 МГц CPU, до 1 Mб Flash
- USB access line STM32F102 - 48 МГц CPU with USB FS
- Performance line STM32F103 - 72 МГц, до 1 Mб Flash, motor control, USB, CAN
- Connectivity line STM32F105/107 - 72 МГц CPU, Ethernet MAC, CAN, USB 2.0 OTG
Также существует следующая классификация:
STM32F101xx, STM32F102xx, STM32F103xx
STM32F101xx, STM32F102xx, STM32F103xx
Connectivity line devices
Придется часто лазить здесь
Еще скажу несколько слов об этом ресурсе. Ясное дело, выбираем нужный контроллер и попадаем на страницу с кучей файлов в формате. рdf. (вкладка Design support). Можно читать все, но достаточно ознакомиться с такими файлами:
1. REFERENCE MANUAL (содержит полную спецификацию на контроллер).
2. ERRATA SHEET (содержит описание ошибок, которые могут возникать при работе с периферией).
3. Остальные документы содержат примеры работы с периферией, вопросы, связанные с программированием, описание некоторых библиотек, а с самого низа страницы можно найти EVARM-проекты демоплат и подобное ПО.
Архитектура
Итак, наш контроллер STM32 содержит в себе Cortex-M3 процессор (M означает серию для бюджетных устройств). Для того, чтобы начать программировать ARMы и не пользоваться только default'ными примерам и настройками нужно иметь представление об их архитектуре. Для начала:
1) 32-битный МК, выполненный по Гарвардской архитектуре (память программ и данных разделены),
2) имеет несколько отдельных шин и 3-ступенчатый конвейер и более 10 регистров общего назначения, что позволяет выполнять операции параллельно и (большинство) - за один такт.
3) набор инструкций - Thumb-2 (смесь 16 - и 32-битных команд, ориентированный на компиляторы C / C + +).
Рассмотрим упрощенную блок-схему шинной архитектуры STM32:
Архитектура на примере линейки Connectivity devices
Итак, давайте коротко пройдемся по основам основ:
Матрица шин (bus matrix) - контроллер высокоскоростных шин, обеспечивающий независимую связь и арбитраж (в случае одновременного доступа к одному ресурсу) между системной шиной и шиной данных ядра, DMA, Ethernet (masters) и периферией - SRAM, FLASH, AHB (slaves) .
Шины ядра:
ICode bus - 32-битная шина инструкций — обеспечивает связь ядра с интерфейсом инструкций Flash.
DCode bus - шина данных — обеспечивает связь ядра с интерфейсом данных во Flash.
System bus - системная шина ядра — обеспечивает связь ядра и периферии
Flash interface (FLITF) интерфейс Flash-памяти — обеспечивает чтение, запись, стирание, чтение с буфером предварительной выборки, защиту памяти (от записи или чтения).
AHB system bus (Advanced High-performance Bus) — шина, которая связывает матрицу шин и периферийные шины APB (Advanced Peripheral Bus (Bridge)). Шина AHB, предназначена для управления, например, регистрами системной периферии (GPIO ЦАП и т.п.). Надо сказать, что шины APB1,2 работают на разных частотах: так APB2 может работать на частоте ядра, а быстродействие APB1 ограничено 36 МГц. Поэтому, на APB2 и висит скоростная периферия (АЦП, некоторые таймеры порты ввода / вывода и т.д.)
DMA (Direct Memory Access) — обеспечивает прямой доступ к памяти в обход ядра (нужно лишь задать что, откуда и куда передать, а DMA сам все возьмет и передаст кому надо через матрицу шин)
Reset & Clock Control (RCC) — обеспечивает тактирование ядра и периферии (которая по дефолту отключена от тактового сигнала) и сброс контроллера.
Стандартная схема подключения
Привожу базовую схему подключения контроллеров STM32F1 и некоторые их нюансы:
- Корпус: контроллеры STM32 помещены в корпусах LQFP с числом лапок от 48 до 144, при этом распиновка ножек контроллеров в одинаковых корпусах - совпадает, что не может не радовать.
- Питание:
- Контроллер питается от источника в 3.3 В (хотя можно подключать 2-3.6 В).
- Хотя напряжение питания равно 3.3В, много ножек контроллера толерантны к 5В сигналов (см. в спецификации лапки с пометкой FT).
- Vbat - используется для подключения резервного источника питания. Если в схеме резервный источник не используется, то Vbat надо посадить на общий источник питания.
- Vdd_1 . 4 подтягиваем к «+», Vss_1 . 4 сажаем на «-» источника питания.
- Спецификация на контроллер советует поставить параллельно источнику питания 5 конденсаторов в 100нФ (поближе к контроллеру) и один на 4.7мкФ (ближе к Vdd_3). Во многих схемах авторы часто не ставят их, думаю, если контроллер питается от чистого стабилизированного источника их можно не ставить.
- Питание АЦП (он питается напряжением 2,4-3,6 В) и цифровой части схемы в STM32 разделены (для большей надежности, очевидно) и если мы не используем отдельный источник для АЦП, Vdda / Vssa сажаем на соответствующие выводы общего источника, иначе схема может работать некорректно и непредсказуемо. В 100-пиновых корпусах есть еще дополнительные лапки опорного источника АЦП Vref + / Vref-. Vref- нужно повесить на Vdda, а на Vref + можно бросить от 2,4 В до Vdda.
- Внутреннего высокочастотного генератора на 8 МГц (HSI).
- Внутреннего низкочастотного источника тактовых импульсов 40 кГц (LSI).
- Внешнего высокочастотного осциллятора (HSE).
- Внешнего низкочастотного осциллятора на 32,768 кГц (LSE-генератор может работать вместе с HSE или синхросигналом и обеспечивает синхронизацию часов реального времени и работу оконного сторожевого таймера).
- Внешнего сигнала синхронизации (его частота должна быть целым делителем максимальной рабочей частоты контроллера).
- «заземлив» лапку NRST. Стоит сказать, что разработчик постарался и уже включил подтягивающий резистор этой лапки. (external reset)
- С помощью одного из сторожевых таймеров независимого или оконного (IWDG или WWDG reset).
- С помощью схемы слежения за низким напряжением (low-power management reset)
- при входе в режим Standby
- при входе в режим Stop
- Программно - установкой определенного бита
Для удобства пайки LQFP корпусов, существуют переходники. Продаются на eBay, бывают универсальные и под фиксированное количество ножек. Средняя цена: 1$ за штуку, посмотреть можно здесь.
В связи с тем. что последнее время цена на контроллеры растет быстрей чем стоимость битков, а, например, наш основной STM32F103VGT6 стал стоить вместо 500р аж 5000+, да еще с непонятными сроками ожидания от года и более, то мы начали вынужденную миграцию на аналоги. И взгляд пал на GD32, как на наиболее вменяемого и адекватного представителя китайпрома. А главная задача стала сделать универсальную прошивку которая бы одинаково работала как на STM32 так и на GD32. Чтобы можно было не глядя лить в наши машины смерти, не обращая внимания на то на какой архитектуре там мозги.
Купили мы небольшую партию этих чипов на Алиэкспрессе :))) Уже звучит жутко, но вариантов особо не было :)
Итак, на смену STM32F103VGT6 идет GD32F103VGT6 — китайцы не заморачивались вообще с названиями. И то правда. Чего нам париться? Совместимость у него по ногам полная, так что впаиваем его как есть.
А вот дальше начинаются различия. Во первых, памяти у него может быть больше. Аж до трех мегабайт флеша, против мегабайта у STM. Что, впрочем, не более чем потенциальная возможность, в моем случае, т.к. GD32F103VGT6 по объему памяти идентичен STM овскому камню. А еще у китайца тактовая частота выше, 108Мгц против 72Мгц у STM. Подозреваю Errata там тоже исправлена. Но, не факт что это к лучшему :)
Качаю Даташит, User Manual, а также подобие SPL только свою собственную. С примерами и кучей сорцев из которых прям торчат уши STM ;) Где то они даже копирайты не вычистили.Беглое чтение user manual дает ощущение дежавю. Ну да, почти полная бинарная совместимость с STM32 на уровне регистров их адресов. В некоторых местах, там где им не хватило конфигурационных бит, они использовали то, что у STM32 зовется как Reserved.
STM32
GD32
Названия регистров немного иные, название битов тоже. Но, на мой взгляд, эти имена часто звучат понятней чем в STM32, банально считывается на уровне аббревиатур логичней.
Сама же структура юзермануала списана почти один в один, как старательный троечник списывает курач, чтобы препод «не догадался». Но это даже к лучшему, проще находить если что.
Ладно, сидеть сравнивать построчно документацию мне лень, попробуем взять быка за рога, а там будь что будет. Буду решать проблемы по мере их поступления.
Беру свой рабочий проект над которым мы копаемся уже несколько лет и, как есть, байт в байт, ничего не правя вообще, заливаю в GD32…
Чем заливаю? Да тем же китайским ST-Link за сто рублей:
ST-Link Utility восприняла ускоглазого сынка как родного. Для нее чужих детей не бывает. :) Все корректно зашилось и … заработало. Подозрительно…
Хм, как прикольно. А что с отладкой? Жму Debug и… все заработало.
Тут, правда, стоит оговориться, что работаю я не с STM TrueStudio, а уже много лет пишу в EmBitz и с недавних пор они используют свой отладчик EbLink и вот ему пофигу что отлаживать, хоть STM хоть GD. Оно там просто работает. Брейкпоинты ставятся, память и регистры видятся, по шагам шагается, флеш прошивается.
С TrueStudio это уже не прокатывает. Они говорят, что мол это не STM и мы этих косоглазых знать не знаем, а что похожи, так это просто совпадение. Для Keil же GigaDevice, я слышал, выкатила плагин.
Диодики моргают, порты считываются, подтяжки встали на нужные уровни. Все пять UART бодро отработали… Аппарат вышел на связь с мозгами и встал в боевой режим и приготовился убивать человеков. Все вроде бы работает. А где секс? Чо секса не будет? Ну воооот.. А я было настроился…
Да щаз! При попытке пошевелить шаговыми движками наша машина смерти рванула с такой прытью, что я думал из нее все гайки ща посыпятся, даром что на нейлоне. Начинаю разбираться. Скорость тиков шаговых двигателей ровно в полтора раза выше. Но при этом мигалка blinker’a, а также все бодрейты уартов тикают штатно. Мигалка ровно раз в секунду на 100мс, а уарты заданы жестко и перебоев со связью нет. Из этого вывод, что как минимум SysTick тикает с правильной частотой. А от него и AHB APB и прочие частоты тоже. Но не может же так быть…
Опять углубляюсь в юзермануалы, сравниваю все побитно. Все совпадает. Все значения делителей тактовых частот совпадают. Один к одному, просто у GD множители PLL идут дальше и позволяют множить аж до х32. Проверяю по SysTick, просто инвертируя бит порта по его прерыванию — тикает верно. Проверяю по DWT таймеру — тикает верно. Timer2 тактуется тоже верно. То есть, по всем признакам работы периферии, SysClock идентичная. А работает быстрей.
Начинаю ковырять исходники и прихожу к выводу, что на максимальной скорости работы шаговых движков у меня тики происходят с такой скоростью, что половина задержки между тиками приходится не столько на выдержку таймера (с ней все в порядке), сколько на выполнение кода, переходы и прочее. Т.е. код выполняется быстрей… Проверяю гипотезу.
Делаю тупую задержку на цикле:
Сравниваю моргание на оригинальном STM и на GD — на GD в полтора раза примерно быстрей. И либо даташит врет и на самом деле SysClock работает на 108Мгц, а значения битов делителей значат вовсе не то, что написано и приводят со 108Мгц до стандартных частот шин, либо код и вправду исполняется быстрей за счет выборки команд.
Первый вариант весьма шизофреничен, т.к. какой смысл так извращаться, а на опечатку это не тянет вообще, т.к. это уже заговор какой то. А вот второй… второй может быть вероятен. Просто за счет того, что у GD более быстрая память и он команды из флеша берет быстрей.Но вот что странно, судя по вскрытиями чипов, у GD память реализована путем напаивания отдельного (. ) кристалла поверх кристалла контроллера и все это уже заливается в корпус. По идее, такая конструкция должна работать медленней. Китайцы сделали какое то кэширование? А может вообще суперскалярность с предсказанием переходов?
Ответ должен быть в сравнении битов настройки задержки выборки флеша. Сравниваю в STM32:
Регистр FLASH_ACR по адресу 0x40022000 и там у нас:
Младшие три байта отвечают за задержку. Я частоты конфигурирую ручками. Не верю я CMSISовскому SystemInit. Слишком часто его переписывали то так то эдак. Хрен знает, что там будет в очередной версии, а мне сюрпризы не нужны. Поэтому я иницилизацию частот написал сам, ручками. В моем коде сделано так:
То есть выборка команд будет через два такта. Что же у ГД по этому адресу прячется? Лезем в мануал:
Все то же самое, те же биты отвечающие за задержку чтения из флеша, но с пометочкой, которую я не сразу заметил. О том, что вся эта радость работает только если поставить бит WSEN в FMC_WSEN, а иначе оно не используется. В STM32 никакого такого регистра естественно нет и задержка работает если выставлена. Зачем китайцы встрелили себе в ногу, поломав совместимость в такой простой фигне непонятно. Что им мешало сделать так, чтобы все работало идентично? Ничего не мешало. Но тем не менее. Можно, конечно, тут добавить запись бита в байт по этому адресу, убедившись только, что на STM32 выстрел уйдет в молоко, попав в очередную Reserved секцию.
Окей, добавляем. Поскольку этого адреса у STM32 нет, то я его добавлю вручную, просто через указатель:
uint32_t *FMC_WSEN; FMC_WSEN = (uint32_t*)0x400220FC;
Бит WSEN там нулевой, поэтому достаточно по этому указателю записать единичку. Правда запись туда запрещена, нужно сначала разблокировать флеш. Записав два раза в регистр FLASH_KEYR ключевое слово 1 и слово 2. Эти слова есть в хидерах на STM32 и на GD. Они одинаковые для обоих камней. Кому интересно FLASH_KEY1 = 0x45670123, а FLASH_KEY2 = 0xCDEF89AB.
FLASH->KEYR = FLASH_KEY1; FLASH->KEYR = FLASH_KEY2;
Разблокировали запись во флеш, записываем бит WSEN:
После чего выставляем задержку памяти:
И включаем снова блокировку флеша, на всякий случай.
По идее, можно включить блокировку флеша сразу же после *FMC_WSEN = (uint32_t)1; А для настроек во FLASH_ACR разблокировка не нужна. Но это не работает, должно пройти какое то время, видимо, чтобы бит успел записаться во флеш и только потом включать снова блокировку.
Правда тут тоже не вышло счастья :)))) Оказалось, что с задержкой в два такта GD32 медленней чем STM32 c задержкой в эти же два такта. Тестовый импульс у GD32 на полной скорости у нас был 23мкс, на двух тактах задержки памяти стал 54мкс, а на одном такте задержки 37мкс. В то время как STM32 на двух тактах давал 37мкс.
То есть в любом случае нам придется как то узнавать где мы находимся и исходя из этого подгонять тайминги.
Ковыряясь в даташите на GD32 я увидел, что следующим после FMC_WSEN идет регистр FMC_PID и в нем сидит какое-то число, уникальный номер кристалла (или его памяти). Но у STM32 этот же адрес возвращает какую-то фигню. Которая еще и меняется. Хотя эти адреса никак не документированы. Так что вариант так себе.
Посоветовался с коллегами, покурил даташиты и документацию на ARM ядро и нашел, что по адресу 0xE00FFFD0 и далее прячутся Peripheral ID регистры. Которые содержат циферки присущие только конкретному семейству и производителю. В частности там зашито номер ревизии чипа, JEP 106 код и еще всякая лабуда. Но, главное, что у STM32 и GD32 эти байты различаются, не меняются, всегда одни и те же от чипа к чипу, в отличии от индивидуального 96 битного ID чипа, который уникальный для каждого экземпляра.
Поэтому поглядел под отладчиком что там, да написал простенькую процедурку для опознания где мы:
Проверил в железе — работает. Вот и славно. Пляшем дальше! :)
А в сухом остатке, из нескольких дней ковыряния GD32, из того что проверил у нас без проблем, идентично, работает:
Хватаю дисплейный модуль от другого проекта, но с этим же камнем. На нем есть FSMC интерфейс. Я на нем управлял дисплеем. Работает на отлично. Добавляем к списку проверенной периферии FSMC.
Хватаю другой проект, на этой же плате. Но уже боевой дисплей от компрессорной установки. Заливаю… Все работает, но жууууутко мееееееедленнно. Я поначалу решил, что я тупо кварц залил флюсом и у меня HSE не поехал. Промыл, просушил. Включил… все жууууутко меееедленно осталось. Странно. К сожалению исходников этого проекта у меня нет, знаю только что он написан на SPL и возможно что-то где-то недоинициализировалось в режиме тактирования. Надыбаю исходники, перепишу и будет ясно в чем был затык. Но я уже четко вижу, что нормально работают каналы DMA. Все не проверял, но UART там сделан через DMA это я знаю точно.
В общем, по мере освоения периферии буду добавлять в этот пост подробности о том, что же у нас по совместимости.
Спасибо. Вы потрясающие! Всего за месяц мы собрали нужную сумму в 500000 на хоккейную коробку для детского дома Аистенок. Из которых 125000+ было от вас, читателей EasyElectronics. Были даже переводы на 25000+ и просто поток платежей на 251 рубль. Это невероятно круто. Сейчас идет заключение договора и подготовка к строительству!
А я встрял на три года, как минимум, ежемесячной пахоты над статьями :)))))))))))) Спасибо вам за такой мощный пинок.
Читайте также: