Съдържание:

Част 1 ARM Монтаж TI RSLK Роботология Учебна програма Лаборатория 7 STM32 Nucleo: 16 стъпки
Част 1 ARM Монтаж TI RSLK Роботология Учебна програма Лаборатория 7 STM32 Nucleo: 16 стъпки

Видео: Част 1 ARM Монтаж TI RSLK Роботология Учебна програма Лаборатория 7 STM32 Nucleo: 16 стъпки

Видео: Част 1 ARM Монтаж TI RSLK Роботология Учебна програма Лаборатория 7 STM32 Nucleo: 16 стъпки
Видео: EduNet. Цифровые технологии и инструменты образования 2024, Юли
Anonim
Image
Image

Фокусът на този Instructable е микроконтролерът STM32 Nucleo. Мотивацията за това да може да създаде монтажен проект от голи кости. Това ще ни помогне да се задълбочим и да разберем проекта за стартиране на MSP432 (TI-RSLK), който вече е бил тема на няколко инструктажа.

Няма много помощ онлайн за създаване на проект само за сглобяване за MSP432, използвайки Code Composer Studio. Досега просто копирахме/поставяхме от вече съществуващ сглобяем проект. Този подход ни послужи добре.

Въпреки това, сега за Lab 7 се сблъскахме с малко проблем. Или поне временно хълцане. Lab 7 въвежда машини с крайни състояния и първото нещо, с което се сблъскваме, е необходимостта от създаване и използване на масив от стойности. Тъй като курсът TI използва предимно C програмиране - това не е проблем. Но тези инструкции са фокусирани върху сглобяването, а не върху C.

Освен това, тъй като масивът има стойности само за четене, би било добре да го поставите във флаш памет, а не в RAM.

Изглежда, че има много повече помощ онлайн за сглобяващи проекти, използващи STM32 MCU, затова започваме с тази инструкция, с цел да използваме наученото, за да приложим след това MSP432 и Studio Composer Studio.

По пътя към тази цел ще имаме и опит с още един, популярен микроконтролер.

Стъпка 1: Първоначален тест на устройството

Първоначален тест на устройството
Първоначален тест на устройството
Първоначален тест на устройството
Първоначален тест на устройството
Първоначален тест на устройството
Първоначален тест на устройството

Отново, защо да изберете STM32 Nucleo по -специално?

Честно казано? Тъй като търсех добри статии за проекти за монтаж от гол метал за ARM контролери и попаднах на тази поредица. И също така, защото STM32 изглежда е популярен MCU.

Направих известно проучване (има много версии за избор - вижте изображението по -горе), но в крайна сметка стана това, което всъщност мога да получа, тъй като щях да използвам Amazon (в САЩ).

Той се предлага в прост, но професионален пакет, с някои инструкции за стартиране. Беше малко смешно да видим, че демонстрацията, записана в контролера, беше почти точно това, което сме правили в миналите Instructables - светодиод мига и променя скоростта според натискането на бутон.

Изглежда, че тази платка за развитие е много подобна на MSP432, тъй като има 2 светодиода и един потребителски бутон. MSP432 има 2 потребителски бутона.

Както можете да видите на снимките, бях малко изненадан, че платката има мини, а не микро USB. Трябваше да изтича, за да си купя кабел.

Друг добър тест е, че когато го свържете към компютъра си (използвам кутия за Linux), той се показва в моя файлов мениджър, като файлова система, наречена „NODE_F303RE“. Отваряне, което разкрива два файла, един HTML и един текст.

Това е всичко, но поне също така казва, че свързването изглежда доста лесно.

Сега сме готови да започнем.

Ще се опитам да не повтарям добрата информация от поредицата статии IVONOMICON Bare Metal, а по -скоро да я увелича.

Стъпка 2: Основните неща

Първото нещо, от което се нуждаем, е компилатор.

И тогава имаме нужда от отстраняване на грешки:

devchu@chubox: ~ $ sudo apt-get install gdb-arm-none-eabiЧетене на списъци с пакети … Готово Изграждане на дърво на зависимостта Четене на информация за състоянието … Готово Ще бъдат инсталирани следните НОВИ пакети: gdb-arm-none-eabi 0 надградени, 1 ново инсталиран, 0 за премахване и 8 не надграден. Трябва да вземете 2, 722 kB архиви. След тази операция ще бъдат използвани 7, 738 kB допълнително дисково пространство. Вземете: 1 https://us.archive.ubuntu.com/ubuntu xenial/universe amd64 gdb-arm-none-eabi amd64 7.10-1ubuntu3+9 [2, 722 kB] Извлечено 2, 722 kB за 1 s (1, 988 kB/s) Избиране на неизбран досега пакет gdb-arm-none-eabi. (Четене на база данни … 262428 файлове и директории, инсталирани в момента.) Подготовка за разопаковане…/gdb-arm-none-eabi_7.10-1ubuntu3+9_amd64.deb… Разопаковане на gdb-arm-none-eabi (7.10-1ubuntu3+9)… Обработка тригери за man-db (2.7.5-1)… Настройване на gdb-arm-none-eabi (7.10-1ubuntu3+9)…

Стъпка 3: Основните неща - Windows

Горната стъпка предполага, че използваме Linux. Ами ако използваме Windows?

Можете да отидете на сайта за разработчици на ръка и има няколко опции за изтегляне. Използвам машина с Windows 8.

По време на инсталацията избрах да я инсталирам в коренния диск "C: \" вместо в програмните файлове, само защото използвам и cygwin и беше по -лесно да създам връзка от моя локален кош към корен C: папка, отколкото всички бъркотия по пътя към програмните файлове (с интервали и т.н.).

Така моята среда и път на cygwin и т.н. изглежда така:

C: / cygwin64 / home / bin / arm-none-eabi-gcc, където arm-none-eabi-gcc е връзка към C: / GNUToolsArmEmbedded / 7.2018.q2.update / bin / arm-none-eabi- gcc.

След това създадох папка „dev“под cygwin home и там поставих файла core. S и изпълних командата компилатор. (вижте по -долу за компилатора).

Направих абсолютно същото за gdb (arm-none-eabi-gdb).

Стъпка 4: Какви са основните

И така, какво е "gcc-arm-none-eabi"?

Компилаторът gnu (GCC) ще компилира езиците за програмиране (като C) в собствен код за машината, на която работи. Например, ако трябва да компилирате някакъв C код, използвайки GCC на вашата машина с Windows, той ще бъде създаден да работи на машината с Windows. Генерираният изпълним файл (обикновено) няма да работи на ARM микроконтролера.

Така че, за да изградим програми, които да бъдат изтеглени и записани в микроконтролера ARM (в настоящия случай това би било STM32 Nucelo), трябва да дадем на GCC нещо друго: възможността за „кръстосано компилиране“. Тоест, възможността за генериране на изпълним файл, не за неговата родна система (и процесор), а за целевата система (микроконтролера ARM). Това е мястото, където "gcc-arm-none-eabi" влиза в игра.

Тогава какво е "gdb-arm-none-eabi"?

След като сме изтеглили и записали (прехвърлили) новосъздадения изпълним файл в микроконтролера, вероятно ще искаме да го отстраним-стъпка по ред по код на кода. GDB е gnu дебъгер и също се нуждае от начин да си свърши работата, но насочен към различна система.

По този начин gdb-arm-none-eabi е за GDB, каквото gcc-arm-none-eabi е за GCC.

Друг предложен пакет за инсталиране е „libnewlib-arm-none-eabi“. Какво е това?

Newlib е библиотека на C и математическа библиотека, предназначена за използване на вградени системи. Това е конгломерат от няколко библиотечни части, всички под лицензи за безплатен софтуер, които ги правят лесно използваеми за вградени продукти.

И накрая, пакетът "libstdc ++-arm-none-eabi". Това е доста очевидно; това е C ++ библиотека за крос-компилатора; за вградени ARM микроконтролери.

Стъпка 5: Файлът за свързване

Файлът за свързване
Файлът за свързване
Файлът за свързване
Файлът за свързване

Нека създадем скрипт за свързване.

Една ключова част или блок в този файл би била командата MEMORY.

--- от sourceware.org:

Конфигурацията по подразбиране на линкера позволява разпределяне на цялата налична памет. Можете да отмените това, като използвате командата MEMORY. Командата MEMORY описва местоположението и размера на блоковете памет в целта. Можете да го използвате, за да опишете кои области на паметта могат да бъдат използвани от свързващия елемент и кои области на паметта трябва да избягва. След това можете да присвоите раздели на определени региони на паметта. Връзката ще зададе адреси на секции въз основа на регионите на паметта и ще предупреди за региони, които стават твърде пълни. Линкерът няма да разбърква секциите наоколо, за да се побере в наличните региони. Скриптът за свързване може да съдържа много приложения на командата MEMORY, но всички дефинирани блокове памет се третират така, сякаш са посочени в една команда MEMORY. Синтаксисът за MEMORY е:

ПАМЕТ

{name [(attr)]: ORIGIN = произход, LENGTH = len…}

Примерът в статията:

/* Определете края на RAM и границата на паметта на стека* //* (4KB SRAM на линията STM32F031x6, 4096 = 0x1000)*//* (RAM започва на адрес 0x20000000) _estack = 0x20001000;

ПАМЕТ

{FLASH (rx): ORIGIN = 0x08000000, LENGTH = 32K RAM (rxw): ORIGIN = 0x20000000, LENGTH = 4K}

Така че трябва да разберем колко FLASH (за нашата програма и константи и т.н.) и колко RAM (за използване от програмата; купчина и стек и т.н.) за нашата конкретна платка. Това става малко интересно.

Хубавата малка карта, която се доставя с Nucleo, казва, че има флаш памет 512 Kbytes, а SRAM е 80 Kbytes. Въпреки това, свързвайки го към USB, той се монтира като файлова система с два файла, като и файловият мениджър и GParted показват, че има над 540+ Kbytes пространство. (RAM?).

НО, опитвайки се да изтриете двата файла с помощта на файловия мениджър, прекъсване и повторно свързване на устройството, все още показва двата файла. (и файловият мениджър е разпознал нещо, защото на всеки файл има малка икона "заключване".

Така че нека да продължим с цифрите на картата. Така че сега вземаме горния пример и го преобразуваме в нашата конкретна дъска.

Може да искате да използвате нещо като този онлайн конвертор на памет, за да преминете от общия KB към конкретен брой байтове.

Тогава може да искате да използвате онлайн десетичен в шестнадесетичен конвертор.

/ * Определете края на RAM и ограничението на паметта на стека */

/* (4KB SRAM на линия STM32F031x6, 4096 = 0x1000)* //* примерът*/

/ * стъпка 1: (80KB SRAM на STM32F303RE, 81920 = 0x14000) * // * нашата дъска */

/* стъпка 2, добавете шестнадесетичния размер към шестнадесетичния начален адрес (по -долу). */

/ * (RAM започва на адрес 0x20000000) */

_estack = 0x20001000; / * примерът */

_estack = 0x20014000; / * нашата дъска */

ПАМЕТ {

FLASH (rx): ORIGIN = 0x08000000, LENGTH = 512K

RAM (rxw): ORIGIN = 0x20000000, LENGTH = 80K

}

Нека извикаме горния файл „linker.script.ld“.

Стъпка 6: Векторната таблица

Векторната таблица
Векторната таблица

Сега ще създадем малък асемблерен файл (с директиви), за да направим някои много основни манипулации на прекъсвания. Ще следваме примера на статията и ще създадем файл с име "core. S".

Отново, тук е примерното съдържание на файла, но направих промяна за нашата конкретна дъска:

// Тези инструкции определят атрибутите на нашия чип и

// асемблерният език, който ще използваме:.syntax unified /*Вижте по-долу след тази кодова област* //*.cpu cortex-m0* / /*коментирайте този ред от примера* /.cpu cortex-m4 /* вместо това добавете кората на нашия борд. вижте горното изображение в тази стъпка * / /*.fpu softvfp * / / *коментирайте този ред от примера * /.fpu vfpv4 / *добавете вместо това нашия борд; той има FPU */.thumb // Глобални местоположения на паметта..global vtable.global reset_handler / * * Действителната векторна таблица. * Включени са само размерът на оперативната памет и манипулаторът за „нулиране“*, за опростяване. */.type vtable, %object vtable:.word _estack.word reset_handler.size vtable,.-vtable

Хм.. Няма директива „.align“

Това обаче не е критично. Повече за това (може би) по -късно.

.синтаксис унифициран

.синтаксис [унифициран | разделен]

Тази директива задава синтаксиса на набор от инструкции, както е описано в раздела ARM-Instruction-Set

9.4.2.1 Синтаксис на набор от инструкции Два малко различни синтаксиса поддържат инструкции ARM и THUMB. По подразбиране, разделен, използва стария стил, където инструкциите ARM и THUMB имат свои собствени, отделни синтаксиси. Новият, унифициран синтаксис, който може да бъде избран чрез директивата.syntax.

.fpu vfpv4

GCC компилаторът може да създаде двоични файлове с няколко опции по отношение на плаващата запетая: мека - подходяща за работа на процесори без FPU - изчисленията се извършват в софтуер чрез генериран от компилатор softfp - подходящ за работа на процесори с или без FPU - ще използва FPU, ако има такъв. За нашия конкретен случай (ще трябва да направите свое собствено проучване), FPU на този съвет отговаря на vfpv4. Може да се наложи да си поиграете с това. Или дори го оставете на softfp.

.thumb (срещу.arm)

Тези ARM микроконтролер всъщност имат комбинация от набори от инструкции. Едната е ARM, другата е THUMB. Една разлика е 16-битовите инструкции срещу 32-битовите инструкции. По този начин тази директива казва на компилатора да третира следващите инструкции като THUMB или ARM.

Просто ще вземем останалата част от файла такъв, какъвто е, тъй като тези Instructables все още не са се задълбочили в програмирането на сглобяване, управлявано от прекъсвания.

Стъпка 7: Версията за сглобяване на програма „Hello World“

Следното може да влезе и в създадения по-рано файл "core. S". Това отново е от примера в статията.

/ * * Манипулаторът за нулиране. Извиква се при нулиране. */.type reset_handler, %function reset_handler: // Задайте указателя на стека до края на стека. // Стойността '_estack' е дефинирана в нашия скрипт за свързване. LDR r0, = _estack MOV sp, r0

// Задайте някои фиктивни стойности. Когато видим тези стойности

// в нашия дебъгер ще знаем, че нашата програма // е заредена на чипа и работи. LDR r7, = 0xDEADBEEF MOVS r0, #0 main_loop: // Добавете 1, за да регистрирате 'r0'. ДОБАВЯ r0, r0, #1 // Цикъл назад. B main_loop.size reset_handler,.-Reset_handler

И така, целта на горната програма е да зареди разпознаваем модел в един ядро MCU регистър (в този случай R7), и нарастваща стойност, започваща от нула в друг регистър на ядро MCU (в този случай R0). Ако преминем през изпълняващия код, трябва да видим увеличението на данните на R0.

Ако сте следвали заедно с инструкциите по отношение на MSP432 и курса/лабораториите на TI-RSLK, тогава почти всички горепосочени програми трябва да са ви познати.

Единственото ново нещо, което мога да видя, е използването на "=" при зареждане на "DEADBEEF" в за регистриране на R7. Не бяхме използвали това.

Прикаченият тук файл "core. S" съдържа пълния източник.

Стъпка 8: Съставяне на кодекса

Време е да направите някои неща от командния ред. Най -накрая нещо истинско.

Ние обаче не сме съвсем там. Отново трябва да променим командата, дадена в статията, и да я променим според собствената си ситуация.

Ето примерния код:

arm -none -eabi -gcc -x асемблер -с -cpp -c -O0 -mcpu = cortex -m0 -mthumb -Wall core. S -o core.o

Ако отидем на сайта gnu.org за GCC, (в този случай версия 7.3),

х

-X е за да посочите езика. В противен случай, ако няма -x, тогава компилаторът ще се опита да отгатне, като използва разширението на файла. (в нашия случай *. S).

Горният пример от статията посочва асемблер-с-cpp, но можем просто да направим асемблер.

° С

-C казва „компилирайте, но не свързвайте.

O0

-O трябва да зададе нивото на оптимизация. Използването на -O0 (о -нула) казва "намалете времето за компилиране и накарайте отстраняването на грешки да даде очакваните резултати. Това е по подразбиране".

mcpu = кора-m0

-Mcpu определя името на целевия процесор. В нашия случай това ще бъде cortex-m4.

mthumb

-Mthumb определя избора между генериране на код, който изпълнява състояния ARM и THUMB.

Стена

Разбира се, стената е много разпространена и добре позната. Включва всички предупредителни флагове.

И накрая, в края на командата имаме входния файл core. S и изходния файл core.o.

Ето получения нов команден ред, който отговаря на нашия конкретен случай.

arm -none -eabi -gcc -x асемблер -c -O0 -mcpu = cortex -m4 -mthumb -Wall core. S -o core.o

И това се компилира.

Стъпка 9: Свързване на програмата

Директно от примера в статията имаме следното:

arm -none -eabi -gcc core.o -mcpu = cortex -m0 -mthumb -Wall --specs = nosys.specs -nostdlib -lgcc -T./STM32F031K6T6.ld -o main.elf

Повечето от горните неща сте виждали. По -долу е новото.

specs = nosys.specs

Това е малко трудно да се обясни.

Това е свързано с „полухостинг“и „ретаргетинг“, както и с вход / изход. Това също е свързано със системни повиквания и библиотеки.

Обикновено вградените системи не предоставят стандартни устройства за вход/изход. Това би повлияло на системните или библиотечните повиквания (пример: printf ()).

Полу -хостинг означава, че инструментът за отстраняване на грешки (вижте Стъпка 11 изображение с част на отстраняване на грешки, закръглена в червено) има специален канал и използва протокола за полухостинг и можете да видите изхода на printf () на хост машината (чрез дебъгъра).

Пренасочването, от друга страна, означава, че същите тези системни или библиотечни обаждания означават нещо друго. Те правят нещо друго, което има смисъл за вградената система. В известен смисъл, да речем за printf (), има нова реализация, пренасочена реализация на тази функция.

Като каза всичко това, --specs = nosys.specs означава, че няма да бъдем полухостинг. Това обикновено би означавало, че пренасочваме. Това ни води до следващото знаме.

nostdlib

Опцията за свързване -nostdlib се използва за свързване на програма, предназначена да работи самостоятелно. -nostdlib предполага отделните опции -nodefaultlibs и -nostartfiles. По-долу обсъждаме двете опции поотделно, но най-типичната употреба е просто nostdlib за еднократно пазаруване. Когато свързвате хоствана програма, стандартните системни библиотеки като libc са свързани по подразбиране, което дава на програмата достъп до всички стандартни функции (printf, strlen и приятели). Опцията за свързване -nodefaultlibs забранява свързването с тези библиотеки по подразбиране; единствените свързани библиотеки са точно тези, които изрично посочвате към линкера, използвайки флага -l.

lgcc

libgcc.a е стандартна библиотека, която предоставя вътрешни подпрограми за преодоляване на недостатъците на определени машини. Например процесорът ARM не включва инструкция за разделяне. ARM версията на libgcc.a включва функция за разделяне и компилаторът излъчва повиквания към тази функция, когато е необходимо.

T

Това е просто начин да кажете на линкъра да използва този файл като скрипт за свързване. В нашия случай името на файла е linker.script.ld.

o main.elf

И накрая, ние казваме на линкера какво ще бъде името на крайния изходен файл с изображение, който ще бъде записан/мига в нашето устройство.

Ето нашата версия на пълния команден ред, модифицирана за нашата конкретна ситуация:

arm -none -eabi -gcc core.o -mcpu = cortex -m4 -mthumb -Wall --specs = nosys.specs -nostdlib -lgcc -T./linker.script.ld -o main.elf

Уверяваме се, че скриптовият файл и файлът core.o са в една и съща директория, където ще изпълним горния команден ред.

И се свързва без проблеми.

Проверка

След това изпълняваме:

arm-none-eabi-nm main.elf

и получаваме:

devchu@chubox: ~/Development/Atollic/TrueSTUDIO/STM32_workspace_9.1 $ arm-none-eabi-nm main.elf 20014000 A _estack 08000010 t main_loop 08000008 T reset_handler 08000000 T vtable

Изглежда добре. Командата arm-none-eabi-nm е начин за изброяване на символи в обектните файлове.

Стъпка 10: Тестване на връзката към STM32 Nucleo-64

TestingConnection към STM32 Nucleo-64
TestingConnection към STM32 Nucleo-64
TestingConnection към STM32 Nucleo-64
TestingConnection към STM32 Nucleo-64

Първата ви мисия, ако решите да я приемете, е да накарате вашата система да види борда ви за развитие.

Използване на Windows

За Windows реших да инсталирам TrueSTUDIO от Atollic (безплатна версия). Това беше безболезнено инсталиране и автоматично инсталира драйвера, за да мога да използвам st-link за тестване на връзката. След като инсталирах TrueSTUDIO и диспечерът на устройства видя устройството, изтеглих инструментите texan/stlink, предложени от статията Bare Metal, която следвахме. Отново поставих папката директно под „C: \“и отново създадох някои връзки от моята локална кошница cygwin home към командите.

ln -s /c/STM32. MCU/stlink-1.3.0-win64/bin/st-info.exe ~/bin/st-info

Като първоначален тест, за да видя дали наистина можем да комуникираме с устройството, тичах:

st-info-sonda

И се върна:

Намерени 1 stlink програмисти

Така че сега знаем, че можем да поговорим/попитаме нашия съвет за развитие.

Използване на Linux

За Linux всъщност не се нуждаете от драйвер. Но за Debian ще трябва да изградите st инструментите от източника.

git clone

Уверете се, че имате инсталиран libusb-1.0-0-dev.

подходящ списък | grep -E "*libusb.*dev*"

Трябва да видиш:

libusb-1.0-0-dev/xenial, сега 2: 1.0.20-1 amd64 [инсталиран]

Или нещо такова.

За да го инсталирате:

sudo apt-get install libusb-1.0-0-dev

Обърнете внимание, че горното не е същото като:

sudo apt-get install libusb-dev

Правилният липсващ libusb dev може да причини проблеми на cmake.

Грешка CMake: Следните променливи се използват в този проект, но те са настроени на NOTFOUND. Моля, задайте ги или се уверете, че са зададени и тествани правилно във файловете CMake: LIBUSB_INCLUDE_DIR (НАПРЪСНЕНО)

Променете основната директория на проекта (… blah /blah /stlink). Направете „make release“.

След тази компилация инструментите трябва да бъдат под ".. /build /Release".

След това можете да стартирате "st-info --probe". Ето изхода със свързания Nucleo, а след това не.

devchu@chubox: ~/Development/stlink $./build/Release/st-info --probe Намерен 1 stlink програмист сериал: 303636414646353034393535363537 openocd: "\ x30 / x36 / x36 / x41 / x46 / x46 / x35 / x30 / x34 / x39 / x35 / x35 / x36 / x35 / x37 "флаш: 524288 (размер на страницата: 2048) sram: 65536 чипид: 0x0446 дескриптор: F303 устройство с висока плътност devchu@chubox: ~/Development/stlink $./build/Release/st- info --probe Намерени 0 stlink програмисти devchu@chubox: ~/Development/stlink $

Стъпка 11: Нека използваме GDB с Linux

Нека използваме GDB с Linux
Нека използваме GDB с Linux
Нека използваме GDB с Linux
Нека използваме GDB с Linux

Ако сте опитвали всичко това и сте стигнали дотук - страхотно! Отлично. Нека се позабавляваме сега.

Когато купувате тези дъски за разработка на ARM, независимо дали са MSP432 Launchpad от Texas Instruments, или този, който обсъждаме сега, Nucleo-F303 (STM32 Nucleo-64), те обикновено пристигат вече изпълнени с работеща програма, обикновено някаква мигаща програма, която включва и натискане на превключвател за промяна на скоростта, с която светодиодите (ите) мигат.

Преди да сме толкова бързи да надпишем това, нека видим какво има да се види и направи.

С Linux отворете терминал, променете директорията на проекта stlink git, който току-що създадохме, и намерете инструмента st-util.

devchu@chubox: ~/Development/stlink $ find. -име st-util

./build/Release/src/gdbserver/st-util

Стартирайте този инструмент. Тъй като вече сме тествали връзката ни със st-info --probe, трябва да получим някакъв изход по следния начин:

devchu@chubox: ~/Development/stlink $./build/Release/src/gdbserver/st-util

st-util 1.4.0-50-g7fafee2 2018-10-20T18: 33: 23 INFO common.c: Зареждане на параметри на устройството…. 2018-10-20T18: 33: 23 INFO common.c: Свързаното устройство е: F303 устройство с висока плътност, id 0x10036446 2018-10-20T18: 33: 23 INFO common.c: SRAM размер: 0x10000 байта (64 KiB), Flash: 0x80000 байта (512 KiB) в страници от 2048 байта 2018-10-20T18: 33: 23 ИНФОРМАЦИЯ gdb-server.c: Чип ID е 00000446, Core ID е 2ba01477. 2018-10-20T18: 33: 23 INFO gdb-server.c: Слушане на *: 4242…

Това е GDB сървърът, който работи сега и вижда нашата дъска за разработка и по -важното е, че слуша на порт 4242 (порт по подразбиране).

Сега сме готови да задействаме GDB клиента.

В Linux отворете друг терминал, въведете това:

arm-none-eabi-gdb -tui

Това е същото като изпълнението на gdb строго от командния ред, но вместо това той произвежда текстово базиран терминал (предполагам, че използва проклятия).

Имаме работещ клиент GDB и GDB сървър. Клиентът обаче не е свързан със сървъра. В момента той не знае нищо за нашия Nucleo (или дъска по ваш избор). Трябва да го кажем. В терминала вашата подкана сега трябва да бъде "(gdb)". Въведете:

помогнете на целта

Ще ви даде списък. Забележете, че този, който искаме, е насочен към удължено -отдалечено - Използвайте отдалечен компютър чрез серийна линия.

Но също така трябва да му дадем местоположението. И така, в подканата (gdb) въведете:

(gdb) целеви разширен-отдалечен локален хост: 4242

Трябва да получите отговор по следния начин:

(gdb) целеви разширен-отдалечен локален хост: 4242

Отдалечено отстраняване на грешки с помощта на localhost: 4242 0x080028e4 в ?? ()

Междувременно в терминала, работещ със st-util gdbserver, получихме следното:

2018-10-20T18: 42: 30 INFO gdb-server.c: Намерени са 6 hw регистъра на прекъсвания

2018-10-20T18: 42: 30 INFO gdb-server.c: GDB свързан.

Стъпка 12: Нека повторим, с Windows и Flash нашата програма

Нека повторим, с Windows и Flash нашата програма
Нека повторим, с Windows и Flash нашата програма
Нека повторим, с Windows и Flash нашата програма
Нека повторим, с Windows и Flash нашата програма
Нека повторим, с Windows и Flash нашата програма
Нека повторим, с Windows и Flash нашата програма

Стъпките за стартиране на st-util gdbserver и клиента arm-none-eabi-gdb са по същество същите, както направихме по време на предишната стъпка. Отваряте два терминала (cygwin, DOS cmd или Windows Powershell), намирате местоположението на st-util, стартирате го. В другия терминал стартирайте клиента arm-none-eabi-gdb. Единствената разлика е, че режимът -tui (изглед на текст, базиран на терминал) най -вероятно не се поддържа.

Ако горното работи в Windows, вероятно ще трябва да спрете (само клиентът). В този момент по някакъв начин ще трябва да стартирате GDB клиента, където е вашият файл за изграждане ("core.out"), или да добавите целия път към този файл като аргумент към GDB клиента.

Опростих живота си, като използвах cygwin и създадох връзки от моята локална директория $ HOME // bin, където се намират и двата инструмента.

Добре, компилирахме и свързахме както преди и имаме файл main.elf готов за мигане.

Имаме st-util, работещ в един прозорец. Рестартираме GDB клиента, този път правим:

arm-none-eabi-gdb main.elf

Оставяме го да стартира, изчакваме подкана (gdb), изпълняваме същата команда за свързване към GDB сървъра (st-util) и сме готови да прехвърлим изпълнимия файл. Много е антиклиматичен:

(gdb) натоварване

При работа с терминали cygwin има известен проблем с това, че понякога конзолните команди не се извеждат. Така че в нашия случай прозорецът със сървъра беше напълно безшумен. Този, който изпълнява клиента, където изпълнихме товара, изведе това:

Зареждане на раздел.text, размер 0x1c lma 0x8000000 Начален адрес 0x8000000, размер на зареждане 28 Скорост на трансфер: 1 KB/sec, 28 байта/запис.

Стъпка 13: Премигване с Linux - Повече възнаграждение: D

Мига с Linux - още възнаграждение: D
Мига с Linux - още възнаграждение: D

Стъпка 14: Нека се потопим малко по -дълбоко

Ако стигнете до тук, отлично. Нека да продължим.

Защо не погледнете вътре в файла main.elf, изпълнимия файл? Изпълнете следното:

arm-none-eabi-objdump -d main.elf

Трябва да видите изход нещо подобно:

main.elf: файлов формат elf32-littlearm

Демонтаж на раздел.text:

08000000:

8000000: 00 40 01 20 09 00 00 08.@. ….

08000008:

8000008: 4802 ldr r0, [pc, #8]; (8000014) 800000a: 4685 mov sp, r0 800000c: 4f02 ldr r7, [pc, #8]; (8000018) 800000e: 2000 movs r0, #0

08000010:

8000010: 3001 добавя r0, #1 8000012: e7fd b.n 8000010 8000014: 20014000. Дума 0x20014000 8000018: deadbeef. Дума 0xdeadbeef

Какви малки късчета можем да получим от горния изход?

Ако си спомняте, когато обсъждахме и създавахме файла linker.script.ld, заявихме, че тези ARM устройства имат RAM, започващ от 0x20000000, и че FLASH паметта започва от 0x08000000.

По този начин можем да видим, че наистина програмата е такава, че всичко се намира в FLASH паметта.

Тогава, по -горе, но по -късна стъпка, когато обсъждахме частта „Hello World“, имаше изявление, при което зареждаме непосредствена, постоянна, буквална стойност („0xDEADBEEF“) в основен регистър на MCU („R7“).

Изявлението беше:

LDR R7, = 0xDEADBEEF

В нашия код това е единственото място, където дори споменаваме DEADBEEF. Никъде другаде. И все пак, ако погледнете горните разглобени/реконструирани инструкции и т.н., има повече неща, свързани с DEADBEEF, отколкото си мислехме.

Така че компилаторът/линкерът по някакъв начин реши постоянно да прехвърли стойността на DEADBEEF в FLASH адрес, на място 0x8000018. И тогава компилаторът промени горната ни инструкция за LDR на:

LDR R7, [PC, #8]

Той дори генерира коментар за нас. Колко хубаво. И ни казва да вземем текущата стойност на брояча на програмата (компютърния регистър), да добавим 0x8 към тази стойност и това е мястото, където DEADBEEF е изгорен, и да получим тази стойност и да я поставим в R7.

Това означава също, че програмният брояч (PC) сочи към адрес 0x8000010, който е началото на main_loop, и че стойността DEADBEEF седи на два адреса след края на main_loop.

Стъпка 15: Накрая, кратък поглед върху изпълняваната програма

Дори и да напуснете GDB, просто въведете отново командата. Дори не е нужно да му давате никакъв файл; вече не мигаме, просто го стартираме.

След като свържете отново GDB клиента към GDB сървъра, в командния ред (gdb):

(gdb) информационни регистри

Трябва да видите нещо подобно:

r0 0x0 0

r1 0x0 0 r2 0x0 0 r3 0x0 0 r4 0x0 0 r5 0x0 0 r6 0x0 0 r7 0x0 0 r8 0x0 0 r9 0x0 0 r10 0x0 0 r11 0x0 0 r12 0x0 0 sp 0x20014000 0x20014000 lr 0xffffffff 4294980000000

Но след това в подканата (gdb) въведете:

(gdb) продължи

И много бързо натиснете CTRL-C. Това трябва да спре програмата. Въведете отново командата "info registers".

Този път изглежда различно:

(gdb) информационни регистри

r0 0x350ffa 3477498 r1 0x0 0 r2 0x0 0 r3 0x0 0 r4 0x0 0 r5 0x0 0 r6 0x0 0 r7 0xdeadbeef 3735928559 r8 0x0 0 r9 0x0 0 r10 0x0 0 r11 0x0 0 r0 0x0 0x00x00x0000 16777216

Какво стана? Точно това, което искахме. DEADBEEF беше зареден в R7 и R0 се увеличава (изключително бързо). Ако повторите, ще видите R0 отново с друга стойност.

Стъпка 16: Искахме да създадем масив само за четене във Flash

Един от начините за създаване на еквивалент на масив с помощта на монтаж и директиви е следният:

.type myarray, %object // името или етикетът „myarray“се определя като тип обект.

myarray: // това е началото на декларацията на 'myarray' // (от какво ще се състои).word 0x11111111 // първият член или стойност, съдържащи се в „myarray“..word 0x22222222 // втората стойност (съседни адреси)..слова 0x33333333 // и така нататък..size myarray,.-myarray // компилаторът/асемблерът вече знае къде е краят или // границата на 'myarray'.

Сега, когато сме го настроили във FLASH памет, можем да го използваме в програмата. По -долу е част:

LDR R1, myarray // това зарежда данни, съдържащи се на първо място на „myarray“. “// това не е това, което искаме.

LDR R1, = myarray // това зарежда самата стойност на местоположението (1 -ви адрес), // не данните.. // това е това, което искаме.

MOV R2, #0 // R2 ще води преброяване, за да се увери, че не тръгваме

// край на масива. LDR R3, = myarrsize // R3 ще бъде еквивалентът на „myarrsize“.

// R0 ще съхранява нашите данни

main_loop:

LDR R0, [R1] // Заредете данните, посочени от R1 („myarray“) в R0. CMP R2, R3 // На границата на масива ли сме? BEQ main_loop // Ако сме, приключихме, така че просто ще се въртим завинаги.

ДОБАВЯНЕ R2, #1 // В противен случай можем да продължим итерацията чрез масив.

ADD R1, #4 // Добавете 4, за да регистрирате R1, така че да сочи правилно към следващия

// адрес..

B main_loop // Цикъл назад.

Видеото преминава през всичко това и в него има грешка. Добре е; показва, че е важен код за изпълнение и отстраняване на грешки. Той показва класически случай на излизане от края на масива.

Препоръчано: