======Запускаем отладку многопроцессорной системы====== В данной статье мы рассмотрим как настроить среду 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]].