Beruflich Dokumente
Kultur Dokumente
Embedded
Programmer
JorgeAparicio'sblogonElectronics,Roboticsandmore...
Thursday,September13,2012
STM32F4DISCOVERYDevelopmentwithGCCinEclipse
First of all, I want to thank the OpenOCD Project for its latest release of OpenOCD. Thanks to
this release, its possible to get a working development environment for the
STM32F4DISCOVERYrelativelyfast.
This Development Environment can also be used for other STM32 / Cortex M microcontrollers
and development boards. I have tested this Development Environment with the
STM32VLDISCOVERY,STM32F4DISCOVERYandF4Dev.
For now this post is Ubuntu specific. Setting the Development Enviroment on other platforms
shouldbefairlysimilar.
embeddedprogrammer.blogspot.it/2012/09/stm32f4discovery-development-with-gcc.html
1/23
18/12/13
DonotusetheGUIarchivemanager
Usethefollowingcommandinstead:
tarjxfgccarmnoneeabi4_62012q220120614.tar.bz2
Let'saddtheGCCbinariesfoldertothePATHenvironmentvariable,foreasieruse.
gedit$HOME/.profile
Appendtothisfilethefollowinglines:
1
2
3
if[d"<pathtogccdirectory>/gccarmnoneeabi<gccversi?
on>/bin"
PATH="<pathtogccdirectory>/gccarmnoneeabi<gccversion>/bin:$PATH"
fi
DoasoftreboottoupdatethePATHvariable.
Thebinariesshouldbeaccessiblefromthecommandline,let'scheck.
armnoneeabigccversion
Youshouldseeanoutputsimilartothefollowinglines:
Ifinsteadyougetthefollowingerrorandyouareusinga64bitUbuntu/LinuxOS:
Itmeansyouaremissingsome32bitlibraries.Theeasiestwaytosolvethisistoinstallallthe
32bitlibrariesusingthefollowingcommand:
sudoaptgetinstallia32libs
embeddedprogrammer.blogspot.it/2012/09/stm32f4discovery-development-with-gcc.html
2/23
18/12/13
Nowtestagainthearmnoneeabigcccommandanditshouldwork.
That'sitfortheGCCdependency.
Dependency:EclipseCDT
You'll need Eclipse C/C++ Development Tooling. I recommend using Eclipse Indigo instead of
EclipseJuno,becausethereisabugwiththecontentassistwhenusingnamespaces.
Grab the correct package from here. (If you still want to use the Juno version, get the package
fromhere)
Untar/unzipthetarball/zipfile,andyouaredone.
Windows
Ifyoudon'thaveJavainstalled,headtothislink.Grabthecorrectinstaller(x86orAMD64),then
followtheinstallationsteps.
AfterinstallingJava,Eclipseshouldwork.
Dependency:GNUARMPlugin
Withthisplugin,EclipsewillbeabletodetecttheARMGCC.
InEclipse,goto(Help>InstallNewSoftware).
Onthisnewwindow,clicktheaddbutton,andinsertthefollowingtext.
http://gnuarmeclipse.sourceforge.net/updates
Click OK and a component named "CDT GNU Cross Development Tools" will appear, check it,
thenclicktheNextbuttonandfollowingtheinstallationinstructions.
You'llbepromptedtoresetEclipse,doso.
You'redonewiththisplugin.
embeddedprogrammer.blogspot.it/2012/09/stm32f4discovery-development-with-gcc.html
3/23
18/12/13
Dependency:ZylinEmbeddedCDTPlugin
ThispluginisnecessarytoflashanddebugwithinEclipse.
InEclipse,goto(Help>InstallNewSoftware).
Onthisnewwindow,clicktheaddbutton,andinsertthefollowingtext.
http://opensource.zylin.com/zylincdt
Click OK and a component named "Zylin Embedded CDT" will appear, check it, then click the
Nextbuttonandfollowingtheinstallationinstructions.
You'llbepromptedtoresetEclipse,doso.
You'redonewiththisplugin.
Dependency:OpenOCD
Withthissoftware,yourPCwillbeabletoflashanddebugSTM32targetsviaaUSB<>JTAG
interface.
Windows
Grabthezipfromhere.Unzipthefile.CopytheuncompressedfolderinyourCdrive.
Append "C:\openocd0.6.1\bin" or "C:\openocd0.6.1\binx64" to your PATH variable. See
thispostifyoudon'tknowhowtoeditthePATHenvironmentvariable.
Linux
Grabtheversion0.6.0tarballfromhere.
Untarthetarball.
Usethefollowinginstallationcommands:
embeddedprogrammer.blogspot.it/2012/09/stm32f4discovery-development-with-gcc.html
4/23
18/12/13
sudoaptgetinstalllibftdidev
cd<pathtotheuntaredopenocdtarball>
./configureenableft2232_libftdienablestlink
make
sudomakeinstall
You'redonewiththeOpenOCDinstallation.
Git(Windows)
If you don't have Git installed. Grab the installer from here. Follow the installations steps, but
choosethe"RunGitfromtheWindowsCommandPrompt"insteadofthedefaultoption.
Make(Windows)
Windows doesn't come with a "make" tool by default. The easiest way to get "make" is
downloadingthisMinGW(**).ThenunzipthedownloadedziparchiveinyourCdrive.
(**)Thetrolltechftpserverhasbeenshutdown,luckilyShaoLinhaspostedamirroronhisGoogle
Drive,checkhispostforinformationonhowtodownloadMinGW.
And append "C:\mingw\bin" to your PATH variable. See this post if you don't know how to edit
thePATHenvironmentvariable.
TheEclipseProjectTemplate
GrabtheEclipseprojecttemplateIhavedeveloped:bareCortexM
cd#choosesomedirectory
gitclonehttps://github.com/JorgeAparicio/bareCortexM.git
ImportingtheEclipseProject
InEclipse,goto(File>Import).
Inthiswindow,select(General>ExistingProjectintoWorkspace).
embeddedprogrammer.blogspot.it/2012/09/stm32f4discovery-development-with-gcc.html
5/23
18/12/13
Inthisnewwindow,clicktheBrowsebuttonnexttothe"Selectrootdirectory"boxandselectthe
bareCortexMfolder.
Inthisproject,gotothe"src"folderandopenthe"main.cpp"file.Youshouldseeasinglefunction
namedintmain().
FromtheEclipsemenuselect(Project>Properties).
Inthiswindows,selecttheC/C++Build.
ClicktheManageConfigurationbuttonnexttotheConfigurationcombobox.
SelectyourplatformandclicktheSetActivebutton.(BydefaulttheLinuxplatformisselected).
embeddedprogrammer.blogspot.it/2012/09/stm32f4discovery-development-with-gcc.html
6/23
18/12/13
** Windows: Edit the (Eclipse > Project > Properties > C/C++ Build > Build command) to
"mingw32make"orwhatevermakeyouareusing.
Now try building the project, if you correctly followed the previous steps the build should be
successful.
Configuringtheprojectforyourtarget
Before flashing your target (in this case the STM32F4DISCOVERY) it's necessary to configure
theprojectforyourspecifictarget.
LinkerScriptselection
Thelinkerscriptcontainsthememorymapofyourtargetdevice.
IntheEclipsemenu,goto(Project>Properties).
NowselectC/C++(Build>Settings).
Select(ARMSourceryGCCC++Linker>General).
ModifythefileintheScriptFiletextbox,tomatchyourtargetdevice.
embeddedprogrammer.blogspot.it/2012/09/stm32f4discovery-development-with-gcc.html
7/23
18/12/13
Youcanseethelistofsupporteddevicesinthelinkerfolder.
OpenOCDinterface/targetconfiguration
You'llneedtotellOpenOCDwhichinterfaceandtargetyouplantouse.
IntheEclipsemenu,(Run>ExternalTools>ExternalToolConfigurations).
Inthisnewwindow,select(Program>OpenOCD).
On the Main tab, make sure the OpenOCD location is correct. Then modify the arguments as
necessary.
embeddedprogrammer.blogspot.it/2012/09/stm32f4discovery-development-with-gcc.html
8/23
18/12/13
modificare la riga:
/usr/local/bin/openocd
in
/usr/bin/openocd
Thefirstargumenttomodifyistheinterface:"fopenocd/interface/<yourinterface>.cfg".Youcan
seethelistofsupportedinterfacesinthe(openocd>interface)folder.
Thesecondargumenttomodifyisthetarget:"fopenocd/target/<yourtarget>.cfg".Youcansee
thelistofsupportedtargetsinthe(openocd>target)folder.
embeddedprogrammer.blogspot.it/2012/09/stm32f4discovery-development-with-gcc.html
9/23
18/12/13
GDBscriptselection
TheGDBscriptcontainstheflashanddebuginformation.
IntheEclipsemenu,goto(Run>DebugConfigurations).
Inthisnewwindow,select(ZylinEmbeddeddebug(Native)>FlashandDebug).
On the Debugger tab, you'll need to select an appropriate GDB script in the GDB command file
textbox.
Youcanseethelistofsupporteddevicesinthegdbfolder.
embeddedprogrammer.blogspot.it/2012/09/stm32f4discovery-development-with-gcc.html
10/23
18/12/13
Configurationtable
Board
Linker
Script
(.ld)
Interface
(.cfg)
Target
(.cfg)
GDBScript
(.script)
stm32f407ve
ujtag
stm32f4x
stm32f407ve
: Flash protection must be disabled (probably using other JTAG dongle) before using this
configuration.
:Youcanuseotherscriptslike:stm32f4_16kb,stm32f4_32kb,etc.forfasterflashing.
Thefirstprogram
Let'sflashyourfirstprogramintotheSTM32F4DISCOVERY.
Copythefollowingcodeinthemain.cppsourcefile.
1
2
3
4
5
6
7
8
9
intfoo=0
intmain()
{
while(true){
foo++
}
}
Buildtheprogram,andthenclicktheOpenOCDactionintheExternalToolmenu(Thegreenplay
embeddedprogrammer.blogspot.it/2012/09/stm32f4discovery-development-with-gcc.html
11/23
18/12/13
+redtoolboxicon)orgoto(Menu>Run>ExternalTools>OpenOCD).
And...
Whatthe...?
IfyouareaLinuxuser,you'llprobablybumpintothaterror.You'llneedtogivepermissiontoyour
interfacedevice,thiswayanonrootedEclipsewillbeabletoflashanddebugthetargetdevice.
USBPermissions/Drivers
Windows(forFTDIdevices)
Grab the libusbwin32 library. Unzip the downloaded zip archive in your C drive. Enter in the
uncompressedfolder,thenenterintothebinfolderandexecutetheinfwizard.
Followtheinstructions,selecttherightdevice("SingleRS232HS"orsimilar)fromthelist.Save
the.inffileanywhereandfinallyselectInstallNow.
Linux
Tograntpermissiontoyourinterfacedeviceyou'llhavecreateafileusingthefollowingcommand.
gksudogedit/etc/udev/rules.d/33openocd.rules
(Youcanchooseanyothernumber,insteadof33)
Inthisnewfileyou'llneedtoaddthefollowingtext:
1
2
3
4
5
6
7
8
9
10
11
12
13
?
#FT232
ATTRS{idProduct}=="6014",ATTRS{idVendor}=="0403",MODE="666"
#FT2232
ATTRS{idProduct}=="6010",ATTRS{idVendor}=="0403",MODE="666"
#FT230X
ATTRS{idProduct}=="6015",ATTRS{idVendor}=="0403",MODE="666"
#STLINKV1
ATTRS{idProduct}=="3744",ATTRS{idVendor}=="0483",MODE="666"
#STLINKV2
embeddedprogrammer.blogspot.it/2012/09/stm32f4discovery-development-with-gcc.html
12/23
18/12/13
14
ATTRS{idProduct}=="3748",ATTRS{idVendor}=="0483",MODE="666"
This will give permission to all the FTDI based JTAGdongles and to the STLINK v2 JTAG
interfacepresentintheSTM32F4DISCOVERY.
If you are using or planning to use the STM32VLDISCOVERY, then you need these additional
steps:
gksudogedit/etc/modprobe.d/stlink_v1.conf
Insidethatnewfile,insertthefollowingtext:
1
optionsusbstoragequirks=483:3744:i
NOTE:Currently,STLINKv1viaOpenOCDcan'tmodifythetargetdeviceflashprotection.This
means,thatifyourSTM32VLDISCOVERYhasitsflashprotectionenabled,youwon'tbeableto
flashit.Ontheotherhand,ifyoumanagetodisabletheflashprotectionusingotherJTAGdongle,
then you'll be able to use the STLINK v1 connection. OpenOCD will probably provide better
supportforSTLINKv1inthefuture.
Arebootisnecessarytoupdatethelastchanges.
Afterthat,thepermissionproblemshouldbefixed.
Backtothefirstprogram
Asbefore,launchOpenOCD.Youshouldgetthefollowingoutputthistime.
That X breakpoints and Y watchpoints is the equivalent of success. Now that you have
established a link between your PC and the microcontroller, you can begin the flash and debug
session.
ClicktheFlashandDebugactionintheDebugmenu(thegreenbugicon).Theflashingprocess
will start, and it will take a while... around 20s (if you using a device with big flash memory,
otherwiseit'sfaster).
embeddedprogrammer.blogspot.it/2012/09/stm32f4discovery-development-with-gcc.html
13/23
18/12/13
NOTE:Actuallyflashingyourprogramisquitefast,sinceisprobablyaround200300bytes,what
takessomuchtimeiserasingtheoldmemory.Thewholeflashmemorygeterasedbeforewriting
the new program. You can achieve faster flashing times if you only "use" a fraction of the
memory,whenusingscriptslikestm32f4_16kb,stm32f4_32kb,etc.
After the flashing is over, you'll go into the debug session. You'll be prompted if you want to
changetotheDebugperspective,answeryes.
Debugging101
Let'sdosomedebuggingnow.First,let'sexaminethisnewperspective.
In the top left window, you'll see Debug window. Inside this window you'll see Thread 1, this is
theprogramthat'scurrentlyrunning,noticethatitsayssuspended,thismeansthattheARMcore
is halted. Also, below Thread 1 you can see the stack of functions called, right now it says the
programisat0x00000000,thisisbecausetheJTAGinterfacehasn'taskedforinformationyet.
Also in the debug window you can see some buttons, that I have labelled from 1 to 7. Now I'll
coverwhattheydo:
Button
Resume(F8)
Leavesthesuspendedstatus.
Suspend
Haltstheprogramexecution.
Terminate(Ctrl+
F2)
Stepinto(F5)
Goes(ifpossible)intothecurrentsubroutine.
Stepover(F6)
Executesthecurrentlineofcodeandmovesontothe
next.
Stepreturn(F7)
Description
Finishestheprogram.
Leavesthecurrentsubroutine.
Ok,nowhittheResumebuttonandthenclicktheSuspendbutton.You'llendinastatesimilarto
thefollowingimage.
embeddedprogrammer.blogspot.it/2012/09/stm32f4discovery-development-with-gcc.html
14/23
18/12/13
You can see that the middle left window changed, and now is showing the main.cpp file. Also,
there is a highlighted line, this is where the halted program currently is. You can also see the
disassemblyofthecurrentprograminthemiddlerightwindow,ifyoucan't,thenyoucanenable
thedisassemblyfrom(Menu>Window>ShowView>Disassembly).
NOTE: Read this note if your program ends in the defaultExceptionHandler() function instead.
This is a common error (bug?) that appears when you are using STLINK connections (in the
STM32VLDISCOVERY or STM32F4DISCOVERY). In this case, terminate (red square button)
the debug session and the OpenOCD connection. And then do the build > launch OpenOCD >
startdebugsessionprocessagain.
Let's watch some variables now, select the Variables tab of the top right window and right click
theemptyspace,thenclickonAddGlobalVariables.
CheckthefoovariableandthenclickOK.Youcannowwatchthevalueoffoo.Tryresumingthe
programforawhileandthensuspenditagain.Youshouldseeanoticeableincrementinthevalue
offoo.
Now,let'sseehowbreakpointswork.Rightclicktheline27(itdoesn'tmatterifyoucan'tseethe
embeddedprogrammer.blogspot.it/2012/09/stm32f4discovery-development-with-gcc.html
15/23
18/12/13
linenumber)andselectToggleBreakpoint.NowhittheResumebutton.
Theprogramwillstopassoonasitreachesthebreakpoint,you'llnoticethatfoo'svalueincreased
inone.
Let's terminate the program (Flash and Debug) and then terminate the OpenOCD session and
jumpintosomethingmoreinteresting.
BlinkingaLED
bareCortexM is a barebone project template, you'll need a peripheral library to do more than just
numericaloperations.Thisiswherelibstm32ppcomesin.
Addingthelibstm32pplibrarytotheproject
Let'splacethelibstm32ppprojectinsidethebareCortexMproject.
cd<pathtobareCortexM>
gitclonehttps://github.com/JorgeAparicio/libstm32pp.git
Gobacktoeclipse,andrightclicktheprojectname(bareCortexM)andselecttheRefreshaction.
Youshouldseethelibstm32ppfolderinsidetheproject.
embeddedprogrammer.blogspot.it/2012/09/stm32f4discovery-development-with-gcc.html
16/23
18/12/13
Now,you'llneedtoaddthelibrarytotheincludepath.
InEclipsemenu,goto(Project>Properties).
Goto(C/C++General>PathsandSymbol).
IntheIncludestab,selecttheGNUC++inlanguagesandthenclicktheAddbutton.
Inthisnewwindow,clicktheWorkspacebuttonandselectthe(libstm32pp>include)folder.
Configuringthelibrary
You'llneedtoconfigurethelibrarytomatchyourtarget,headtothe(libstm32pp>include)folder
and open the device_select.hpp. There you can select your target's family by commenting and
uncommentingthedefinesinthatfile.
embeddedprogrammer.blogspot.it/2012/09/stm32f4discovery-development-with-gcc.html
17/23
18/12/13
Usingthelibrary
Go into the (libstm32pp > demo) folder and open the gpio_pin.hpp file. Copy the content to your
main.cpp file. You can change the LED pin from PA0 to any other pin you wish. For the
STM32F4DISCOVERY you can select PD12, PD13, PD14 or PD15 to use the user LEDs
availableintheboard.FortheSTM32VLDISCOVERYusethePC8andPC9instead.
Afterthat,build,launchOpenOCDandstartthedebuggingsession.
ConfiguringtheClock
Ifyouwanttoconfigureyourdeviceclockheadtothe(libstm32pp>include)folderandopenthe
embeddedprogrammer.blogspot.it/2012/09/stm32f4discovery-development-with-gcc.html
18/23
18/12/13
The clock will be configured when you call the function clk::initialize(). You should call this
function as earlier as possible in your main function. If you are using any of the external
crystals/oscillators (HSE or LSE) then you'll need to define the functions: clk::hseFailureHandler
and clk::lseFailureHandler. These functions will be called in case the external oscillators doesn't
stabilizeinsometimeasdictatedbyHSE_TIMEOUTandLSE_TIMEOUT.
TheSTM32microcontrollersusevariousbuses(AHB,APB)tomovedatabetweentheprocessor
andtheperipherals.Thesebusesdefinetheoperatingfrequencyofvariousperipheralsandthese
busescanbeclockedatdifferentfrequencies.Allthisconfigurationiscarriedintheclock.hppfile,
youcancheckthefinalfrequenciesusingthecPrintstatement:
The cPrints statement prints its argument as an error. In the above image I used the cPrint
statementtoprintthevalueofclk::AHBwhichtheworkingAHBfrequency.YoucanusecPrintto
print other compile time known values, as cPrint creates an error, be sure to remove it or
commentitafterusingit.
embeddedprogrammer.blogspot.it/2012/09/stm32f4discovery-development-with-gcc.html
19/23
18/12/13
NOTE: As far as I know, the STM32F4 devices from the revision "A" can't use the ART
accelerator (see the errata sheet here), for these devices the LATENCY parameter is important
whenconfiguringtheclock.Frommyobservationsthefollowinglatenciesworkwell:
ClockFrequency
LATENCY
(AHB)
Comment
Upto42MHz
Zero
SolidRockStable.
From42Mhzto84
MHz
One
Seemsstable.
168MHz
Three
SomeWTFswhenusinginterruptsand
enablingoptimization.
NOTE: 84 MHz and latency one SHOULD be equivalent to 42 MHz, since the uC will execute
oneinstructionandwaitonecyclebeforeexecutingthenextinstruction.However,whenyoutake
inconsiderationthatinstructionscantakemorethanonecycle(e.g.FPUoperations)andprogram
jumps(duetofunctionsandinterrupts),calculatingthe"real"operatingfrequencygetsreallyhard.
My recommendation: Stick to 42 MHz max with zero latency while developing your application.
After everything works fine, try increasing the clock and try different values for the latency until
yougetsomethingstable.ThencheckifyouareactuallygettingbetterperformanceontheAHB
busperipherals.
Handlinginterrupts
The most important feature in every microcontroller are the interrupts. With these interrupts the
microcontrollercanhandlevariousinternal/externaleventsastheycomeby.
To enable interrupts you'll need to map the interrupt handlers in memory. I've already done this
job,soyouonlyneedtoinclude"interrupt_cpp.hpp"fileinthe"interrupts.cpp"sourcefile(thisisin
thesrcfolder).
Let'stryademonow,gotothe(libstm32pp>demo)folderandopenthetim_blink_led.hppfile,or
if you are using a STM32F4DISCOVERY go to (libstm32pp > demo > f4discovery) folder and
opentheled_wheel.hppfile.Copythecontentofthefiletomain.cpp.
In the tim_blink_led demo you might want to change the LED from PA0 to some other pin. In
either demo you can change the LED blink frequency by changing the configurePeriodicInterrupt
functionargument.
embeddedprogrammer.blogspot.it/2012/09/stm32f4discovery-development-with-gcc.html
20/23
18/12/13
Build,launchOpenOCDandstartthedebuggingsession.
LEDWheeldemo@16Hz
New,deleteandprintf
Since you're developing in C++, it's possible to use the operators new, delete and input/output
functionslikeprintf.Youcanalsousethecoutfunction,butittakestoomuchflashmemory,so
I'llrecommendusingprintfinstead.
Toenablethesefunctions,you'llneedtodefinethesystemcalls.Thesystemcallsarehardware
dependant standard functions like read, write, close, start, exit, sbrk, etc. libstm32pp provides a
minimalimplementation,whichisenoughtousethenew,deleteandprintffunctions.
To enable the system calls, you'll need to include the "system_call_cpp.hpp" file in the
"system_call.cpp"sourcefile(locatedinthesrcfolder).
Alsoyou'llneedtoenablethestartuplibraries.
InEclipse,goto(Menu>Project>Properties).
Goto(C/C++Build>Settings).
IntheToolSettingstab,goto(ARMSourceryGCCC++Linker>General).
Uncheckthe"Nostartupordefaultlibraries".
embeddedprogrammer.blogspot.it/2012/09/stm32f4discovery-development-with-gcc.html
21/23
18/12/13
newdemo
Let's do a quick demo about the new operator. Write in your main.cpp source file the following
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#defineSIZE10
int*foo
intmain()
{
foo=newint[SIZE]
for(inti=0i<SIZEi++)
foo[i]=0
while(true){
for(inti=0i<SIZEi++)
foo[i]++
}
}
Build,runOpenOCDandstartadebuggingsessionasusual.
Thefirstthingyou'llnoticeisthatthissmallprogramtakesaround90KBofflash.That'stheprice
to pay for using dynamically allocated memory. If you watch the foo variable after running the
program for some time, you'll notice that the pointer has a value around 0x20000000, this is the
addressthatthenewoperatorassigneditandalsoyoucanseethevaluestoredinthataddress,
whichwouldbethefirstelementofthearray.
printfdemo
There is a printf demo in the (libstm32pp > demo) folder. You can use printf with any of the 6
embeddedprogrammer.blogspot.it/2012/09/stm32f4discovery-development-with-gcc.html
22/23
18/12/13
UARTmodules,whichneedstobespecifiedinthesystem_call.hppfile(thisisinthe(libstm32pp
>include)folder).You'llalsoneedaUSB<>UARTconvertertogettheUARToutputintoyour
PC.InyourPC,you'llneedaserialportterminalemulatorlikeminicomorqSerialTerm.
Optimization
Finally,let'scoverhowtodooptimization.
Ineclipse,goto(Menu>Project>Properties).
Goto(C/C++Build>Settings).
IntheToolSettingstab,goto(ARMGCCC++Compiler>Optimization).
SelectintheOptimizationLevel,theoptionthatfitsyourneed.
Myrecommendation:Whendevelopinganapplication,Irecommendworkingwiththeoptimization
turned off and turning it on after you have finished developing. This is because the optimization
willcomplicatethedebuggingprocess,asthecompilerwilloptimizeoutsomevariablesandalso
somebreakpointsmightmisbehave.
embeddedprogrammer.blogspot.it/2012/09/stm32f4discovery-development-with-gcc.html
23/23