Хочу показать, как можно писать код и собирать hex-файлы для отечественных микроконтроллеров компании «Миландр» в удобной среде Qt Creator. Обычно для этих средств используются другие среды разработки, но с появлением системы QBS все несколько поменялось.

Для того, чтобы все заработало, достаточно скачать среду и компилятор. Компилятор — GCC; среда, как сказано в заголовке — Qt Creator.

Скачивание необходимого


— Qt Creator можно скачать с официального сайта Qt и без проблем установить как в Windows, так и в Linux. Ставить можно куда угодно;
— Затем скачиваем GCC for ARM. Я брал ссылки отсюда. Распаковываем в удобное для вас место, желательно недалеко от корня диска;
— Скачиваем библиотеки CMSIS и SPL с сайта Миландра. Распаковываем куда угодно. Или можно взять шаблон, который я выложил в конце статьи здесь, и пользоваться библиотеками оттуда. Но когда вам захочется ковыряться дальше, то придется добавлять еще библиотечные файлы. ИХ можно найти на официальном сайте.

Все, больше нам ничего не понадобится.

Создание шаблона


Итак, после того, как вы установили и распаковали все необходимое, можно приступить к созданию проекта и написанию кода. Написанное здесь справедливо как для Windows, так и для Linux (сборка проекта тестировалась на Ubuntu).

Начнем:

— Открываем Qt Creator и создаем новый проект с системой сборки QBS. Назовем его, к примеру, «Habr».





Получаем простой Hello World. После чего из файла main.c удаляем все и оставляем пустой файл. Мы вернемся к нему чуть позднее.

— Открываем файл Habr.qbs и аналогично вычищаем оттуда все, оставляя пустоту. После чего пишем туда следующий код:

import qbs
Project {
    name: "simple"
    Product {
        name: "micro"
        type: "hex"
        Group {
            name: "sources"
            files: ["main.c",
                    "system_MDR32F9Qx.c",
                    "startup_Cortex_M3.c"]
            fileTags: ['c']
        }
        Rule {
            inputs: ["c"]
            Artifact {
                fileTags: ['obj']
                filePath: input.fileName + '.o'
            }
            prepare: {
                var args = [];
                args.push("-mcpu=cortex-m3")
                args.push("-mthumb")
                args.push("-g")
                args.push("-ffunction-sections")
                args.push("-O0")
                args.push("-Wall")
                args.push("-Wunused")
                args.push("-DM3")
                args.push('-c');
                args.push(input.filePath);
                args.push('-o');
                args.push(output.filePath);
                var compilerPath = "C:/4.9_2014q4/bin/arm-none-eabi-gcc.exe"
                var cmd = new Command(compilerPath, args);
                cmd.description = 'compiling ' + input.fileName;
                cmd.highlight = 'compiler';
                cmd.silent = false;
                return cmd;
            }
        }
        Rule{
            multiplex: true
            inputs: ['obj']
            Artifact{
                fileTags:['elf']
                filePath: project.name + '.elf'
            }
            prepare:{
                var args = []
                args.push("-mcpu=cortex-m3")
                args.push("-mthumb")
                args.push("-g")
                args.push("-nostartfiles")
                args.push("-O0")
                args.push("-Wl,--gc-sections")                
                for(i in inputs['obj'])
                    args.push(inputs["obj"][i].filePath);
                args.push("-TC:/Source/Qt/ARM_Test_QBS/arm-gcc-link.ld")
                args.push('-o');
                args.push(output.filePath);
                var compilerPath = "C:/4.9_2014q4/bin/arm-none-eabi-gcc.exe"
                var cmd = new Command(compilerPath,args);
                cmd.description = "linking"+project.name
                return cmd;
            }
        }
        Rule{
            inputs: ['elf']
            Artifact{
                fileTags:['hex']
                filePath: project.name + '.hex'
            }
            prepare:{
                var args = []
                args.push("-O")
                args.push("ihex")
                args.push(input.filePath)
                args.push(output.filePath)
                var hexcreator = "C:/4.9_2014q4/bin/arm-none-eabi-objcopy.exe"
                var cmd = new Command(hexcreator,args);
                cmd.description = 'create_hex'+project.name
                return cmd;
            }
        }
    }
}


В этом коде поочередно вызываются компилятор, линковщик и создатель хекс файла со своими параметрами.

Обязательно! Пропишите в переменную CompilerPath путь до ваших компилятора, линковщика и gcc-objcopy.

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



В файл main.c, который стоит и ждет, пока мы туда что-нибудь напишем, вставляем следующее:

#include "MDR32F9x.h"  //Подключаем заголовочный файл с регистрами
#include "system_MDR32F9Qx.h" //Подключаем файл с инициализацией периферии
long check = 0;

void InitPortLED(void)//Инициализация портов микроконтроллера
{
    MDR_PORTD->FUNC &= ~((0x3FF << (10 << 1))); 
    MDR_PORTD->ANALOG |= (1<<14|1<<13|1<<12|1<<11|1<<10); 
    MDR_PORTD->PWR |= (0x155 << (10 << 1));      
    MDR_PORTD->RXTX &= ~(1<<14|1<<13|1<<12|1<<11|1<<10);
    MDR_PORTD->OE |= (1<<14|1<<13|1<<12|1<<11|1<<10);
}

int main()
{
    SystemInit();//Системная функция, которая инициализирует тактовый генератор
    InitPortLED();
    while(1)//Мигалка светодиодами
    {
        check++;
        if(check == 1000)
            MDR_PORTD->RXTX |= 1<<14|1<<10|1<<12;//vkl diod
        if(check == 4000)
        {
            check = 0;
            MDR_PORTD->RXTX &= (0<<11|0<<13);
        }
    }
}

Выбор портов обусловлен работой с отладочной платой Миландра.

После запускаем компиляцию и убеждаемся, что все скомпилировалось и мы стали обладателями hex файла.



Все прекрасно, теперь этот файл можно прошивать в контроллер и наслаждаться мигающими диодами.

Как и говорил, выкладываю шаблон, с исходниками.

На этом все, спасибо за внимание!

UPD: Выложил шаблон на GitHub

Комментарии (4)


  1. ncix
    01.06.2015 19:05

    Задержка пустыми итерациями цикла это конечно жесть, да и глобальная переменная тут ни к чему.
    Но за QBS Спасибо! Полезная информация.


    1. Nerock Автор
      01.06.2015 19:12
      +2

      Да, я понимаю, что это беда, но я больше разбирался с Qbs, чем с рабочим кодом :)


  1. Miharus
    01.06.2015 20:39

    Кто нибудь пробовал миландровские контроллеры в режиме отладки?


    1. Nerock Автор
      01.06.2015 20:48

      Он должен в нем работать, но у меня, с помощью JLink-а, не получалось его завести. Завтра попробую поковырять, если получится, отпишусь