======Запускаем отладку многопроцессорной системы======
В данной статье мы рассмотрим как настроить среду CM-LYNX, чтобы выполнить отладку сразу нескольких процессоров 1967ВНxx. Связь отладчика с процессором осуществляется посредством JTAG интерфейса, поэтому чтобы в режиме отладки иметь доступ сразу к нескольким процессорам, необходимо объединить процессоры в JTAG цепочку. В нашем проекте мы будем использовать [[http://ic.milandr.ru/products/programmno_otladochnye_sredstva/otladochnye_komplekty/otladochnyy_komplekt_dlya_protsessora_tsifrovoy_obrabotki_signalov_1967vn028/|отладочный комплект для процессора цифровой обработки сигналов 1967ВН028]], на отладочной плате которого уже реализовано соединение двух процессоров 1967ВН028 в JTAG цепочку.
===== Особенности JTAG цепочки на отладочной плате для 1967ВН028 =====
Подключение процессоров 1967ВН028 к отладчику по интерфейсу JTAG может быть настроено с помощью перемычек XP3-XP5. В зависимости от установленного положения на XP3-XP5 могут быть использованы следующие режимы:
^Режим подключения отладчика к процессорам^Положение XP3^Положение XP4^Положение XP5^
|Подключён только процессор D5 |1-2|не установлена|1-2|
|Подключён только процессор D6 |2-3|не установлена|2-3|
|Подключены оба процессора: JTAG цепочка D6-D5 |2-3|установлена|1-2|
Рисунок, наглядно демонстрирующий различные режимы подключения отладчика к процессорам.
{{dsp:multicore:JTAG_Chain_1967VN028.png}}
Для использования многопроцессорной отладки нам необходимо объединить процессоры в JTAG цепочку, поэтому устанавливаем перемычки на XP3-XP5 для режима с подключением двух процессоров.
===== Настройка проекта =====
В качестве тестового примера для отладки мы будем использовать проект Hello World, описанный в статье [[https://startmilandr.ru/doku.php/prog:spec:proj_codemaster-lynx |Создаем проект в среде CM-LYNX]]. По статье выполняем все пункты по созданию проекта до настроек режима Debug, т.е. указываем новый workspace, создаём в нём проект для 1967ВН028 и добавляем файл main.c с кодом мигания светодиодами. Далее настройка режима Debug будет несколько отличаться от стандартной.
Текущая реализация отладки предусматривает запуск многопроцессорного режима с таким же интерфейсом, как и для однопроцессорного. Однако, т.к. процессоров мы используем сразу несколько, то стандартный файл конфигурации компоновщика (LDF файл) нам не подойдёт, и его необходимо изменить. Чтобы среда понимала наличие нескольких процессоров, в LDF файл, по умолчанию это Name_project.ldf, с помощью оператора PROCESSOR необходимо добавить описание второго процессора, а по сути, скопировать описание имеющегося процессора, но изменив название с P0 на P1.
Чтобы не загромождать LDF файл описаниями процессоров, причём в нашем случае это будет одно и тоже описание, вынесем описание в отдельный файл.
Алгоритм изменения LDF файла будет следующим:
1. Создаём файл с произвольным расширением, например, «two_proc.sec», для этого кликаем правой кнопкой мыши по названию проекта и в выпадающем меню выбираем New->File. В открывшемся окне вводим название файла и расширение.
{{dsp:multicore:sec.png}}
2. Из стандартного LDF (Name_project.ldf) перемещаем блок SECTIONS из описания PROCESSOR P0 в созданный файл «two_proc.sec».
Ниже приведён листинг фрагмента, который мы перемещаем:
SECTIONS
{
program
{
FILL(0xb3c00000) // Fill any gaps with NOPs.
INPUT_SECTION_ALIGN(4)
INPUT_SECTIONS( StartUp.doj(.program) )
INPUT_SECTIONS( $OBJECTS(.program*) )
// The next line adds 10 nops after the last piece of code in the
// code section. This is required on TS201 to prevent uninitialised
// memory getting into the pipeline.
. = . + 10;
} >M0Code
cdata
{
INPUT_SECTIONS( $OBJECTS(.cdata*) )
INPUT_SECTIONS( $OBJECTS(.strings*) )
ldf_ctor_start = .;
INPUT_SECTIONS( $OBJECTS(.ctor0) )
INPUT_SECTIONS( $OBJECTS(.ctor1) )
INPUT_SECTIONS( $OBJECTS(.ctor2) )
INPUT_SECTIONS( $OBJECTS(.ctor3) )
INPUT_SECTIONS( $OBJECTS(.ctor4) )
INPUT_SECTIONS( $OBJECTS(.ctor5) )
ldf_ctor_end = .;
} >M0Code
bss ZERO_INIT
{
bss_start = .;
INPUT_SECTIONS( $OBJECTS(.bss*) )
bss_end = .;
} >M2DataA
data
{
INPUT_SECTIONS( $OBJECTS(.data*) )
} >M4DataA
// Allocate stacks for the application. Note that stacks
// grow downward, and must be quad-word aligned. This means
// that the location just after the highest word of the stack
// is quad-word aligned (evenly divisible by 4). There are two
// labels for each stack: "*_base" is the location just ABOVE
// the top of the stack, and "*_limit" is the lowest word that
// is part of the stack. Each stack occupies all of its own
// memory block.
jstackseg
{
ldf_jstack_limit = .;
ldf_jstack_base = . + MEMORY_SIZEOF(M6Stack);
} >M6Stack
kstackseg
{
ldf_kstack_limit = .;
ldf_kstack_base = . + MEMORY_SIZEOF(M8Stack);
} >M8Stack
// The default heap occupies its own memory block
defheapseg
{
_ldf_defheap_base = .;
_ldf_defheap_size = MEMORY_SIZEOF(M10Heap);
} >M10Heap
}
3. Теперь в стандартном LDF файле вместо описания каждого процессора просто подключим созданный ранее файл: #include «two_proc.sec». Листинг получившегося LDF файла представлен ниже:
#if defined(__1967VN028R2__)
#define INT_MEM_BANK_SIZE 0x20000 // Internal memory blocks are 0x20000 (128k)
#elif defined(__1967VN044__)
#define INT_MEM_BANK_SIZE 0x10000 // Internal memory blocks are 0x10000 (64k)
#else
#define INT_MEM_BANK_SIZE 0x10000 // Internal memory blocks are 0x10000 (64k)
#endif
ARCHITECTURE(ADSP-TS201)
$OBJECTS = $COMMAND_LINE_OBJECTS;
MEMORY
{
M0Code { TYPE(RAM) START(0x00000000) END(0x00000000 + (INT_MEM_BANK_SIZE - 1)) WIDTH(32) }
M2DataA { TYPE(RAM) START(0x00040000) END(0x00040000 + (INT_MEM_BANK_SIZE - 1)) WIDTH(32) }
M4DataA { TYPE(RAM) START(0x00080000) END(0x00080000 + (INT_MEM_BANK_SIZE - 1)) WIDTH(32) }
M6Stack { TYPE(RAM) START(0x000C0000) END(0x000C0000 + (INT_MEM_BANK_SIZE - 1)) WIDTH(32) }
M8Stack { TYPE(RAM) START(0x00100000) END(0x00100000 + (INT_MEM_BANK_SIZE - 1)) WIDTH(32) }
M10Heap { TYPE(RAM) START(0x00140000) END(0x00140000 + (INT_MEM_BANK_SIZE - 1)) WIDTH(32) }
MS0 { TYPE(RAM) START(0x30000000) END(0x37FFFFFF) WIDTH(32) }
MS1 { TYPE(RAM) START(0x38000000) END(0x3FFFFFFF) WIDTH(32) }
MSSD0 { TYPE(RAM) START(0x40000000) END(0x43FFFFFF) WIDTH(32) }
MSSD1 { TYPE(RAM) START(0x50000000) END(0x53FFFFFF) WIDTH(32) }
MSSD2 { TYPE(RAM) START(0x60000000) END(0x63FFFFFF) WIDTH(32) }
MSSD3 { TYPE(RAM) START(0x70000000) END(0x73FFFFFF) WIDTH(32) }
// Memory blocks need to be less than 2 Gig.
HOST { TYPE(RAM) START(0x80000000) END(0x8FFFFFFF) WIDTH(32) }
HOST1 { TYPE(RAM) START(0x90000000) END(0xAFFFFFFF) WIDTH(32) }
HOST2 { TYPE(RAM) START(0xB0000000) END(0xCFFFFFFF) WIDTH(32) }
HOST3 { TYPE(RAM) START(0xD0000000) END(0xEFFFFFFF) WIDTH(32) }
HOST4 { TYPE(RAM) START(0xF0000000) END(0xFFFFFFFF) WIDTH(32) }
}
PROCESSOR P0
{
OUTPUT( p0_$COMMAND_LINE_OUTPUT_FILE )
#include "two_proc.sec"
}
PROCESSOR P1
{
OUTPUT( p1_$COMMAND_LINE_OUTPUT_FILE )
#include "two_proc.sec"
}
Обратите внимание на строки:
OUTPUT( p0_$COMMAND_LINE_OUTPUT_FILE )
...
OUTPUT( p1_$COMMAND_LINE_OUTPUT_FILE )
Их мы тоже немного модифицировали, чтобы в результате сборки программы для каждого процессора создавался свой уникальный объектный файл dxe.
Собираем проект для конфигурации Debug и видим, что в отладочной консоли выводится сообщение о создании двух dxe файлов, каждый из которых соответствует отдельному процессору.
{{dsp:multicore:console.jpg}}
Теперь создаём отладочную конфигурацию. Для этого нажимаем на стрелку у значка жука и переходим в Debug configurations.
{{dsp:multicore:debug1.png}}
Так как у нас выбран тулчейн LLVM, то в открывшемся окне слева выбираем тип Milandr Application (LLVM) и выбираем иконку "New". Для тулчейн Milandr необходимо выбрать Milandr Application, дальнейший процесс создания отладочной конфигурации будет таким же, как и для LLVM.
{{dsp:multicore:debug2.png}}
Создастся конфигурация {Name_project} Debug. Теперь во вкладке main, в поле C/C++ Application необходимо указать путь к файлу с расширением .dxe. Файла dxe у нас два, но выбрать нужно обязательно первый полученный файл (по первому оператору PROCESSOR). Сделать это можно, кликнув на кнопку «Search Project…» и выбрав в открывшемся окне файл с процессором 0.
{{dsp:multicore:debug3.png}}
Теперь нажимаем на кнопку «Debug», после чего среда автоматически загрузит во все процессоры копию программы в соответствии с отладочной информацией о многопроцессорной конфигурации, хранящейся в "dxe"-файле, и запустится режим отладки.
===== Режим Debug =====
Теперь после запуска режима Debug в отладочной сессии будет отображаться два потока, по одному потоку на каждый процессор.
{{dsp:multicore:debug4.png}}
Выбрав соответствующий поток, можно по отдельности запускать выполнение программы на разных процессорах. Чтобы запустить выполнение программы одновременно на двух процессорах, воспользуемся функцией «Multicore Commands Mode».
{{dsp:multicore:multicore.png}}
Когда данная функция активирована, отладочные команды (Resume, Suspend, Terminate, Step Into, Step Over, Step Return) выполняются одновременно для всех активных процессоров.
{{dsp:multicore:plata.jpg}}
----
Старая версия статьи для CM-LYNX 1.05.04 доступна здесь: [[https://startmilandr.ru/doku.php/prog:spec:interprocessor_exchange|Тестирование совместной работы двух процессоров 1967ВН028]].