Სარჩევი:

ნაწილი 1 ARM Assembly TI RSLK Robotics Learning Curriculum Lab 7 STM32 Nucleo: 16 Steps
ნაწილი 1 ARM Assembly TI RSLK Robotics Learning Curriculum Lab 7 STM32 Nucleo: 16 Steps

ვიდეო: ნაწილი 1 ARM Assembly TI RSLK Robotics Learning Curriculum Lab 7 STM32 Nucleo: 16 Steps

ვიდეო: ნაწილი 1 ARM Assembly TI RSLK Robotics Learning Curriculum Lab 7 STM32 Nucleo: 16 Steps
ვიდეო: Learn Some ARM Assembly - MSP432 - TI-RSLK - Texas Instruments Robotics System Learning Kit - Lab 3 2024, ივლისი
Anonim
Image
Image

ამ ინსტრუქციის ფოკუსია STM32 Nucleo მიკროკონტროლი. ამის მოტივაცია, რომ შევძლოთ შიშველი ძვლებისგან შეკრების პროექტის შექმნა. ეს დაგვეხმარება უფრო ღრმად ჩავწვდეთ და გავიგოთ MSP432 Launchpad პროექტი (TI-RSLK), რომელიც უკვე იყო რამოდენიმე ინსტრუქციის თემა.

ინტერნეტში არ არის ძალიან დიდი დახმარება MSP432– ისთვის ასამბლეის პროექტის შესაქმნელად, Code Composer Studio– ს გამოყენებით. აქამდე ჩვენ უბრალოდ ვიკოპირებდით/ვკრავდით უკვე არსებული ასამბლეის პროექტიდან. ეს მიდგომა კარგად გვეხმარება.

თუმცა, ახლა, ლაბორატორი 7 -ისთვის, ჩვენ ცოტა პრობლემა შეგვხვდა. ან თუნდაც დროებითი ჩხვლეტა. ლაბორატორია 7 შემოაქვს სასრული მდგომარეობის მანქანებს და პირველი რასაც ჩვენ ვხვდებით არის ღირებულებების მასივის შექმნისა და გამოყენების აუცილებლობა. ვინაიდან TI კურსი ძირითადად იყენებს C პროგრამირებას - ეს არ არის პრობლემა. მაგრამ ეს ინსტრუქციები ორიენტირებულია შეკრებაზე და არა C.

გარდა ამისა, ვინაიდან მასივი მხოლოდ წაკითხვის მნიშვნელობისაა, კარგი იქნება ის ჩადოთ ფლეშ მეხსიერებაში და არა RAM- ში.

როგორც ჩანს, ინტერნეტში გაცილებით მეტი დახმარებაა STM32 MCU– ს გამოყენებით შეკრების პროექტებისთვის, ამრიგად, ჩვენ ვიწყებთ ამ ინსტრუქციებით, იმისთვის, რომ ვისწავლოთ ნასწავლი, შემდეგ მივმართოთ MSP432– ს და Code Composer Studio– ს.

ამ მიზნისკენ მიმავალ გზაზე ჩვენ ასევე მივიღებთ გამოცდილებას კიდევ ერთ, პოპულარულ მიკროკონტროლერთან.

ნაბიჯი 1: მოწყობილობის საწყისი ტესტირება

მოწყობილობის საწყისი ტესტირება
მოწყობილობის საწყისი ტესტირება
მოწყობილობის საწყისი ტესტირება
მოწყობილობის საწყისი ტესტირება
მოწყობილობის საწყისი ტესტირება
მოწყობილობის საწყისი ტესტირება

კიდევ ერთხელ, რატომ ავირჩიოთ STM32 Nucleo განსაკუთრებით?

პატიოსნად? იმიტომ, რომ ვეძებდი კარგ სტატიებს ARM კონტროლერებისათვის შიშველი ლითონის შეკრების პროექტებზე და ამ სერიას წავაწყდი. და ასევე იმიტომ, რომ STM32, როგორც ჩანს, პოპულარული MCU.

მე ჩავატარე კვლევა (ბევრი ვერსიის ასარჩევია - იხილეთ სურათი ზემოთ), მაგრამ საბოლოოდ ის გახდა ის, რისი მიღებაც რეალურად შემეძლო, რადგან ვაპირებდი ამაზონის გამოყენებას (აშშ -ში).

ის მოდის მარტივი, მაგრამ პროფესიონალური პაკეტით, დაწყების ინსტრუქციით. ცოტა სასაცილო იყო იმის დანახვა, რომ კონტროლერში ჩაწერილი დემო იყო ზუსტად ის, რაც ჩვენ გავაკეთეთ წარსულ ინსტრუქციებში - LED ანათებს და ცვლის სიჩქარეს ღილაკის დაჭერის მიხედვით.

როგორც ჩანს, ეს დაფა ძალიან ჰგავს MSP432- ს იმით, რომ არის 2 LED და ერთი მომხმარებლის ღილაკი. MSP432– ს აქვს 2 მომხმარებლის ღილაკი.

როგორც ხედავთ ფოტოებში, მე ცოტა გამიკვირდა, რომ დაფას აქვს მინი და არა მიკრო USB. მოუხდა გაშვება კაბელის საყიდლად.

კიდევ ერთი კარგი გამოცდა ის არის, რომ როდესაც მას კომპიუტერთან აკავშირებთ (მე Linux ბოქსს ვიყენებ), ის გამოჩნდება ჩემს ფაილ მენეჯერში, როგორც ფაილური სისტემა, სახელწოდებით "NODE_F303RE". გახსნისას გამოჩნდება ორი ფაილი, ერთი HTML და ერთი ტექსტი.

ეს არის ის, მაგრამ ყოველ შემთხვევაში ის ასევე ამბობს, რომ კავშირი საკმაოდ ადვილი ჩანს.

ახლა ჩვენ მზად ვართ დავიწყოთ.

მე შევეცდები არ გავიმეორო IVONOMICON Bare Metal სტატიების სერიის რაიმე კარგი ინფორმაცია, არამედ გავზარდო იგი.

ნაბიჯი 2: აუცილებელი

პირველი რაც ჩვენ გვჭირდება არის შემდგენელი.

და შემდეგ, ჩვენ გვჭირდება debugger:

devchu@chubox: su $ sudo apt-get install gdb-arm-none-eabi პაკეტების სიების წაკითხვა … დასრულდა შენდება დამოკიდებულების ხე კითხულობს სახელმწიფო ინფორმაციას… შესრულებულია შემდეგი ახალი პაკეტები დაინსტალირდება: gdb-arm-none-eabi 0 განახლებულია, 1 ახლად დაინსტალირებული, 0 ამოსაღებად და 8 არა განახლებული. უნდა მიიღოთ 2, 722 კბ არქივი. ამ ოპერაციის შემდეგ, გამოყენებული იქნება 7, 738 კბ დამატებითი დისკის ადგილი. მიიღეთ: 1 https://us.archive.ubuntu.com/ubuntu xenial/სამყაროს amd64 gdb-arm-none-eabi amd64 7.10-1ubuntu3+9 [2, 722 კბ] ამოღებულია 2, 722 კბ 1 წამში (1, 988 კბ/წ) ადრე არჩეული პაკეტის არჩევა gdb-arm-none-eabi.. გამომწვევები man-db (2.7.5-1)… gdb-arm-none-eabi (7.10-1ubuntu3+9) დაყენება…

ნაბიჯი 3: აუცილებელი - Windows

ზემოაღნიშნული ნაბიჯი ვარაუდობს, რომ ჩვენ ვიყენებთ Linux- ს. რა მოხდება, თუ ჩვენ ვიყენებთ Windows- ს?

შეგიძლიათ გადახვიდეთ arm Developer– ის საიტზე და გადმოტვირთვის რამდენიმე ვარიანტი არსებობს. მე ვიყენებ Windows 8 აპარატს.

ინსტალაციის დროს, მე ავირჩიე მისი ინსტალაცია პროგრამის ფაილების ნაცვლად "C: \" დისკზე მხოლოდ იმიტომ, რომ მე ასევე ვიყენებ cygwin- ს და უფრო ადვილი იყო ბმულის შექმნა ჩემი ადგილობრივი ბინდან ძირეულ C: საქაღალდეზე, ვიდრე ყველა არეულობა პროგრამის ფაილების გზაზე (სივრცეებით და ა.

ამრიგად, ჩემი ციგვინის გარემო და გზა ასე გამოიყურება:

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 debugger და მასაც ჭირდება გზა თავისი სამუშაოს შესასრულებლად, მაგრამ სხვა სისტემის დამიზნების მიზნით.

ამრიგად, gdb-arm-none-eabi არის GDB, რა gcc-arm-none-eabi არის GCC.

პაკეტის კიდევ ერთი შემოთავაზება იყო "libnewlib-arm-none-eabi". რა არის ის ერთი?

Newlib არის C ბიბლიოთეკა და მათემატიკის ბიბლიოთეკა, რომელიც განკუთვნილია ჩაშენებულ სისტემებზე გამოსაყენებლად. ეს არის ბიბლიოთეკის რამდენიმე ნაწილის კონგლომერაცია, ყველა თავისუფალი პროგრამული უზრუნველყოფის ლიცენზიით, რაც მათ ადვილად გამოსაყენებელს ხდის ჩადგმულ პროდუქტებზე.

და ბოლოს, პაკეტი "libstdc ++-arm-none-eabi". რომ ერთი საკმაოდ აშკარაა; ეს არის C ++ ბიბლიოთეკა ჯვრის შემდგენლისათვის; ჩამონტაჟებული ARM მიკროკონტროლერებისთვის.

ნაბიჯი 5: Linker ფაილი

ლინკერის ფაილი
ლინკერის ფაილი
ლინკერის ფაილი
ლინკერის ფაილი

მოდით შევქმნათ ლინკერის სკრიპტი.

ამ ფაილის ერთი ძირითადი ნაწილი ან ბლოკი იქნება MEMORY ბრძანება.

--- sourceware.org– დან:

ბმულის ნაგულისხმევი კონფიგურაცია იძლევა ყველა არსებული მეხსიერების გამოყოფას. თქვენ შეგიძლიათ გადალახოთ ეს MEMORY ბრძანების გამოყენებით. MEMORY ბრძანება აღწერს სამიზნეში მეხსიერების ბლოკების ადგილმდებარეობას და ზომას. თქვენ შეგიძლიათ გამოიყენოთ იგი იმის აღსაწერად, თუ რომელი მეხსიერების რეგიონები შეიძლება გამოყენებულ იქნეს ბმულის მიერ და რომელი მეხსიერების რეგიონებს უნდა აარიდოს თავი. ამის შემდეგ შეგიძლიათ მიანიჭოთ სექციები მეხსიერების კონკრეტულ რეგიონებს. ლინკერი დააყენებს განყოფილების მისამართებს მეხსიერების რეგიონების მიხედვით და გააფრთხილებს რეგიონების შესახებ, რომლებიც ძალიან სავსე ხდება. ლინკერი არ შეანჯღრევს მონაკვეთებს, რათა მოერგოს ხელმისაწვდომ რეგიონებს. ლინკერის სკრიპტი შეიძლება შეიცავდეს MEMORY ბრძანების ბევრ გამოყენებას, თუმცა, ყველა მეხსიერების ბლოკი განიხილება ისე, როგორც ისინი მითითებულია ერთი MEMORY ბრძანების შიგნით.:

მეხსიერება

{name [(attr)]: ORIGIN = წარმოშობა, LENGTH = len…}

მაგალითი სტატიაში:

/* განსაზღვრეთ ოპერატიული მეხსიერების დასასრული და დასტის მეხსიერების ლიმიტი* //* (4KB SRAM STM32F031x6 ხაზზე, 4096 = 0x1000)*//* (ოპერატიული მეხსიერება იწყება მისამართზე 0x20000000) _estack = 0x20001000;

მეხსიერება

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

ასე რომ, ჩვენ უნდა გავარკვიოთ რამდენი FLASH (ჩვენი პროგრამისთვის და მუდმივები და ა.შ.) და რამდენი RAM (პროგრამისთვის გამოსაყენებლად; ბევრი და დასტის და ა.შ.) ჩვენი კონკრეტული დაფისთვის. ეს ხდება ცოტათი საინტერესო.

პატარა ბარათი, რომელსაც მოყვება Nucleo, ამბობს, რომ მას აქვს ფლეშ მეხსიერება 512 კბაიტი, ხოლო SRAM არის 80 კბაიტი. ამასთან, USB– სთან დაკავშირებისას, იგი დამონტაჟებულია როგორც ფაილური სისტემა ორი ფაილით, და ორივე ფაილის მენეჯერი და GParted მიუთითებენ, რომ მას აქვს 540+ კბაიტზე მეტი ადგილი. (ოპერატიული მეხსიერება?)

მაგრამ, ორი ფაილის წაშლის მცდელობა ფაილ მენეჯერის გამოყენებით, გათიშვა და მოწყობილობის ხელახლა დაკავშირება, კვლავ აჩვენებს ორ ფაილს. (და ფაილ მენეჯერმა რაღაც აღიარა, რადგან თითოეულ ფაილზე არის პატარა "დაბლოკვის" ხატი.

მოდით წავიდეთ ფიგურებით ბარათზე. ახლა ჩვენ ვიღებთ ზემოთ მოყვანილ მაგალითს და ვაქცევთ მას ჩვენს კონკრეტულ დაფაზე.

შეიძლება დაგჭირდეთ გამოიყენოთ მსგავსი მეხსიერების ონლაინ კონვერტორი, ზოგადი KB– დან ბაიტების კონკრეტულ რაოდენობაზე გადასასვლელად.

მაშინ შეიძლება დაგჭირდეთ გამოიყენოთ ათწილადიანი ექვსკუთხედის გადამყვანი.

/ * განსაზღვრეთ ოპერატიული მეხსიერების დასრულება და დასტის მეხსიერების ლიმიტი */

/* (4KB SRAM STM32F031x6 ხაზზე, 4096 = 0x1000)* //* მაგალითი*/

/ * ნაბიჯი 1: (80KB SRAM STM32F303RE, 81920 = 0x14000) * // * ჩვენი დაფა */

/* ნაბიჯი 2, დაამატეთ ექვსკუთხა ზომა hex საწყის მისამართს (ქვემოთ). */

/ * (ოპერატიული მეხსიერება იწყება 0x20000000 მისამართზე) */

_estack = 0x20001000; / * მაგალითი */

_estack = 0x20014000; / * ჩვენი დაფა */

მეხსიერება {

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

ოპერატიული მეხსიერება (rxw): ORIGIN = 0x20000000, LENGTH = 80K

}

მოდით ვუწოდოთ ზემოაღნიშნულ ფაილს "linker.script.ld".

ნაბიჯი 6: ვექტორული ცხრილი

ვექტორული ცხრილი
ვექტორული ცხრილი

ახლა ჩვენ ვაპირებთ შევქმნათ პატარა ასამბლეის ფაილი (დირექტივებით), რომ შევასრულოთ ძალიან ძირითადი შეფერხებები. ჩვენ მივყვებით სტატიის მაგალითს და შევქმნით ფაილს სახელწოდებით "core. S".

კიდევ ერთხელ, აქ არის მაგალითი ფაილის შინაარსი, მაგრამ მე შევიტანე ცვლილება ჩვენი კონკრეტული დაფისთვის:

// ეს ინსტრუქციები განსაზღვრავს ჩვენი ჩიპის ატრიბუტებს და

// ასამბლეის ენა, რომელსაც ჩვენ გამოვიყენებთ:. სინტაქსი ერთიანი /*ქვემოთ იხილეთ ამ კოდის შემდეგ* //*.cpu cortex-m0* / /*კომენტარი გააკეთეთ მაგალითის ამ ხაზზე* /.cpu cortex-m4 /* დაამატეთ ნაცვლად ჩვენი დაფის ქერქი. იხილეთ ზემოთ მოცემული სურათი ამ ნაბიჯში * / /*.fpu softvfp * / / *კომენტარი გააკეთეთ მაგალითის ამ სტრიქონის შესახებ * /.fpu vfpv4 / *დაამატეთ ჩვენი დაფის ნაცვლად; მას აქვს FPU */.thumb // გლობალური მეხსიერების ადგილები..global vtable.global reset_handler / * * ფაქტობრივი ვექტორული ცხრილი. * მხოლოდ ოპერატიული მეხსიერების ზომა და 'გადატვირთვის' დამმუშავებელი შედის * სიმარტივისთვის. */.ტიპი vtable, %object vtable:.word _estack.word reset_handler.size vtable,.-vtable

ჰმ.. არა '. გასწორება' დირექტივა

თუმცა, ეს არ არის კრიტიკული. დაწვრილებით ამის შესახებ (შეიძლება) მოგვიანებით.

.სინტაქსი ერთიანი

.სინტაქსი [ერთიანი | გაყოფილი]

ეს დირექტივა ადგენს ინსტრუქციის ნაკრების სინტაქსს, როგორც ეს აღწერილია ARM-Instruction-Set განყოფილებაში

9.4.2.1 ინსტრუქციის ნაკრები სინტაქსი ორი ოდნავ განსხვავებული სინტაქსი არის ARM და THUMB ინსტრუქციების მხარდაჭერა. ნაგულისხმევი, გაყოფილი, იყენებს ძველ სტილს, სადაც ARM და THUMB ინსტრუქციებს ჰქონდათ საკუთარი, ცალკეული სინტაქსები. ახალი, ერთიანი სინტაქსი, რომლის შერჩევა შესაძლებელია. სინტაქსის დირექტივის საშუალებით.

.fpu vfpv4

GCC შემდგენელს შეუძლია აწარმოოს ორობები რამოდენიმე ვარიანტით მცურავ წერტილთან დაკავშირებით: რბილი - შესაფერისი CPU– ზე გასაშვებად FPU– ს გარეშე - გამოთვლები ხდება პროგრამულ უზრუნველყოფაში შემდგენლის მიერ წარმოქმნილი softfp - შესაფერისი CPU– ზე გასაშვებად FPU– ით ან მის გარეშე - გამოიყენებს FPU– ს, თუ არსებობს რა ჩვენი კონკრეტული შემთხვევისთვის (თქვენ მოგიწევთ საკუთარი კვლევის გაკეთება), ამ კონკრეტული დაფის FPU შეესაბამება vfpv4. შეიძლება დაგჭირდეს ამით თამაში. ან თუნდაც დატოვე softfp- ზე.

. thumb (წინააღმდეგ. იარაღი)

ამ ARM მიკროკონტროლერს ფაქტობრივად აქვს ინსტრუქციის ნაკრების ნაზავი. ერთი არის ARM, მეორე არის THUMB. ერთი განსხვავება არის 16-ბიტიანი ინსტრუქცია 32-ბიტიანი ინსტრუქციის წინააღმდეგ. ამრიგად, ეს დირექტივა ეუბნება შემდგენელს განიხილოს შემდგომი ინსტრუქციები როგორც THUMB ან ARM.

ჩვენ ვაპირებთ უბრალოდ მივიღოთ დარჩენილი ფაილი ისე, როგორც ეს არის, რადგან ეს Instructables ჯერ არ ჩავუღრმავებულა შეწყვეტისკენ მიმავალი ასამბლეის პროგრამირებაში.

ნაბიჯი 7: პროგრამის 'Hello World' ასამბლეის ვერსია

შემდეგი ასევე შეიძლება შევიდეს ადრე შექმნილ "core. S" ფაილში. ეს კიდევ ერთხელ არის სტატიაში მოცემული მაგალითიდან.

/ * * გადატვირთვის დამმუშავებელი. გადატვირთვაზე დარეკეს. */.ტიპი reset_handler, %ფუნქცია reset_handler: // დააყენეთ დასტის მაჩვენებელი დასტის ბოლომდე. // "_estack" მნიშვნელობა განისაზღვრება ჩვენს ლინკერის სკრიპტში. LDR r0, = _estack MOV sp, r0

// დააწესეთ რამდენიმე მნიშვნელობის მნიშვნელობა. როდესაც ჩვენ ვხედავთ ამ ღირებულებებს

// ჩვენს გამართვაში, ჩვენ ვიცით, რომ ჩვენი პროგრამა // ჩიპზეა ჩატვირთული და მუშაობს. LDR r7, = 0xDEADBEEF MOVS r0, #0 main_loop: // დაამატეთ 1 რეგისტრაცია 'r0'. ADDS r0, r0, #1 // უკან დაბრუნება. B main_loop. ზომა reset_handler,.-Reset_handler

ამრიგად, ზემოაღნიშნული პროგრამის მიზანია ცნობადი ნიმუშის ჩატვირთვა ერთ ძირითად MCU რეესტრში (ამ შემთხვევაში R7) და ნულოვანი ღირებულების გაზრდა სხვა ძირითადი MCU რეგისტრში (ამ შემთხვევაში R0). თუ ჩვენ გავდივართ შემსრულებელ კოდში, ჩვენ უნდა დავინახოთ R0– ის მონაცემების ზრდა.

თუ თქვენ მიჰყევით ინსტრუქციას MSP432- თან და TI-RSLK კურსთან/ლაბორატორიებთან დაკავშირებით, მაშინ თითქმის ყველა ზემოთ ჩამოთვლილი პროგრამა თქვენთვის ნაცნობი უნდა იყოს.

ერთადერთი რაც მე შემიძლია დავინახო არის "=" - ის გამოყენება DEADBEEF- ის ჩატვირთვისას R7 რეგისტრაციაში. ჩვენ არ გამოვიყენეთ ეს.

აქ დართული "core. S" ფაილი შეიცავს სრულ წყაროს.

ნაბიჯი 8: კოდის შედგენა

დროა გავაკეთოთ რაღაც ბრძანების სტრიქონი. რაღაც რეალური, ბოლოს და ბოლოს.

თუმცა, ჩვენ არ ვართ იქ. ჩვენ კვლავ უნდა შეცვალოთ სტატიაში მოცემული ბრძანება და შეცვალოთ იგი ჩვენს სიტუაციაში.

აქ არის მაგალითი კოდი:

arm -none -eabi -gcc -x assembler -with -cpp -c -O0 -mcpu = cortex -m0 -mthumb -Wall core. S -o core.o

თუ ჩვენ მივდივართ gnu.org საიტზე GCC– სთვის, (ამ შემთხვევაში ვერსია 7.3),

x

-X არის ენის მითითება. წინააღმდეგ შემთხვევაში თუ არა -x, მაშინ შემდგენელი შეეცდება გამოიცნოს ფაილის გაფართოების გამოყენებით. (ჩვენს შემთხვევაში, *. S).

სტატიის ზემოთ მოყვანილი მაგალითი განსაზღვრავს assembler-with-cpp, მაგრამ ჩვენ შეგვიძლია უბრალოდ გავაკეთოთ ასამბლერი.

-C ამბობს შეადგინე, მაგრამ არ დაუკავშირო.

O0

-O არის ოპტიმიზაციის დონის დადგენა. -O0 (oh -zero) გამოყენებისას ნათქვამია "შეამცირეთ შედგენის დრო და გახადეთ გამართული შეცდომები წარმოქმნას მოსალოდნელი შედეგები. ეს არის ნაგულისხმევი".

mcpu = ქერქი-m0

-Mcpu განსაზღვრავს სამიზნე პროცესორის სახელს. ჩვენს შემთხვევაში, ეს იქნება cortex-m4.

დედა

-Mthumb განსაზღვრავს შერჩევას კოდს შორის, რომელიც ასრულებს ARM და THUMB მდგომარეობას.

კედელი

რა თქმა უნდა, კედელი არის ძალიან გავრცელებული და ცნობილი. ის ჩართავს ყველა გამაფრთხილებელ დროშას.

დაბოლოს, ბრძანების ბოლოს გვაქვს შეყვანის ფაილის core. S და გამომავალი ფაილის core.o.

აქ არის ახალი ბრძანების ხაზი, რომელიც შეესაბამება ჩვენს კონკრეტულ შემთხვევას.

arm -none -eabi -gcc -x assembler -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 ()).

Semihosting ნიშნავს debugger (იხ. ნაბიჯი მე -11 სურათი, რომელშიც debugger ნაწილი შემოხაზულია წითლად) აქვს სპეციალური არხი და იყენებს semihosting პროტოკოლს, და თქვენ შეგიძლიათ ნახოთ printf () გამომავალი მასპინძელ მანქანაზე (გამართვის მეშვეობით).

მეორეს მხრივ, მიზნობრივი დანიშნულება ნიშნავს იმას, რომ იგივე სისტემის ან ბიბლიოთეკის ზარები სხვა რამეს ნიშნავს. ისინი სხვა რამეს აკეთებენ, რაც აზრი აქვს ჩამონტაჟებულ სისტემას. გარკვეული გაგებით, ვთქვათ printf () - სთვის, არის ახალი განხორციელება, ამ ფუნქციის შემდგომი განხორციელება.

ყოველივე ამის თქმის შემდეგ, --specs = nosys.specs ნიშნავს, რომ ჩვენ არ ვიქნებით ნახევრადმომხმარებელი. ეს ჩვეულებრივ ნიშნავს იმას, რომ ჩვენ ხელახლა ვაკეთებთ მიზანს. ეს მიგვიყვანს შემდეგ დროშამდე.

nostdlib

ბმულის ვარიანტი -nostdlib გამოიყენება იმ პროგრამის დასაკავშირებლად, რომელიც მიზნად ისახავს დამოუკიდებლად გაშვებას. -nostdlib გულისხმობს ინდივიდუალურ ვარიანტებს -nodefaultlibs და -nostartfiles. ქვემოთ ჩვენ განვიხილავთ ორ ვარიანტს ცალკე, მაგრამ ყველაზე ტიპიური გამოყენება არის მხოლოდ nostdlib ერთჯერადი საყიდლებისთვის. მასპინძელი პროგრამის დაკავშირებისას სტანდარტული სისტემური ბიბლიოთეკები, როგორიცაა libc, სტანდარტულად არის დაკავშირებული, რაც პროგრამას აძლევს ყველა სტანდარტულ ფუნქციას (printf, სტრლენი და მეგობრები). ბმულის ვარიანტი -nodefaultlibs გამორთავს იმ ნაგულისხმევ ბიბლიოთეკებთან კავშირს; მხოლოდ ბიბლიოთეკები არის ზუსტად ის, რასაც თქვენ აშკარად ასახელებთ ლინკერს –l დროშის გამოყენებით.

lgcc

libgcc.a არის სტანდარტული ბიბლიოთეკა, რომელიც უზრუნველყოფს შიდა ქვეპროგრამებს კონკრეტული მანქანების ნაკლოვანებების დასაძლევად. მაგალითად, ARM პროცესორი არ შეიცავს გაყოფის ინსტრუქციას. Libgcc.a– ს ARM ვერსია მოიცავს გაყოფის ფუნქციას და შემდგენელი ასხივებს ზარებს იმ ფუნქციისთვის, სადაც საჭიროა.

ეს მხოლოდ საშუალებაა ვუთხრათ შემკავშირებელს გამოიყენოს ეს ფაილი, როგორც ლინკერის სკრიპტი. ჩვენს შემთხვევაში, ფაილის სახელია linker.script.ld.

მთავრად.თავად

დაბოლოს, ჩვენ ვეუბნებით ლინკერს რა იქნება სახელი საბოლოო გამომავალი გამოსახულების ფაილზე, რომელიც დაიწვის/აანთებს ჩვენს მოწყობილობას.

აქ არის სრული ვერსია ბრძანების ხაზის, რომელიც შეცვლილია ჩვენი კონკრეტული სიტუაციისთვის:

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– თან

ტესტირება კავშირი STM32 Nucleo-64– თან
ტესტირება კავშირი STM32 Nucleo-64– თან
ტესტირება კავშირი STM32 Nucleo-64– თან
ტესტირება კავშირი STM32 Nucleo-64– თან

თქვენი პირველი მისია, თუ თქვენ აირჩევთ მის მიღებას, არის თქვენი სისტემის დანახვის თქვენი განვითარების დაფა.

Windows- ის გამოყენება

Windows– ისთვის გადავწყვიტე დავაინსტალირო TrueSTUDIO Atollic– დან (უფასო ვერსია). ეს იყო უმტკივნეულო ინსტალაცია და ავტომატურად დააყენა დრაივერი, ასე რომ მე შემეძლო გამომეყენებინა st-link კავშირის შესამოწმებლად. მას შემდეგ რაც დავაინსტალირე TrueSTUDIO და მოწყობილობის მენეჯერმა დაინახა მოწყობილობა, მე გადმოვწერე Texan/Stlink ინსტრუმენტები, რომლებიც შემოთავაზებულია შიშველი ლითონის სტატიით, რომელსაც ჩვენ ვადევნებდით თვალს. მე კვლავ მოვათავსე საქაღალდე პირდაპირ "C: \" - ის ქვეშ და კვლავ შევქმენი რამოდენიმე ბმული ჩემი ადგილობრივი cygwin ყუთიდან ბრძანებებთან.

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

როგორც საწყისი ტესტი იმის დასადგენად, ნამდვილად შეგვიძლია თუ არა მოწყობილობასთან ურთიერთობა, მე გავიქეცი:

st-info-გამოძიება

და დაბრუნდა:

ნაპოვნია 1 სტაბილური პროგრამისტი

ასე რომ, ახლა ჩვენ ვიცით, რომ ჩვენ შეგვიძლია ვისაუბროთ/ვიკითხოთ ჩვენი განვითარების დაფაზე.

Linux- ის გამოყენება

Linux– ისთვის, თქვენ ნამდვილად არ გჭირდებათ მძღოლი. მაგრამ დებიანისთვის, თქვენ უნდა ააწყოთ st ინსტრუმენტები წყაროდან.

git კლონი

დარწმუნდით, რომ დაინსტალირებული გაქვთ libusb-1.0-0-dev.

შესაფერისი სია | grep -E "*libusb.*dev*"

თქვენ უნდა ნახოთ:

libusb-1.0-0-dev/xenial, ახლა 2: 1.0.20-1 amd64 [დაინსტალირებული]

ან რაღაც მსგავსი

მისი ინსტალაციისთვის:

sudo apt-get დააინსტალირეთ libusb-1.0-0-dev

გაითვალისწინეთ, რომ ზემოაღნიშნული არ არის იგივე, რაც:

sudo apt-get დააინსტალირეთ libusb-dev

Libusb– ის გამოტოვებულმა სწორმა ნაწილმა შეიძლება გამოიწვიოს პრობლემები cmake– სთან.

CMake Error: ამ პროექტში გამოიყენება შემდეგი ცვლადები, მაგრამ ისინი მითითებულია NOTFOUND. გთხოვთ, დააყენოთ ისინი ან დარწმუნდეთ, რომ ისინი სწორად არის დაყენებული და გამოცდილი CMake ფაილებში: LIBUSB_INCLUDE_DIR (ADVANCED)

შეცვალეთ პროექტის ძირეული დირექტორია (… blah /blah /stlink). გააკეთე "გაათავისუფლე".

მას შემდეგ რაც აშენდება, ინსტრუმენტები უნდა იყოს ".. /build /Release".

ამის შემდეგ შეგიძლიათ გაუშვათ "st-info-probbe". აქ არის გამომავალი Nucleo დაკავშირებული, მაშინ არა.

devchu@chubox: ~/Development/stlink $./build/Release/st-info --probe აღმოაჩინეს 1 stlink პროგრამისტი სერიული: 303636414646353034393535363537 openocd: "\ x30 / x36 / x36 / x41 / x46 / x46 / x35 / x30 / x30 / x34 / x39 / x35 / x35 / x36 / x35 / x37 "ფლეშ: 524288 (გვერდის ზომა: 2048) sram: 65536 chipid: 0x0446 descr: F303 მაღალი სიმკვრივის მოწყობილობა devchu@chubox: ~/Development/stlink $./build/Release/st- ინფორმაცია -გამოძიება ნაპოვნია 0 stlink პროგრამისტი devchu@chubox: ~/განვითარება/stlink $

ნაბიჯი 11: მოდით გამოვიყენოთ GDB Linux– ით

მოდით გამოვიყენოთ GDB Linux– ით
მოდით გამოვიყენოთ GDB Linux– ით
მოდით გამოვიყენოთ GDB Linux– ით
მოდით გამოვიყენოთ GDB Linux– ით

თუ თქვენ ცდილობდით ამ ყველაფერს და მიაღწიეთ აქამდე - მშვენიერია! შესანიშნავია. მოდი ახლა ცოტა გავხალისდეთ.

როდესაც ყიდულობთ ARM– ის განვითარების დაფებს, იქნება ეს MSP432 Launchpad Texas Instruments– დან, თუ ეს ჩვენ ახლა განვიხილავთ, Nucleo-F303 (STM32 Nucleo-64), ისინი ჩვეულებრივ ჩამოდიან უკვე გაშლილი პროგრამით, როგორც წესი ზოგიერთი მოციმციმე პროგრამა, რომელიც ასევე მოიცავს გადამრთველის დაჭერას LED (ებ) ის ციმციმის სიჩქარის შესაცვლელად.

სანამ ჩვენ ასე სწრაფად ვწერთ ამას, მოდით ვნახოთ რა არის სანახავი და გასაკეთებელი.

Linux– ით გახსენით ტერმინალი, შეცვალეთ დირექტორია stlink git პროექტი, რომელიც ახლახან ავაშენეთ და იპოვეთ st-util ინსტრუმენტი.

devchu@chubox: ~/განვითარება/stlink $ find. -სახელი st-util

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

გაუშვით ეს ინსტრუმენტი. ვინაიდან ჩვენ უკვე გამოვცადეთ ჩვენი კავშირი st-info-ზონთან, ჩვენ უნდა მივიღოთ გამომავალი ასეთი:

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

st-util 1.4.0-50-g7fafee2 2018-10-20T18: 33: 23 ინფორმაცია საერთო. 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 INFO gdb-server.c: ჩიპის ID არის 00000446, ძირითადი ID არის 2ba01477. 2018-10-20T18: 33: 23 ინფორმაცია 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 in ?? ()

იმავდროულად, ტერმინალში, რომელიც მუშაობს st-util gdbserver, მივიღეთ ეს:

2018-10-20T18: 42: 30 ინფორმაცია gdb-server.c: ნაპოვნია 6 hw breakpoint რეგისტრი

2018-10-20T18: 42: 30 ინფორმაცია 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) და ჩვენ მზად ვართ დავახუროთ შესრულებადი. ძალიან კლიმატური საწინააღმდეგოა:

(გდბ) დატვირთვა

Cygwin ტერმინალებით გაშვებული, არის ცნობილი პრობლემა, როდესაც კონსოლის ბრძანებები არ გამოდის. ჩვენს შემთხვევაში, სერვერის გაშვებული ფანჯარა სრულიად ჩუმად იყო. ის, ვინც აწარმოებს კლიენტს, სადაც ჩვენ ვტვირთავდით დატვირთვას, გამოაქვს ეს:

ჩატვირთვის განყოფილება.ტექსტი, ზომა 0x1c lma 0x8000000 საწყისი მისამართი 0x8000000, დატვირთვის ზომა 28 გადაცემის სიჩქარე: 1 კბ/წმ, 28 ბაიტი/ჩაწერა.

ნაბიჯი 13: Flashing Linux– ით - მეტი ჯილდო: D

Flashing ერთად Linux - მეტი დაჯილდოვება: D
Flashing ერთად Linux - მეტი დაჯილდოვება: D

ნაბიჯი 14: მოდით ჩავყვინთოთ ცოტა უფრო ღრმად

თუ აქ მოხვედი, შესანიშნავია. მოდით გადავიდეთ.

რატომ არ უნდა გამოიყურებოდეს main.elf ფაილის შიგნით, შემსრულებელი? გაუშვით შემდეგი:

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

თქვენ უნდა ნახოთ ასეთი გამომავალი:

main.elf: ფაილის ფორმატი elf32-littlearm

მონაკვეთის დაშლა.ტექსტი:

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 მეხსიერებაშია.

შემდეგ, ზემოთ, მაგრამ მოგვიანებით, როდესაც ჩვენ ვისაუბრეთ "გამარჯობა მსოფლიო" ნაწილზე, იყო განცხადება, სადაც ჩვენ ჩავტვირთავთ დაუყოვნებლივ, მუდმივ, პირდაპირი მნიშვნელობას ("0xDEADBEEF") MCU ძირითად რეგისტრში ("R7").

განცხადება იყო:

LDR R7, = 0xDEADBEEF

ჩვენს კოდში, ეს არის ერთადერთი ადგილი, სადაც ჩვენ აღვნიშნავთ DEADBEEF- ს. Სხვაგან არსად. და მაინც, თუ გადახედავთ ზემოაღნიშნულ დაშლილ/რეკონსტრუქციულ ინსტრუქციებს და ა.შ., DEADBEEF– თან უფრო მეტია, ვიდრე გვეგონა.

ამრიგად, შემდგენელმა/შემმაერთებელმა რატომღაც გადაწყვიტა, რომ სამუდამოდ დაეხატა DEADBEEF- ის მნიშვნელობა FLASH მისამართზე, 0x8000018 ადგილას. შემდეგ, შემდგენელმა შეცვალა ჩვენი ზემოთ LDR ინსტრუქცია, რომ იყოს:

LDR R7, [კომპიუტერი, #8]

ჩვენთვის კომენტარიც კი გამოიწვია. Რა კარგია. და ის გვეუბნება, რომ ავიღოთ პროგრამის მიმდინარე მრიცხველი (კომპიუტერის რეგისტრი), დავამატოთ 0x8 ამ მნიშვნელობას და ეს არის ადგილი, სადაც DEADBEEF დაიწვა, და მივიღოთ ეს მნიშვნელობა და ჩავსვათ R7- ში.

ეს იმას ნიშნავს, რომ პროგრამის მრიცხველი (კომპიუტერი) მიუთითებდა მისამართზე 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 0xfffff800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010020002000200020002000979792000797979200079700700002000200020007295700500002000979002000

მაგრამ შემდეგ, (gdb) მოთხოვნით, შეიყვანეთ:

(გდბ) გააგრძელე

და ძალიან სწრაფად მოხვდა CTRL-C. ამან უნდა შეაჩეროს პროგრამა. კვლავ შეიყვანეთ ბრძანება "ინფორმაციის რეგისტრაცია".

ამჯერად ის სხვანაირად გამოიყურება:

(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 rff 0x00 000000000000000000000000000000000000000000000000000000000000000000 16777216

Რა მოხდა? ზუსტად ის, რაც გვინდოდა. DEADBEEF დატვირთულია R7– ში და R0 იზრდება (უკიდურესად სწრაფად) იზრდება. თუ გაიმეორებთ, თქვენ დაინახავთ R0- ს სხვა მნიშვნელობით.

ნაბიჯი 16: ჩვენ გვინდოდა შევქმნათ მხოლოდ წაკითხული მასივი Flash- ში

მასივის ექვივალენტის შესაქმნელად ერთ -ერთი გზა ასამბლეისა და დირექტივების გამოყენებით არის შემდეგი:

.ტიპი myarray, %object // სახელი ან ეტიკეტი 'myarray' განისაზღვრება, როგორც ობიექტის ტიპი.

myarray: // ეს არის დასაწყისი დეკლარაციის "myarray" // (რისგან შედგება იგი).. სიტყვა 0x11111111 // პირველი წევრი ან მნიშვნელობა, რომელიც შეიცავს "მიარას".. სიტყვა 0x22222222 // მეორე მნიშვნელობა (მომიჯნავე მისამართები).. სიტყვა 0x33333333 // და ასე შემდეგ..size myarray.

ახლა, როდესაც ჩვენ დავაყენეთ იგი FLASH მეხსიერებაში, შეგვიძლია გამოვიყენოთ პროგრამაში. ქვემოთ მოცემულია ნაწილი:

LDR R1, myarray // ეს იტვირთება "myarray" - ის 1 -ლი ადგილის მონაცემებზე. " // ეს არ არის ის, რაც ჩვენ გვინდა.

LDR R1, = myarray // ეს იტვირთება ადგილმდებარეობის მნიშვნელობა (პირველი მისამართი), // არა მონაცემები.. // ეს არის ის, რაც ჩვენ გვინდა.

MOV R2, #0 // R2 შეინარჩუნებს დათვლას, რათა დავრწმუნდეთ, რომ არ გავდივართ

// მასივის დასასრული. LDR R3, = myarrsize // R3 იქნება "myarrsize" - ის ექვივალენტი.

// R0 დაიცავს ჩვენს მონაცემებს

main_loop:

LDR R0, [R1] // ჩატვირთეთ R1 ('myarray') მითითებული მონაცემები R0- ში. CMP R2, R3 // ვართ მასივის ლიმიტზე? BEQ main_loop // თუ ჩვენ ვართ, ჩვენ დავამთავრეთ, ასე რომ ჩვენ უბრალოდ მარყუჟს შევუდგებით სამუდამოდ.

ADD R2, #1 // წინააღმდეგ შემთხვევაში, ჩვენ შეგვიძლია განვაგრძოთ გამეორება მასივის საშუალებით.

ADD R1, #4 // დაამატეთ 4 R1 რეგისტრაციისთვის, ასე რომ ის სწორად მიუთითებს შემდეგზე

// მისამართი..

B main_loop // უკან დაბრუნება.

ვიდეო გადის ამ ყველაფერს და მასში არის ხარვეზი. Კარგია; ეს აჩვენებს, რომ მნიშვნელოვანია გაშვებული და გამართული კოდი. ის აჩვენებს მასივის ბოლოდან გასვლის კლასიკურ შემთხვევას.

გირჩევთ: