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

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


prog:spec:elpower_dualcore

Различия

Здесь показаны различия между двумя версиями данной страницы.

Ссылка на это сравнение

Предыдущая версия справа и слева Предыдущая версия
Следующая версия
Предыдущая версия
prog:spec:elpower_dualcore [2019/06/03 14:51]
vova [Особенности двухъядерной отладки]
prog:spec:elpower_dualcore [2019/08/16 14:48] (текущий)
vova [Запускаем двухъядерную отладку]
Строка 1: Строка 1:
-======Запускаем микроконтроллер для управления двигателями "​Электросила"​ в режиме DUALCORE====== +======Запускаем микроконтроллер для управления двигателями"​Электросила"​в режиме DUALCORE ​| IDE Keil====== 
-Микроконтроллер для управления двигателями выполнен на базе двух ядер ARM Cortex-M4F. По сбросу два ядра МК работают в режиме LOCKSTEP, при этом первое ядро выполняет инструкции программы,​ а второе ядро только дублирует все операции первого ядра с задержкой в два такта. Данный режим применяется для обнаружения сбоев в работе МК путём сравнения поведения первого и второго ядра.\\+Микроконтроллер для управления двигателями выполнен на базе двух ядер ARM Cortex-M4F. По сбросу два ядра МК работают в режиме LOCKSTEP. При этом первое ядро выполняет инструкции программы,​ а второе ядро только дублирует все операции первого ядра с задержкой в два такта. Данный режим применяется для обнаружения сбоев в работе МК путём сравнения поведения первого и второго ядра.\\
 При необходимости режим LOCKSTEP может быть отключен,​ и тогда два ядра становятся независимыми (режим DUALCORE) и могут исполнять различные программы,​ что увеличивает общую производительность МК. При необходимости режим LOCKSTEP может быть отключен,​ и тогда два ядра становятся независимыми (режим DUALCORE) и могут исполнять различные программы,​ что увеличивает общую производительность МК.
  
-В данной статье мы рассмотрим ​для среды Keil пример перехода МК из режима LOCKSTEP в режим DUALCORE, а также разберём некоторые особенности двухъядерной отладки.+В данной статье мы рассмотрим пример перехода МК из режима LOCKSTEP в режим DUALCORE ​(для среды Keil), а также разберём некоторые особенности двухъядерной отладки.
 =====Проект для работы МК в двухъядерном режиме===== =====Проект для работы МК в двухъядерном режиме=====
  
-На примере проекта SMP (Symmetric Multi-Processing) мы разберём процесс запуска МК в режиме DUALCORE, а также посмотрим,​ как осуществляется отладка сразу двух ядер. Проект для Keil можно скачать по [[https://​drive.google.com/​uc?​authuser=0&​id=1uj7oTC9q8RNkGm5-RSkv8sXAj7BrWZj_&​export=download|этой ссылке]].+На примере проекта SMP (Symmetric Multi-Processing) мы разберём процесс запуска МК в режиме DUALCORE, а также посмотрим,​ как осуществляется отладка сразу двух ядер. Проект для Keil можно скачать по [[https://​drive.google.com/​uc?​authuser=0&​id=1OIh1bju2RZFqIoZ_UNxorCIPYEoGj9wx&​export=download|этой ссылке]].
  
 В статье я опирался на [[https://​www.milandr.ru/​press/​news/​4658/​|презентацию Миландра с выставки «ЭкспоЭлектроника»]] под номером 02, в которой приведены подробные настройки сред Keil и IAR для работы с МК в режиме DUALCORE. В статье я опирался на [[https://​www.milandr.ru/​press/​news/​4658/​|презентацию Миландра с выставки «ЭкспоЭлектроника»]] под номером 02, в которой приведены подробные настройки сред Keil и IAR для работы с МК в режиме DUALCORE.
Строка 30: Строка 30:
 {{ prog:​esila_cores:​lockstep.png?​600 }} {{ prog:​esila_cores:​lockstep.png?​600 }}
  
-После того, как мы запустим отладку,​ МК перейдёт в режим DUALCORE и два процессорных ядра начнут работать независимо. После этого у отладчика появится возможность подключиться ко второму ядру.+После того, как мы запустим отладку,​ МК перейдёт в режим DUALCOREи два процессорных ядра начнут работать независимо. После этого у отладчика появится возможность подключиться ко второму ядру.
  
 {{ prog:​esila_cores:​dualcore.png?​600 }} {{ prog:​esila_cores:​dualcore.png?​600 }}
  
-Но пока не будет запускать отладку,​ а разберём процесс перехода из режим LOCKSTEP в режим DUALCORE.+Но пока не будем запускать отладку,​ а разберём процесс перехода из режима LOCKSTEP в режим DUALCORE.
  
 ====Процесс перехода из режим LOCKSTEP в режим DUALCORE==== ====Процесс перехода из режим LOCKSTEP в режим DUALCORE====
Строка 44: Строка 44:
 <​code>​ <​code>​
 Процедура выполняется при выключенных DMA, кэш и прерываниях. Процедура выполняется при выключенных DMA, кэш и прерываниях.
-1. Разблокировать запись в регистры батарейного домена записав ключ в регистр BKP_KEY +1. Разблокировать запись в регистры батарейного доменазаписав ключ в регистр BKP_KEY. 
-2. Установить бит LOCKSTEP_EN регистра REG_60_SYS +2. Установить бит LOCKSTEP_EN регистра REG_60_SYS. 
-3. Очистить конвейер инструкцией DSB+3. Очистить конвейер инструкцией DSB.
 4. В зависимости от выполнения условия CPUID==0 передать управление на разные 4. В зависимости от выполнения условия CPUID==0 передать управление на разные
-   ​участки кода, загрузить разные значения в указатели стека+   ​участки кода, загрузить разные значения в указатели стека.
 </​code>​ </​code>​
  
Строка 54: Строка 54:
 ** **
 <​code>​ <​code>​
-1. Разблокировать запись в регистры батарейного домена записав ключ в регистр BKP_KEY +1. Разблокировать запись в регистры батарейного доменазаписав ключ в регистр BKP_KEY. 
-2. Сбросить бит LOCKSTEP_EN регистра REG_60_SYS +2. Сбросить бит LOCKSTEP_EN регистра REG_60_SYS. 
-3. Очистить конвейер инструкцией DSB +3. Очистить конвейер инструкцией DSB. 
-4. Выполнить сброс процессора установив бит SYSRESETREQ регистра AIRCR+4. Выполнить сброс процессораустановив бит SYSRESETREQ регистра AIRCR.
 </​code>​ </​code>​
  
Строка 83: Строка 83:
 После исполнения данного кода произойдёт переход в режим DUALCORE, при этом ядро 0 и ядро 1 продолжат выполнять программу уже по отдельности. После исполнения данного кода произойдёт переход в режим DUALCORE, при этом ядро 0 и ядро 1 продолжат выполнять программу уже по отдельности.
  
-Чтобы два ядра могли совместно исполнять программу,​ нам необходимо указать для каждого из них отдельный стек и кучу. В проекте это сделано в файле startup.c, функция // _//​_//​user_setup_stackheap//,​ которая вызывается библиотекой C во время запуска программы,​ т.е. после перехода в //​_//​_//​main//​. Подробнее про это описано на [[http://​www.keil.com/​support/​man/​docs/​armlib/​armlib_chr1359122863069.htm|официальном сайте Keil]].+Чтобы два ядра могли совместно исполнять программу,​ нам необходимо указать для каждого из них отдельный стек и кучу. В проекте это сделано в файле startup.s, функция // _//​_//​user_setup_stackheap//,​ которая вызывается библиотекой C во время запуска программы,​ т.е. после перехода в //​_//​_//​main//​. Подробнее про это описано на [[http://​www.keil.com/​support/​man/​docs/​armlib/​armlib_chr1359122863069.htm|официальном сайте Keil]].
  
 <​code>​ <​code>​
Строка 105: Строка 105:
 </​code>​ </​code>​
  
-Здесь и далее "​SMP_REG"​ обозначает регистр идентификации ядра, который содержит один бит: ​0 - первое ядро, ​1 - второе. С помощью данного регистра можно легко передать управление на разные участки кода.+Здесь и далее "​SMP_REG"​ обозначает регистр идентификации ядра, который содержит один бит: ​при чтении данного регистра ​первое ядро ​получает значение 0а второе ​ядро - значение 1. С помощью данного регистра можно легко передать управление на разные участки кода.
  
-После разделения стека оба ядра продолжат по отдельности выполнять запуск программы и в конечном итоге перейдут в функцию main(). ​+После разделения стека оба ядра продолжат по отдельности выполнять запуск программы ив конечном итогеперейдут в функцию main(). ​
  
 =====Запускаем двухъядерную отладку===== =====Запускаем двухъядерную отладку=====
  
-В проекте SMP показан пример взаимодействия двух ядер с использованием мьютексов. При этом ядро 0 мигает синим светодиодом (PC18), а ядро 1 - красным (PC20). Ничего сложно в работе программы нет, поэтому перейдём сразу к отладке.+В проекте SMP показан пример взаимодействия двух ядер с использованием мьютексов. При этом ядро 0 мигает синим светодиодом (PC19), а ядро 1 - красным (PC21). Ничего сложного в работе программы нет, поэтому перейдём сразу к отладке. 
 + 
 +<note important>​В зависимости от номера версии платы могут отличаться выводы микроконтроллера,​ отвечающие за диоды указанных цветов. Например,​ для платы V2, это были выводы PC18 и PC20 соответственно. В таком случае,​ необходимо внести изменения в программный код. Пример работает без изменений для V3. </​note>​
  
 Программу будем запускать из памяти ОЗУ, поэтому в настройках Keil выбираем конфигурацию "//RAM ULINK2 @0//", которая запускает отладку 0-го ядра. Программу будем запускать из памяти ОЗУ, поэтому в настройках Keil выбираем конфигурацию "//RAM ULINK2 @0//", которая запускает отладку 0-го ядра.
Строка 119: Строка 121:
 За настройку запуска режима отладки отвечает файл инициализации "//​0x02000000.ini//",​ в котором выполняются две строки:​ За настройку запуска режима отладки отвечает файл инициализации "//​0x02000000.ini//",​ в котором выполняются две строки:​
 <​code>​ <​code>​
-load %L incremental // Загрузить программу в память ОЗУ 
 Setup(0x02000000); ​ // Установить значения SP (указатель стека),​ PC (счётчик команд),​ VT (начало таблицы векторов) Setup(0x02000000); ​ // Установить значения SP (указатель стека),​ PC (счётчик команд),​ VT (начало таблицы векторов)
 +g ,main             // Запустить выполнение программы с адреса,​ указанного в PC, и остановится в main
 </​code>​ </​code>​
  
-Запускаем режим отладки ​и автоматически останавливаемся в функции //main()//, так как в настройках проекта установлена опция "Run to main()"​. Переход в режим DUALCORE и установка различных стеков ​была ​произведена до входа в mian(), поэтому ​сейчас два ядра уже работают независимо. ​+Собираем проект и запускаем режим отладки. МК автоматически останавливается в функции //main()//, так как в настройках проекта, вкладка Debug, ​установлена опция "Run to main()"​. ​Слева внизу в окне "​Command"​ отображается лог запуска отладки,​ в котором видно, что на момент запуска отладки режим DUALCORE был выключен (равен 0), а отлаживаемое ядро имеет номер 0. 
 + 
 +{{ prog:​esila_cores:​command.png }} 
 + 
 +Переход в режим DUALCORE и установка различных стеков производится в файле startup.s ​до входа в main(), поэтому ​на момент остановки в функции main() ​два ядра уже работают независимо. 
 + 
 +<note important>​Если после запуска отладки выполнение программы не было остановлено в начале функции main, то в этом случае необходимо выйти из отладки,​ перейти в опции проекта,​ вкладка Debug, и снять галочку "Run to main()",​ после чего можно снова запускать отладку.</​note>​ 
 + 
 +{{ prog:​esila_cores:​opt_debug_run.png }}
  
 Казалось бы, мы подключились к ядру 0 и остановили его работу,​ при этом ядро 1 должно продолжать исполнять программу в своём "​ритме"​. Однако,​ здесь есть нюанс. Так как программа исполняется из ОЗУ, то отладчик может ставить программные точки останова,​ т.е. подменять инструкции,​ на которых мы хотели остановиться,​ на инструкции остановки типа "BKPT #​0x00"​. Казалось бы, мы подключились к ядру 0 и остановили его работу,​ при этом ядро 1 должно продолжать исполнять программу в своём "​ритме"​. Однако,​ здесь есть нюанс. Так как программа исполняется из ОЗУ, то отладчик может ставить программные точки останова,​ т.е. подменять инструкции,​ на которых мы хотели остановиться,​ на инструкции остановки типа "BKPT #​0x00"​.
Строка 129: Строка 139:
 {{ prog:​esila_cores:​bkpt.png }} {{ prog:​esila_cores:​bkpt.png }}
  
-При установке опции "Run to main()"​ такая программная точка останова ставится в начале main(), а так как оба ядра проходят по этому участку кода, то и остановлены они будут тоже оба. Нам такая ситуация даже удобна,​ так как мы точно знаем, что оба ядра остановлены,​ и запустив отладку второго ядра, можно смотреть за ходом выполнения программы. Однако,​ если необходимо чтобы второе ядро не останавливалось,​ достаточно снять галочку с опции "Run to main()"​ и при запуске отладки МК будет останавливаться в функции Reset_Handler.+При установке опции "Run to main()" ​(или "g ,main" в файле инициализации для старых версий Keil) такая программная точка останова ставится в начале main(), а так как оба ядра проходят по этому участку кода, то и остановлены они будут тоже оба. Нам такая ситуация даже удобна,​ так как мы точно знаем, что оба ядра остановлены,​ и запустив отладку второго ядра, можно смотреть за ходом выполнения программы. Однако,​ если необходимо чтобы второе ядро не останавливалось,​ достаточно снять галочку с опции "Run to main()" ​(или "g ,​main"​) ​и при запуске отладки МК будет останавливаться в функции Reset_Handler.
  
-Так как ​два ядра остановлены,​ мы можем запустить ​ядро и увидеть, что на демоплате мигает ​только ​синий светодиод. Теперь запустим отладку второго ядра. Для этого переходим в папку проекта SMP и ещё раз запускаем пример.+Сейчас два ядра остановлены, ​и мы можем ​в окне отладки ​запустить ​выполнение программы (F5), при этом будет ​запущено ​только ядро 0, а на демоплате ​замигает синий светодиод. Теперь запустим отладку второго ядра. Для этого переходим в папку проекта SMP и ещё раз запускаем пример.
  
 {{ prog:​esila_cores:​smp_prj.png }} {{ prog:​esila_cores:​smp_prj.png }}
Строка 145: Строка 155:
 </​code>​ </​code>​
  
-Запускаем отладку и видим, что ядро остановлено в начале функции main():+Собираем проект,​ запускаем отладку и видим, что ядро остановлено в начале функции main():
  
 {{ prog:​esila_cores:​stop_main.png }} {{ prog:​esila_cores:​stop_main.png }}
Строка 156: Строка 166:
 1. Как уже было отмечено ранее, если программа запускается из ОЗУ, то отладчик ULINK2 может ставить программные точки останова,​ которые,​ в случае попадания на общие участки кода, будут останавливать оба ядра. 1. Как уже было отмечено ранее, если программа запускается из ОЗУ, то отладчик ULINK2 может ставить программные точки останова,​ которые,​ в случае попадания на общие участки кода, будут останавливать оба ядра.
  
-2. После сбросе МК //не// по питанию,​ настройки режима DUALCORE сохраняются,​ так как блок BKP не сбрасывается. Это приводит к тому, то если программа будет загружена во FLASH память,​ а затем произойдёт Reset, оба ядра начнут исполнять загрузочную программу,​ в которой нет разделения стеков для двух ядер. Это обстоятельство может приводить к ошибкам при определении режима загрузки,​ и МК "​свалиться" в бесконечный цикл ожидания. Например,​ в режиме загрузки FLASH+JA при установленном бите LOCKSTEP МК не стартует. При этом для режима FLASH+JB данная ошибка не наблюдается.+2. После сброса МК //не// по питанию,​ настройки режима DUALCORE сохраняются,​ так как блок BKP не сбрасывается. Это приводит к тому, ​чтоесли программа будет загружена во FLASH память,​ а затем произойдёт Reset, оба ядра начнут исполнять загрузочную программу,​ в которой нет разделения стеков для двух ядер. Это обстоятельство может приводить к ошибкам при определении режима загрузки,​ и МК "​свалится"​ в бесконечный цикл ожидания. Например,​ в режиме загрузки FLASH+JA при установленном бите LOCKSTEP МК не стартует. При этом для режима FLASH+JB данная ошибка не наблюдается.
  
 3. При работе из FLASH-памяти необходимо учитывать ошибку Errata 1001, при которой возникают ошибки ECC, особенно часто в двухъядерном режиме работы. 3. При работе из FLASH-памяти необходимо учитывать ошибку Errata 1001, при которой возникают ошибки ECC, особенно часто в двухъядерном режиме работы.
prog/spec/elpower_dualcore.1559559112.txt.gz · Последние изменения: 2019/06/03 14:51 — vova