Дек 10

ARM Without Magic. Урок 1. Самое начало.

Небольшое предисловие.
Этот урок, как и последующие, написан прежде всего для новичков в прошивко-строении и не совсем новичков программировании. Для людей, которые хотят разобраться, как все устроено и почему работает именно так. После вдумчивого прочтения этого курса не должно остаться никаких вопросов, о том, что делает та или иная строка в любом файле, какие команды для сборки и отладки прошивки вызываются, для чего они нужны и как работают. Я постараюсь избавиться от ассемблерных вставок (в паре мест они будут, но не более), все что нужно знать – это язык программирования C на каком-то начальном уровне, сложные места постараюсь разъяснять. Ну и конечно для чтения документации потребуется хоть немного знать английский язык, к документации мы будем обращаться часто.
Я не буду особо заострять внимание на работу с блоками периферии, во-первых, потому что они все время разные, а во-вторых, по этой теме написаны тысячи статей и отснято тысячи бестолковых видеоуроков, что я вряд ли смогу сказать что-то новое и полезное. Я склоняюсь к тому, что лучший учебник по управлению светодиодом и отправке несколько байт через USART — это документация на соответствующий процессор. Она правильная и полная. В общем этакий экскурс в BareMetal для прикладных программистов. И основное отличие прошивки МК от прикладной программы в том, что все приходится делать самому. Инициализировать переменные, раскидывать секции по правильным адресам. Обычно это скрыто под капотом всяких IDE и их шаблонов, да так хорошо спрятано, что многие относятся к этим процессам как к магии: поставил волшебных галочек или произнес страшное заклятие — и прошивка собралась. Само по себе это не плохо, я тоже уже не первый год пользуюсь шаблоном для создания новых проектов, но мне нравится знать как оно работает и где подкрутить, чтобы получить требуемый результат.

Мы не будем привязываться к какой-то особенной среде разработки, мы не будем пользоваться генераторами проектов типа STM32 CubeMX, мы на первом этапе вообще прошивку руками соберем, без всяких систем сборок, и отлаживать будем тоже руками.

Ориентироваться я буду на процессоры STM32, так как с ними мне приходится работать чуть ли не каждый день, они дешевые и доступные. Из приборов для начала потребуется отладочная плата на процессоре STM32F103C8 (например Blue-pill) и отладчик ST-Link v2. Все это доступно для покупки на AliExpress за сущие копейки. Но все что будет написано довольно легко адаптировать к любому ARM Cortex-M процессору. Собственно цель курса в том, чтобы, используя полученные знания можно было без труда использовать любой доступный процессор.

Continue reading

Май 09

STM32 CCM

Есть у некоторых взрослых STM-ок такая дурная штука, как CCM (core coupled memory). Это отдельный регион памяти, не шуточного размера в 64K (для F4xx), который по-умолчанию вообще не используется. Выделена эта память в отдельный регион, потому что имеет подключение только к D-BUS ядра, что накладывает кое-какие ограничения. Главное — это невозможно использовать вместе с DMA и DMA2D и выполнять код (примечание: это для F40x, но вообще неплохо заглянуть в PDF, раздел «Архитектура системы»), а в остальном — память как память.
Есть несколько способов хоть как-то его начать использовать, самый простой способ — это положить туда стек.
Для этого нужно модифицировать всего одну строку скрипта линковки, ту что задает адрес _estack и положить в этот символ адрес конца CCM (0x10010000):

_estack = 0x10010000;    /* end of CCMRAM */

При этом весь стек переедет в CCM и как следствие все локальные переменные, аргументы функции итд.
Второй не менее простой, но довольно ручной способ — это указание секции при описании переменной:

__attribute__((section(".ccmram"))) int ccmvar;

однако, стоит при этом помнить, что без модификации startup-скрипта при инициализации там будет мусор, заполним нулями, добавив где-нибудь после FillZeroBSS

/* Zero fill the CCM segment. */
ldr  r2, =_sccmram
FillZeroCCM:
  movs  r3, #0
  str  r3, [r2], #4
 
LoopFillZeroCCM:
  ldr  r3, = _eccmram
  cmp  r2, r3
  bcc  FillZeroCCM

а заодно уберем в скрипте линковки из описания секции .ccmram запись инициализации во FLASH:

  .ccmram :
  {
    . = ALIGN(4);
    _sccmram = .;       /* create a global symbol at ccmram start */
    *(.ccmram)
    *(.ccmram*)
 
    . = ALIGN(4);
    _eccmram = .;       /* create a global symbol at ccmram end */
   } >CCMRAM

теперь все переменные с attribute((section(«.ccmram»))) будут стартовать с нулевыми значениями

Дек 26

STM32: Шифруем прошивку.

Не сильно хорошая, но все же защита от бездумного копирования устройства. А может быть и еще что-то. В общем, идея такая: зашифровать некоторые критические функции, без которых устройство работать не будет, хитрожопые алгоритмы или математика какая-нибудь. Причем, желательно не потерять удобную сборку и отладку, и использовать желательно без всяких указателей. Я использую arm-none-eabi-gcc в качестве тулчейна и CMake как систему сборки. Поэтому все нижесказанное относится именно к этой связки и для других компиляторов-сборщиков придется немного перепилить.
Continue reading

Авг 31

STM32 и malloc во внешней памяти FMC / SDRAM

После того, как FMC/FSMC запустился и работает, внешняя память отражается по соответствующим адресам. Эту память можно использовать по захардкоденным адресам

char * ptr = (char*)0xC0000000;

но каждый раз вычислять адреса не комильфо. Тем более, для этого как раз есть специальная штука — heap и malloc/free.
Нужно только рассказать malloc где у нас эта память и сколько её. Самый простой способ — исправить правила линковки: Суть такова. _sbrk использует память начиная c адреса переданного линковщиком как end, стоит положить его адрес SDRAM, как malloc начинает раздавать адреса из неё.
Continue reading

Апр 27

AVR CMake

Clion & AVRВот уже несколько лет пользуюсь CMake-ом, чтобы собирать проекты под AVR. Сподвиг на этом конечно же вышедший осенью 2014 Jetbrains CLion, который как оказалось идеально подходит для написания кода под Atmel AVR. Короче, рекомендую.
Возможно, для корректной работы нужно будет установить переменную среды AVR_FIND_ROOT_PATH — на папку с avr (содержащую lib и include), а так же папка с avr-gcc, avr-g++, avr-objcopy, avr-size должны находиться в PATH. Ну или доработать напильником generic-gcc-avr.cmake

В общем, шаблон тут: https://github.com/bevice/avr_cmake_template
Continue reading

Окт 15

Аппаратный I2C (TWI) в микроконтроллерах AVR

При наличии на борту AVR аппаратной реализации I2C почему-то многие предпочитают программные реализации. Хотя, на мой скромный взгляд — использование железного варианта проще, стабильнее и удобнее.

Применение встроенного интерфейса и подразумевает работу на прерываниях, но сегодня мы обойдемся без оных. Для понимания работы контроллера это несколько проще, а переложить код на использование прерываний не составит труда.

Описывать шину I2C не имеет смысла, исчерпывающие описание можно найти на википедии, Казусе и конечно у DI HALT’a. Последняя ссылка заслуживает особого внимания, там основное внимание уделяется именно AVR, но в качестве примеров используется RTOS, что несколько абстрагирует от последовательности работы. Именно для того, чтобы дополнить статью DI HALT’a (а так же, чтобы не забыть что и как самому) и была написана эта небольшая заметка.
Continue reading