Инструменты пользователя

Инструменты сайта


prog:spec:proj_1901

Создаем проект для 1901ВЦ1Т

Миландр представляет хорошую поддержку в SPL для микропроцессоров 1986ВЕ1Т и семейства 1986ВЕ9х. Но помимо этого производитель выпускает достаточно много других интересных микропроцессоров, поддержка которых пока реализована слабо. В этой статье мы рассмотрим, как создать проект для одного из таких МК - 1901ВЦ1Т.

Микропроцессор 1901ВЦ1Т состоит из двух ядер - RISC и DSP. Первое RISC ядро аналогично ядру семейства 1986ВЕ9х и разработано на базе ARM Cortex M3. Поэтому все, что мы напишем для 1986ВЕ9х, должно более-менее прижиться и в 1901ВЦ1Т. Работать с этим ядром мы будет в том же Keil.

DSP ядро является аналогом TMS320C546 и для его программирования необходима среда "Code Composer Studio" версий 2 или 3.3. Собранный с помощью данной среды hex файл можно загрузить через RISC ядро в DSP. Также, на сколько я знаю, среда разработки "CodeMaster-ARM" позволяет производить компиляцию и отладку для обоих ядер сразу. Это наверное очень удобно, но в моем случае пока недоступно. Поэтому мы пойдем по первому пути и попробуем когда-нибудь реализовать вариант с загрузкой DSP через RISC ядро. Сейчас же создадим первый проект, который будет собираться и загружаться в 1901ВЦ1Т.

Дополнение: Pack с поддержкой 1901ВЦ1Т теперь можно взять из этого проекта - ссылка. С ним проекты для 1901ВЦ1Т собираются стандартным образом, как и для прочих микроконтроллеров. Поэтому статья становится не вполне актуальна, но показывает способ собрать проект под микроконтроллер, для которого нет поддержки.

Создаем проект

(Для сборки проекта необходимо установить Legacy support for ARM Cortex-M devices. Если этого не сделать, то файлы поддержки ядра, такие как core_cm3.h, core_cmFunc.h, … необходимо будет подключить вручную из пака для микроконтроллеров 1986ВЕ9х.)

Итак, нажимаем создать новый проект, выбираем папку и название проекта. Назовем его "HelloWorld_1901". После этого нам открывается окно с выбором микроконтроллера. Можно раскрыть дерево "Milandr" и убедиться, что наш процессор не поддерживается в PACK от производителя. Надеюсь вскоре это исправят.

Раскрываем дерево "ARM", выбираем "ARM Cortex M3" и там присутствует всего один шаблон "ARMCM3" - выбираем его, жмем "ОК".

Далее открывается окно "Manage Run-Time Environment", ничего выбирать тут не нужно, просто жмем "ОК".

Создался пустой проект, папку для кода "Source Group 1" мы лаконично переименуем в "user". Добавим файл "main.c":

  • Правой клавишей на "user"
  • "Add New Item to Group user …"
  • Выбираем тип файла и вбиваем имя main
  • Add.

В группе проекта появился файл "main.c". Давайте сразу реализуем в нем пустую функцию main.

Запускаем компиляцию и видим по ошибкам внизу, что нашему проекту много чего не хватает, и в первую очередь, таблицы векторов прерываний. Таблица векторов прерываний обычно находится в файле с расширением "*.s", ищем такой файл для нашего процессора в папке PACK от Миландр и находим его по такому пути:

C:\Keil_v5\ARM\PACK\Keil\MDR1986BExx\1.4\Libraries\CMSIS\CM3\DeviceSupport\MDR1901VC1T\
  inc\
      MDR1901VC1T.h    
  startup\arm\
      startup_MDR1901VC1T.s
      system_MDR1901VC1T.c
      system_MDR1901VC1T.h      

Здесь я сразу представил дерево путей и все файлы, которые нам потребуются для компиляции проекта. Эти файлы защищены от записи, а нам потребуется внести некоторые изменения. Кроме этого, эти файлы потенциально могут быть обновлены при апдейте Pack. Поэтому скопируем их в директорию нашего проекта, для этого заведем в ней отдельную папку - "lib". Затем снимем защиту от записи:

  • Выделить все файлы
  • Правая клавиша мыши - свойства
  • Снять галочку Read Only.

Подключаем файл с таблицей векторов прерываний - "startup_MDR1901VC1T.s":

  • В дереве проектов жмем правой клавишей на "user"
  • Кликаем на "Add Existing Files to Group user"
  • Выбираем папку lib
  • Меняем в диалоговом окне тип отображаемых файлов на "All files"
  • Выбираем нужный файл
  • Жмем Add и закрываем диалог Close.

Пытаемся скомпилировать проект, и возникает следующая ошибка:

По сообщению компилятора понятно, что объектному файлу скомпилированному из файла "startup_MDR1901VC1T.s" требуется внешняя (из другого объектного файла) функция SystemInit. Если поискать, то такая функция реализована в файле "system_MDR1901VC1T.c". Подключаем его к проекту аналогично тому, как подключали файл "startup_MDR1901VC1T.s". Пытаемся скомпилировать:

Опять ошибка, требуется подключить еще один файл - "MDR32F9Qx_config.h", он располагается в C:\Keil_v5\ARM\PACK\Keil\MDR1986BExx\1.4\Config. Скопируем его так-же к себе в проект к остальным библиотечным файлам, в папку "lib" и подключим.

Теперь при попытке сборки, возникает аналогичная ошибка, но с указанием, что требуется файл "MDR32F9Qx_lib.h". Находим его в C:\Keil_v5\ARM\PACK\Keil\MDR1986BExx\1.4\Libraries\MDR32F9Qx_StdPeriph_Driver\inc и подключаем. Запускаем сборку и видим, что проект успешно собрался.

Настройки проекта

Проект компилируется, теперь необходимо указать специфику микропроцессора в опциях проекта. В микропроцессоре 1901ВЦ1Т используется RISC ядро аналогичное 1986ВЕ92У, поэтому все настройки необходимо выставить как в статье - "Настройки проекта для 1986ВЕ9х", за исключением вкладки "Device".

Пишем "Hello World"

Если сравнить спецификации на 1901ВЦ1Т и 1986ВЕ9х, то видно, что порты ввода вывода располагаются в одинаковых адресах и с одинаковыми смещениями (раздел "Описание регистров портов ввода-вывода"). Также наблюдаем полную аналогию в тактировании для CPU_CLK (раздел "Сигналы тактовой частоты" - схема тактирования и описание регистров). По этой причине наш пример "Hello World - светодиод" не требует никаких дополнительных доработок. Тактирование и переключение вывода порта будут работать и в данном микроконтроллере 1901ВЦ1Т. Копируем наш код из примера в текущий файл "main.c"

Для работы примера требуется два файла - MDR32F9Qx_port.c и MDR32F9Qx_rst_clk.c. Они должны быть скомпилированы средой Keil, поэтому подключаем их к нашему проекту. Файлы эти находятся по следующему пути:
C:\Keil_v5\ARM\PACK\Keil\MDR1986BExx\1.4\Libraries\MDR32F9Qx_StdPeriph_Driver\src

Окно проекта у нас теперь выглядит так, здесь подключены все необходимые файлы:

Для того чтобы компиляция прошла успешно, необходимо указать среде, где следует искать заголовочные файлы.

  1. В опциях проекта идем в закладку С/С++.
  2. Находим внизу строку "Include Paths", нажимаем кнопку с многоточием.
  3. В открывшемся окне создаем новую строку пути.
  4. В этой строке нажимаем кнопку с многоточием и в открывшемся диалоге выбираем папку, где Keil будет искать требуемые для компиляции файлы.
  5. Создаем две строки с путями согласно скриншоту.

На данном этапе проект компилируется с многочисленными ошибками. Для их устранения требуется зайти в файл MDR32F9Qx_config.h и сделать макроопределение под наш микропроцессор.

#ifndef __MDR32F9Qx_CONFIG_H
#define __MDR32F9Qx_CONFIG_H

#define  USE_MDR1901VC1T  /* - Это макроопределение указывает используемый МК*/
....
....
#endif /* __MDR32F9Qx_CONFIG_H */

Теперь проект снова успешно собирается. Осталось проверить, какой вывод и от какого порта разведен на один из светодиодов на демоплате. На плате, рядом с микросхемой памяти DD1, виден целый ряд перемычек к каждому светодиоду. Если присмотреться, то на плате указана маркировка, какой порт используется на каждом светодиоде. Давайте выберем крайний светодиод, он подписан на плате РВ11. Модифицируем код "Hello World - светодиод" для мигания этим светодиодом.

Для того чтобы оставить рабочим старый вариант, вынесем все определения, зависящие от конкретного МК, в макроопределения. Итоговый код получился таким:

#include <MDR32F9Qx_port.h>
#include <MDR32F9Qx_rst_clk.h>

//  Прототип функции задержки, реализованной ниже
void Delay(int waitTicks);

#define _test1901      // Выбираем секцию 1901ВЦ1Т для компиляции

#ifdef _testBE9x       //  Определения для 1986ВЕ9х - неактивна при выбранном ключе _test1901
  #define PORT_LedClock 	RST_CLK_PCLK_PORTC
  #define PORT_Led 		MDR_PORTC
  #define PORT_LedPin 		PORT_Pin_0
  #define DELAY_Ticks 		1000000
#endif

#ifdef _test1901       //  Определения для 1901ВЦ1Т - активна
  #define PORT_LedClock 	RST_CLK_PCLK_PORTB
  #define PORT_Led 		MDR_PORTB
  #define PORT_LedPin 		PORT_Pin_11
  #define DELAY_Ticks 		1000000
#endif

//  Точка входа, отсюда начинается исполнение программы
int main()
{
  // Заводим структуру конфигурации вывода(-ов) порта GPIO
  PORT_InitTypeDef GPIOInitStruct;
	
  //  Включаем тактирование порта C
  RST_CLK_PCLKcmd (PORT_LedClock, ENABLE);
	
  //  Инициализируем структуру конфигурации вывода(-ов) порта значениями по умолчанию
  PORT_StructInit(&GPIOInitStruct);
  
  //  Изменяем значения по умолчанию на необходимые нам настройки
  GPIOInitStruct.PORT_Pin        = PORT_LedPin;
  GPIOInitStruct.PORT_OE         = PORT_OE_OUT;
  GPIOInitStruct.PORT_SPEED      = PORT_SPEED_SLOW;
  GPIOInitStruct.PORT_MODE       = PORT_MODE_DIGITAL;
  
  //  Применяем заполненную нами структуру для PORTC.
  PORT_Init(PORT_Led, &GPIOInitStruct);

  //  Запускаем бесконечный цикл обработки - Основной цикл	
  while (1)
  {
    // Считываем состояние вода PC0
    // Если на выводе логический "0", то выставляем вывод в логическую "1"
    if (PORT_ReadInputDataBit (PORT_Led, PORT_LedPin) == 0)
    {	
	PORT_SetBits(PORT_Led, PORT_LedPin);	// LED
    }	
    
    //  Задержка
    Delay(DELAY_Ticks);

    // Считываем состояние вода PC0
    // Если на выводе = "1", то выставляем "0"
    if (PORT_ReadInputDataBit (PORT_Led, PORT_LedPin) == 1)
    {
	PORT_ResetBits(PORT_Led, PORT_LedPin);
    };
    
    //  Задержка    
    Delay(DELAY_Ticks);
  }      
}

//  Простейшая функция задержки, позднее мы заменим ее на реализацию через таймер
void Delay(int waitTicks)
{
  int i;
  for (i = 0; i < waitTicks; i++)
  {
    __NOP();
  }	
}

Далее все просто - компилируем, прошиваем программу и наблюдаем мигание на выбранном нами светодиоде. Значит наш проект собрался и запустился успешно. Подобным образом можно реализовывать управление прочей периферией RISC ядра 1901ВЦ1Т, схожей по реализации с 1986ВЕ9х.

prog/spec/proj_1901.txt · Последнее изменение: 2022/04/03 23:09 (внешнее изменение)