Wednesday, June 8, 2016

DIY Aviation Altimeter with QNH setting

Aviation use altimeters are extremely sensitive mechanical devices which use a bellows to convert pressure to displacement, and then use a clockwork mechanism to convert the displacement to dial position on the display. Since the overall displacement is quite small (a few millimeters of bellows compression for the ~20,000 ft. altitude range of the device, the mechanism must be fairly complex, precise and maintained periodically. Accurate and sensitive MEMS pressure sensors have been available since around 2005, which are a perfect replacement for the mechanical altimeters. However the early versions were analog (simple Wheatstone bridges) which meant that they were susceptible to drifts, required temperature compensation and fairly complex electronics to read the output voltage with sufficient precision to allow use as an aviation altimeter. 

DIY altimeter.


Technology to the rescue, recently these problems were solved with tiny pressure sensors which include temperature compensation, low drift, and high precision analog digital converters on-board. Simple communication protocol is sufficient to interface with them, and it is only a matter of following the datasheet to implement up to 24 bit pressure and temperature readout. Quite incredible, where the tecnology has come!

One such notable pressure sensor is Measurement Specialities MS5611 series. They have 24 bit precision and high accuracy, with factory calibrated coefficients permanently stored on-chip, which are used to convert raw measurement values to pressure reading. It is a dream come true; such a precision and accuracy is difficult to come by at such low prices, of about $8~10. Better, they come installed in many drone flight controllers. This is great because for about $25, you get a STM32F103 microcontroller with many other sensors, clock, regulator, all broken out to .1" pin headers. A great platform to experiment and develop with (see my blog on using Naze32 for development).

In this project, a full function barometric altimeter for aviation use was implemented using a Flip32 (Naze32 clone) flight controller board with installed MS5611 pressure sensor, an SSD1306 graphic OLED screen on I2C, and a rotary volume encoder. A single LiPo cell powers the system, with about 40mA current draw.

QNH adjustment is also implemented. You can learn the local QNH value of a nearby airport, dial it into the device, and obtain the MSL altitude in feet. In exactly the same way as a conventional altimeter is used. It was compared during flight with the altimeter of a Cessna 172, and the altitude is always within about 50ft, so it works quite well.




It is quite easy if you want to build one! You only need to buy a Naze32 or Flip32, or similar flight controller with a STM32F1, connect the I2C display (only 4 wires), connect the volume encoder (again 4 wires), burn the binary, and you are ready to go! It can be powered off a single LiPo cell. A small 240mAh cell completely hides behind the display, and will power the altimeter for about 6 hours.


Operation: At power up, an information screen is briefly displayed. Then it returns to normal operation where altitude in ft. is displayed in the center of the screen, measured local pressure in hPa and temperature in Deg. C. at the top, and set QNH at the bottom. To adjust QNH, press and turn the dial. The QNH set screen appears. At the center QNH value is displayed and at the top are the MSL altitude in feet and meters. If you know QNH, you can dial it while keeping the dial pressed in, or if you know the MSL altitude, you can dial that, just as in conventional altimeters. Upon releasing the dial, the device returns to the altitude display screen. Double click takes you into the information screen and back out of it.


Information screen at power up.
QNH set screen:  Enter either QNH of nearby airport or known airfield altitude. Turning the knob changes both.

Firmware: The source code of the project can be downloaded here. It uses u8glib graphics library ARM port, and was compiled with GCC ARM Embedded toolchain, easily downloadable from Launchpad. A binary is also provided, if you do not want to compile from source, for direct burning into a Naze32, Flip 32 or similar. Electrical connections are very simple: OLED display connects to the provided I2C terminals (I2C2), encoder to GPIOA: A signal to PA1, B signal to PA3, click signal to PA0. Internal pull ups of STM32 are used for simplicity so no pull up resistors are needed, no smoothing capacitors are needed either, since debounce is done in the software by a digital filter. See my blog posts for u8glib on STM32F103, and on connecting a volume encoder to the STM32F103.

The pressure altitude calculation formula can be found at several places in the Internet. There are a few sets of coefficients with a slight variation. However, the ones used here have been tested aboard a C172, and compare very well with its installed (mechanical) altimeter.

I wrote the pressure sensor communication and pressure calculation routines from the device datasheet.  I also wrote the bulk of u8g_arm.c and u8g_arm.h files using templates from u8g and several examples from around the web. One critical component is the setup of TIM2 for the delays.

So there you have it. Please build one for yourself, and make suggestions on how it should be. I have several ideas in my mind of how to make it better:
  • Implement a menu to adjust parameters (AGL or QNH display, feet or meters etc.).
  • Battery backup or   EEPROM backup for set parameters. Unfortunately flight controllers typically have the battery backup pin of the processor connected to upply voltage. Also, STM32F103 does have self programmable flash but again unfortunately, with a very small cycle count for this application of about 10,000 writes.
  • Upon power up it should default to the latest recorded altitude for best convenience.
  • I have other versions for larger STN LCD displays, for DOGM128W, and for ST7920, both connected over the SPI interface. DOGM128W is nice because it has a small form factor; only the glass panel. But it is somewhat difficult to find. ST7920 is bulkier, but abundant; it is used in the graphical interface of the Reprap Ramps 3D printer user interface, complete with a volume encoder! STN LCD is best in direct sunlight applications. Future blog posts will detail altimeters with those screens.  
Check back here for updates.

Disclaimer: Although this is an altimeter, those who build or use one accept the associated risks and are solely responsible for safe operation. Do not trust your life on it! It is not intended to be a replacement for certified or any other instrument for aircraft (but perhaps a coal stove).



Friday, May 27, 2016

Connect an SSD1306 OLED display to your STM32F103 board

Oled graphic screens are cheap to get from Chinese suppliers these days. For about 5USD, you can get a 1" sized monochrome display with 128x64 pixel resolution. The connection is also easy because they have I2C interfaces (or SPI; selectable), so only 4 wires, including power is all that's needed.


Display, displaying some text and rounded rectangle courtesy u8glib, ARM port.

STM32F103 is a very nice microcontroller; quite powerful, fast, easy to use, and there are many examples on various applications. This project shows how a popular SSD1306 OLED display can be connected to STM32F103, over I2C port 2, and using u8glib, by olikarus, at: https://github.com/olikraus/u8glib

There are many cheap development boards for the STM32F103 on the Internet, but another source of good development boards is to repurpose existing boards. I used the Naze32 (or one of its clones to be exact, the Flip 32), which come at a price of about US$20. It was designed for quadcopters and thus has many sensors integrated, voltage regulator clock etc. It is a good bargain. The SSD1306 OLED module is already running on Naze32, thanks to CleanFlight control program, and theoretically if you want the same functionality, you can pick out parts from CleanFlight. Unfortunately CleanFlight is quite large, and it was made to support many processors. It is easy to get lost in the source. So I decided to write my own.

The graphics library is u8glib by olikarus. it is hugely popular, but with one significant drawback: It was written for Arduino. There is an ARM port, (the version I used is: u8glib_arm1.18.1), but it requires you to write a few extensions for your particular processor, namely three delay functions, initialization of the connection peripheral, and a function to write to the display. These have been implemented in the files u8g_arm.c and u8g_arm.h. There are many similar samples on the Internet, but there seem to be differences in all, so I had to write them from scratch. Timer 2 is used for the delay functions.


 
The nice thing about this project is that the display can be easily connected to the board; there are only 4 wires to connect, and they are on matching 2.4mm header pins on the display and the board. Just buy the I2C display and the Flip32, and plug them together. It is therefore mainly a software project, and easy to build. The video shows the simplicity; a battery, the display and NAZE32. It can all be powered from a single LiPo cell (also visible in the video, but not connected), so quite convenient to build portable devices with. A small detail, the red LED flashes show when u8glib is active, so indicate the processor work load.

The sample code displays a few strings on the screen, draws a rounded rectangle around them, and animates them. U8glib allows for many more geometrical shapes and they can be easily inserted in your project with a few commands.
Download the source code at Github.

The project requires that GCC ARM Embedded is installed, together with the ARM port of u8glib and its fonts, as stated above. You should modify the Makefile to specify the respective tool locations. Specifically, the path to u8glib is specified in U8GLIB, and to the fonts directory in U8GFONT variables. How to install and use GCC cross compiler is shown in another blog post of mine.

This project was used as a part of a DIY aviation altimeter, which is at another blog post of minethat you can reach from this link.

Thursday, May 19, 2016

FreeRTOS Simple project for STM32F103 and GCC ARM Embedded


FreeRTOS is a simple way of adding an operating system to your microprocessor projects. It allows you to write more complex programs without worrying about the underlying details. It is quite user friendly and easy to use. However, as with any complex software, there are some details to get just right before it will work as desired. Here I present an example of how two periodic tasks can be created in FreeRTOS. It is intended as a starting point where the basic setup has been completed and working. It is easy to further modify to your own needs. That said, using a RTOS and a multitasking method to accomplish your goals is far from simple, and requires careful design.

Ingredients:
  • GCC ARM EMBEDDED is used, running on a STM32F103RB processor. 
  • The tests were done on a STM32 Nucleo FRB103 board. 
  • FreeRTOS version is V8.2.1, which is recent at the time of writing.
  • It can be built not only using commandline tools, but also the same source codes in a GUI environment such as Eclipse, Keil, Attollic etc. Please remember to modify the Makefile to suit your own directory structure.

The code can be found in my Github pages.

There are some pitfalls in the initial setup of the processor which you must take care of:

1. FreeRTOSConfig.h. It is necessary to set pointers to interrupt handlers to those provided by the FreeRTOS. This is done in the lines:

//Needed for the STM32F10x processors: #define vPortSVCHandler SVC_Handler #define xPortPendSVHandler PendSV_Handler #define xPortSysTickHandler SysTick_Handler

The remaining series of lines in FreeRTOSConfig.h are to set the properties of the processor etc. They are fairly easy to understand.

2. The main body of the program; freertos_testXX.c. This sets up the processor to run the tasks. It is fairly easy to understand and get running, using the FreeRTOS supplied functions. It is necessary to add the line to initialize the nested vectored interrupt controller on the STM32F103:

NVIC_PriorityGroupConfig( NVIC_PriorityGroup_4 ); //Needed for STM32F10x

Sometimes it is necessary to pass a structure to the tasks e.g., to initialize task parameters. An example of that is shown in the last two examples. Task priorities etc. can be set as desired, as documented in the FreeRTOS homepage.

The project is intended to run on a STM32 Nucleo F103RB board. But any similar is fine.

Several versions of freertos_testxx.c have been included. The project can be built using any of them by changing the Makefile. I wrote them when working with the project. Their function is shown below:

freertos_test01.c

First tests of periodic task creation using vTaskDelayUntil. Tasks are created with no passed data structures. Their operation as intended was confirmed.
As set up, T1 and T2 are "periodic" tasks; T2 has lower priority than T1. T2 will only run when T1 is done. T1 flashes the on board LED when it is running. Since T1 has a long execution time, the start of T2 is delayed, and you can see this in the flashing pattern of T2; it is irregular. However, when we exchange the priorities and T2 becomes the high priority task, its flashing becomes regular; whenever it is released, it is immediately executed by the the RTOS kernel.

freertos_test02.c

Same as previous.
Added a single value data passed to the task; its period. The passed value is declared in the function call as a void pointer. In the target function body, it must be either assigned to the correct pointer type (by declaring a pointer of the correct type, and equating it to the function argument void pointer through a suitable type-cast), or each time it is used, type-cast it to the correct pointer type. This may even be done implicitly since the function argument where this is used, or the left hand side of the equality will dictate a correct type-cast. However, better not to leave it to the compiler as implicit; some ambiguity might break the program.
Tasks are also truly periodic (in the sense of FreeRTOS) in which vTaskDelayUntil() function call is used.
It works fine.

freertos_test03.c

Same as previous.
Added a data structure to pass the data to the task. The data structure must be in the memory when the task runs. So that precludes the possibility of creating a data structure on the fly for the task in main() and remove it after task creation. It must be there all the time.
The data structure must be created by using a malloc call (apparently this costs time, but it is done only during initialization, so it is possible).
TODO: Check if malloc is allowed in the heap-1 model.
In this example, T1 parameters are passed using a structure. T2 has only one parameter. This is passed in a simpler manner, by type casting to void * on the fly. Even a literal (directly written number) can be passed in this way.
When created correctly, the data is passed to the task correctly. However, if a normal structure declaration is used within the main function, then apparently, the values are on the stack of main, and are not available to the calling function. The latter method does not work. Program compiles but the tasks do not get the intended values.

freertos_test04.c

Tasks receive all the critical values through the passed variable structure, i.e. period, number of instructions, and GPIO port to toggle for execution. This simplifies the structure for demos, because only 1 task function can be written, and shared among all created tasks.

freertos_test04a.c

Only one task function is written and all tasks are created as different instances of this. Their parameters are set by the passed data structure during the creation function call. This works fine. The body of the same task is called with different arguments to create several tasks.

The execution of the tasks can be recorded and visualized using a (cheap) logic analyzer and a viewing program such as GTK Wave, if they set a GPIO pin at entry, and reset it at completion. One sample run of 500ms is shown in the photo below. Task T1 period is 30ms and it has a higher priority. Task T2 period is 50ms and priority is lower at 50ms.

The task execution times seen in GTK Wave
You can see the signals repeat at the least common multiple of the periods (150ms), also called the hyperperiod. You can also see T1 preemts T2 just after zero; T2 seems to execute longer than usual, and T1 and T2 are setting their GPIO pins at the same time. What is actually happening is that when the time to execute T1 comes, T2 is preempted (suspended), and T1 runs instead. This happens three more times in the example above.

You can also see that the execution times of T1 are regular, but the execution times of T2 are irregular. Being lower priority, even if T2 is released, it must first wait for T1 to complete.

Saturday, May 7, 2016

Naze32 Custom Code: Binking Lights with GCC ARM Embedded

Modern flight controllers for drones and RC aircraft make great prototyping boards. At the time of writing, there are STM32F103, STM32F30x and also STM32F4xx based controllers. They are inexpensive, small, include voltage regulators, nice 0.1" header pins, as well as s series of inertial and barometric sensors.

I wanted to build an altimeter for amateur aviation use. At first I wanted to build it on a custom PCB, but then I realized that a flight controller fits the bill nicely, and will come much smaller and cheaper. Because they are widely available, the project can be replicated easily by more amateurs, compared to a custom PCB project

So I took a Flip32 board I had laying around (an exact clone of Naze32 which is quite popular), and decided to port some custom code on it from another similar STM32F103 project for a different board. Schematics are easily found on the Internet. So I found the pin which the LED is connected: Port PB4. Compiled the code, flashed and verified, but... It did not run. What could be the problem?

I looked around, and considered many possibilities, mostly focusing around clock initialization problems. The STM32 series have quite complex clock trees with many different sources of clock and fallback clocks in case one fails. However, after many trials there was no improvement. What could be the problem? I also looked in the source of Cleanflight. It was written for several processors and is divided into many source files, so it is quite difficult to trace the exact startup sequence for STM32F103.

Eventually, looking over the reference manuals (well over 1100 pages), I found the likely suspect. The STM32 has a powerful JTAG interface for debugging which is enabled by default at power-on.  It uses several pins, one of which, PB4 is NJTRST. It is possible to disable the JTAG functionality during the processor initialization, so that PB4 becomes a useable pin again. If you want to be able to use JTAG later on, it is possible to do that anyway, because it is always active after power on. So diabling it here is not a big deal.

You can download the blink source code here. It sets up the processor and blinks the two on-board LEDs in unison. The code itself is simple enough, just another LED blink program. The interesting part is the first few lines of  initialize_PROC() function, where JTAG pins are returned to their GPIO configuration. Programming an ARM STM32F10x processor is described here.

The result is (well, OK, you cannot see it blink in the still shot but...):

Flip32 with blinking lights program. Wire below is from a LiPo cell stuck to the bottom.





I scratched my head a lot over this, so I hope this will help others.









ARM STM32F10x GCC: Connect a volume control encoder

Volume control is nowadays commonly done using rotary encoders rather than traditional potentiometers. They would make nice input devices in DIY projects. This example shows how you can connect such an encoder to STM32F103. As in my other projcts, plain ARM GCC toolsuite is used with no GUI.

Roraty volume encoders output a quadrature signal, and represent the rotation angle and direction using two square wave signals A and B generated in + or  - 90 degree phase shift with respect to each other. They are easy to read in practice; detect the rising edge of signal A, and check the level of signal B; if it is high, encoder is turning in one direction, else in the other direction.

Typical rotary volume encoder.

In real life, it can be a bit more difficult using the cheap encoders which are based on mechanical switch contact. There can be a lot of contact bounce which can be mistaken as switch rotation and poor user experience.

This project shows an example of how such an encoder can be connected to the STM32F103 processor. It reads the encoder and sends '1' or '0' over UART1 as the encoder is turned.

The  source code can be downloaded here. The project is built using GCC ARM Embedded, the installation of which is  shown here. It contains several files to divide  the functionality neatly so that it can be re-used easily. The source also contains Elm-ChaN's xprintf and xuart files which allow using regular printf over serial port, and are greatly helpful in debugging simple applications (but the latency is large and depends on the displayed value).

The encoder device produces a quadrature signal generating two square wave signals which are + or - 90 degrees out of phase depending on the direction of rotation. The signal is decoded using software (not the hardware quadrature counter of STM32F103) because of the low pulse rate. Encoder pins are connected to ordinary GPIO pins. Since many of these encoders come from Chinese manufacturers with low quality, they may have a lot of noise and bounce during rotation. To eliminate this noise, a debounce method is implemented using a DSP lowpass filter (1st order, IIR, 1kHz sampling frequency). The result is nice and smooth action without missing or extra counts.

I built the circuit around a Flip32 flight controller which makes a great STM32 prototyping board. It already has LEDS, 0.1" headers, voltage regulator, USB serial converter and several inertial and barometric sensors. The best is, all of that costs only about $15-20 depending on the configuration. Besides it is nicely compact and easy to carry around. The only gripe is that the Vbat pin is not brought out. Here is a photo of one of the prototypes:

Rotary volume encoder connected to a STM32F103 board, the Flip32 (Naze32 clone).


 I also took a video of operation. The board is connected through a USB-Serial converter to a Linux computer running Kermit. Each time the encoder is pressed and turned, a '1' or '0' is displayed on the screen, depending on the direction. No data is displayed if encoder is turned without pressing (this is a safety feature for the altimeter application this functionality was built for). The press-and-turn can be easily disabled in the source.






To run the program on your board, edit endcoder.h file to change the GPIO pins that are actually used. The SysTick should be set for 1kHz operation and the encoder pins are scanned at each interrupt.

The encoder code was used in another project of mine、aviation altimeter, that you can reach through this link.

Monday, April 25, 2016

ARM STM32F10x GCC: Connect a LCD backpack


The Hicathi H44780 LCD is ubiquitious, but it is also quite old technology. It is quie slow (each character takes about 1ms to display) and it requires a lot of pins to connect (8 data + 3 control) having no serial interface. However, it was so popular in the last 30 or so years, that its legacy lives on and it is still the #1 choice for alphanumeric displays.

To offset the difficulty in connecting it, many serial to parallel boards were developed over the years; some converting RS232, acting as a display controller. A few years ago, two boards were introduced, both using I2C to parallel converter chips, also known as I2C port expanders. The most widely used board has a PCF8754T I2C to parallel converter, and many libraries for the Arduino community, using the LiquidCrystal library.

This project demonstrates the use of GCC ARM Embedded toolchain without a GUI. A STM32F103RB is connected to a 2x16 Hitachi H44780 LCD, over a LCD backpack; thtrough I2C. On the STM32F10x, the I2C1 bus is used for communication.

The processor is STM32F103RB. I2C module initialization and use is demonstrated, using the API provided by the STM32F10x_StdPeriph_Lib_V3.5.0 standard periperal libraries.
This version of the program is for the red 2x16 LCD Backpack, labeled Funduino. However most of the clones will work as long as they use the PCF8574T I2C to parallel converter chip. Check its address and modify the value of the address definition in main.c (default address is 0x27).

Connections for STM32F103RB Nucleo board (or anything similar): SDA -> I2C1_SDA (PB7, Morpho CN7, Pin21) SCL -> I2C1_SCL (PB6, Morpho CN10, Pin17) 5V (Morpho, CN7, Pin18) GND (Morpho, CN7, Pin20 (STM32F103 I2C1: SCL, SDA are 5V tolerant.) Connect 10K pull up resistors from SCL and SDA to 5V.

You can build the project as shown my other post. Follow the steps shown there to modify the Makefile to suit your setup, make and burn into your board.


The LiquidCrystal library is by YWROBOT, but was originally written for Arduino. ARM conversion and most of the code here was taken from this post  (in Russian. I do not know Russian...).

I used this as one of the first steps when learning how to program STM32F103. Tweaked it, and prepared a project, complete with all files. I am posting it in the hope that someone will benefit from this complete project.

The backpack in action is shown in the photo below. 4 jumper cables are all that are required to make it work, including power. It displays the current value of an internal variable. The heart symbol at the top is user defined.
The LCD backpack in operation. The heart symbol in the first line is user defined.




The backpack is shown below:
PCF8574T backpack and STM32F103RB Nucleo board, connected by some jumper wires

Closeup of the PCF8574T backpack.



Thursday, April 21, 2016

ARM STM32F10x programming with GCC


This is about how you can build a simple ARM program using free software tools and really cheap development boards subsidized by the manufacturer. If you wish to skip my story about how I came to using it, skip to the next section.

My story

I have been programming microprocessors since 1989, "assembling" my first simple program to binary, by hand on paper during a bus trip. I had been interested in working with ARM microcontrollers for some time but intimidated by the many possible approaches to ARM development. Which processor, which development environment and whether I should use an operating system or not. The ARM processor family is large, and since ARM does not produce physical processors, there are a large number of manufacturers who produce ARM processors, from which you can buy. But which one? Where do we start?

I am not really fond of large processor boards which claim to do everything. I am also not a fan of large and heavyweight development environments that claim to do everything. Both of them carry an enormous complexity that is difficult to understand, and although easy to start working with, writing your first program and build flashy
gadgets, in the long run it is difficult to understand the inner workings of the board or environment and therefore difficult to master the fundamentals. One reason is that they were built to the reasoning of the manufacturers with customers of professional programmer teams writing huge programs in mind. Not necessarily in-line with my way of thinking. Besides, you are now tied to a certain manufacturer and lose the freedom to pick the best one for the application.

The ease of entry generally comes at a price; you need to pay money or maintain a heavyweight board or development environment, tied to their updates and bug fixes, as well as pay cash to keep using beyond the trial period, or go beyond code size limitations etc.

What I wanted was something simple. A simple board that I could add to as I went along, and a simple compiler that was virtually limitless.

First of all, the compiler. GCC is one of the best compilers around. But several years back, there was no simple way of using GCC on embedded targets but compile your own compiler from scratch. You started with a GCC suite for the development PC, then compiled a version of it from source generate a compiler for the target processor, then used it to compile the libraries for the target processor etc. It was a long and tedious process, which required a lot of parameter tweaks, which if done wrong, produced a dud; a compiler which would compile code without errors, but that code was not fit to run on the target processor. You need to start over again with no clear directions of how to fix the problem. Been there, done that. if it is your paying job, you can endure it. But for hobby purposes where you use it off and on, the labour becomes old too quickly.

Then the board; there are many boards around. Some of them flashy, with every peripheral, including a HD TFT display and the kitchen sink. They come with a nice board support package to run all of those peripherals. The problem is, if you are not an expert, then you are left with complex devices which are difficult to learn how they work and you cannot modify or use the system to build what you want with it. So I consider the complex systems as short lived passion. Simpler boards which are almost like pin header adapters are the best in my opinion. They are minimal in that they provide clock, voltage regulation and perhaps some connection like USB or serial, and they bring all pins of the processor to some easy to connect header pins.

Start simple, learn it all, keep your cash too

I was fortunate to come across three things in the Internet:
1. Chinese cheap suppliers
2. The open source e-book : "Discovering the STM32 Microcontroller" by
Geoffrey Brown from Indiana University: http:www.cs.indiana.edu/~geobrown/book.pdf
3. The pre-compiled GCC suite maintained by some folks at ARM.



All of what I will explain can be done in Linux or Windows. I am not a Windows user, but have supervised students who have quickly gotten it working under windows. During this endeavour, I was lucky to come across Prof. Geoffrey Brown's on-line book stated above. It follows the same approach as me, and was extremely helpful in the first steps when I started working with ARM STM32F10x microcontrollers. You should download it and read at least the first 4 chapters, and then those related to your peripherals. Very clear and concise explanations.

The following is how you can set up a development environment based on GCC (GNU Compiler Collection) and run your first program.

Downloads

    Get the GCC compiler tools

    From: https://launchpad.net/gcc-arm-embedded
    I used the gcc-arm-none-eabi-4_9-2015q2-20150609

    But the newest version can be used instead. It has support for other processors such as the STM32F4 series with hardware floating point support as well.

    Download the appropriate pre-compiled binary for your operating system. The binaries are quite well behaved, in that they simply extract to a single folder, and do not spawn other files at remote directories, or modify operating system components (such as Win
    registry). If you are not interested any more, simply erase the folder, and it is gone forever from your system.

    Get the STM libraries

    Download the STM32F10x libraries from ST microelectronics, (or, go to www.st.com and search for stsw-stm32054). The page says that the libraries have been superseded by STM32CubeF1. However, they are still available, work well and stable(CubeF1 is not ready at the time of writing, apparently). You will need to scroll down to the bottom of the page to find the offering. I used the: STM32F10x_StdPeriph_Lib_V3.5.0 in my examples.

    The libraries are simply extracted under a single folder, and consist of source and configuration files for the target processor that will be used when compiling your code. They include no executables for the host computer.

    Install GNU Make

    The GNU Make is also required. It is naturally included in *NIX systems. If your OS does not have it, (such as in Windows) the source can be downloaded from:
    https://www.gnu.org/software/make/
    However, it is better to download a pre-built binary from:
    http://gnuwin32.sourceforge.net/packages/make.htm
    In some Windows distributions, a few DLL files might be missing. You can download the dependencies also from the same site. The latest pre-built binary version at the time of writing is 3.81. Do not worry much about the latest version; make has been around since 1989, and it is a really old, well behaved and stable program; any version
    should do.


    And the Device Programmer

    A device programmer for the STM32F10x is necessary. See below for a short discussion. In some cases, you can get by without it, since the Nucleo boards provide a clever programming method which does not need any special program to be installed in the host computer.

    A good text editor. Gedit is popular and native in Linux. However Emacs is much better if you can invest in a short amount of time to learn it. Learn the many keyboard shortcuts, and you can write text much more efficiently than the guy next door who must reach for the arrow keys and mouse to do every which task. A colleague used to say that "Emacs is like smoking. First it makes you cough, but once you get used to it, you can never quit." There are also other people who say learning Emacs is like quitting smoking; they've done it many times... In Windows there is Notepad++, PSPad or other similar freeware that are very good.

    Installation

    Decide on a suitable directory in your file system, preferably somewhere under your home directory. Let's call it the development folder. I built a directory structure that looks like:

    ARM/
       Compiler/
          Compiler directory/
          Library directory/
       Code/
          My code/
       Documents/
          Various collected and created information.

    Any naming will do, as long as you keep track of what you put where. There is no magic structure you must obey. This is the nice thing about building your tools!

    Install/extract all the files.
    First, add 'make' to the PATH environment variable (search how to add to path for your OS) and test that it works in a command shell:
    $ make
    It should respond:
    make: *** No targets specified and no makefile found. Stop.

    Correct any errors.

    Then, setup GCC. You should add the GCC compiler to your PATH variable so that any program is aware of its presence. Alternatively, you can explicitly specify its location to GNU Make. I recommend adding GCC to PATH. When done, test 'gcc' by typing in a command shell:
    $ arm-none-eabi-gcc --version

    And the response should be:
    arm-none-eabi-gcc (GNU Tools for ARM Embedded Processors) 4.9.3 20150529   (release) [ARM/embedded-4_9-branch revision 224288] Copyright (C) 2014 Free Software Foundation, Inc. This is free software; see the source for copying conditions.  There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    Of course the version number may be different. If there is any "not found" error, you must correct it now.

    Extract the library to the appropriate location. There is no simple way to test the success, except going into the directory and seeing that the files have actually been created.

    A command shell is also necessary. In Linux, there is already a powerful command shell that you can use. In Windows there are two choices. You can either use the standard command shell by selecting "Run" from the main menu, and typing 'cmd'. However, I recommend using Windows PowerShell which is much more, er, powerful, and actually
    carries much of Bash functionality from Unix systems. It is not well known, but a standard part of the distribution. See Wikipedia entry  or other sources on using Windows PowerShell.

    At this point, you have a working toolset to compile code for many ARM Cortex processors. Check which ones your GCC supports by the following command:

    $ arm-none-eabi-gcc -print-multi-lib

    The processor board

    There are obviously many boards out there. Since I like the simple boards, I used this one from China:
    The board that I used when starting my development.

    It can be found at DealExtreme.com, here, costing about $6.5. However, I think that it is better to buy something more common, so the STM NUCLEO-F103RB is probably a better choice. This post is based around the Nucleo board; it is more readily available, and has a debugger hardware on-board.

    STM32 Nucleo board with STM32F103RB
    I chose the STM32F103 processor because it is quite powerful but also simple. It is used in several applications such as in attitude control of quadcopters, and many more applications. It is very cheap to obtain and so has a great price to performance ratio. The next step up could be the F40x series boards with hardware floating point support, if you really need the power.



    Compiling your first project

    The next step is to compile a sample project, and download it to your target processor board. First download the example code that I wrote for the STM32F103 Nucleo board, to a suitable location in the development folder.

    Download the source to a suitable directory.

    The first thing is to modify the supplied Makefile to match your particular GCC and STM32F10x peripheral library installations. Open the Makefile with a text editor. Do not double click on the source files and end up opening them in Visual C or similar GUI; we have nothing to do with Visual C! In Makefile, edit the definitions: "TOOLROOT" and "LIBROOT", to suit your installation. Find the lines where it says:
    TOOLROOT=..... LIBROOT=......
    Modify, save, and that should be enough.

    Next open a command shell and navigate to the project source directory. Type:
    $ make
    Much text will fly by, ending with the last command of the Makefile:
    arm-none-eabi-objcopy -O binary Blink32F103_Nucleo-Sample.elf Blink32F103_Nucleo-Sample.bin
    Unix has a "No news is good news" policy. If it does not complain, there is nothing wrong. Make has the same policy regardless of it running on Linux or Windows. If there is an error, make will stop with either an 'error' message, or something like:
    make: *** No rule to make target `main.o', needed by `Blink32F103_Nucleo-Sample.elf'. Stop.

    If it all goes right, you will end up with three files:
    Blink32F103_Nucleo-Sample.bin Blink32F103_Nucleo-Sample.elf Blink32F103_Nucleo-Sample.map
    The file name will be the same as the name of the directory that you created for the project, but the extensions will be the same as those shown. We will use the first one:
    'Blink32F103_Nucleo-Sample.bin' to burn into the processor. The .elf file is to be used with the GDB debugger, and the .map file shows the memory map of the project; where each function is located, where each variable is located etc.

    How to burn into the processor

    At this point it is necessary to use a device programmer hardware. Luckily, there is one already attached to the Nucleo boards, the STLINK V2. The software to communicate with it from Windows is the ST-Link utility, a lightweight freeware program from ST Microelectronics, which works well. It can be downloaded from www.st.com and search for "STSW-LINK004".

    For Linux, there is the free software "ST-link" it can directly interface with GDB also.

    However, I like to use an even simpler and lighter program, "stm32flash". It is extremely simple to use. However, you need to connect a USB-serial(TTL) converter to the UART1 RX and TX pins physically, and pull BOOT0 pin to ground going out of reset. I like stm32flash a lot because of its simplicity so I use it.

    The final and probably easiest way of programming a Nucleo board is to use its clever user interface. When you connect the Nucleo to your host computer, it is recognized as a USB mass storage device (AKA usb thumb drive). Simply drag and drop your executable binary file (<filename>.bin extension) into the drive, and it will be programmed into the flash. Easy as that!

    At this point, perhaps after a reset, the green LED labelled LD2 should start to blink once a second, in a rather comforting way. Good job.

    How the project is made up

    Once you can compile and write your code into the microcontroller, and see the LED blinking, you can sit back and relax! You can start to build more projects quite easily now. Now let's look into the structure of the "project". It is made of the following files and their role:

    Makefile

    This is the orchestra conductor. It directs the compiler and the linker about your options, the paths of the libraries, what steps to take to obtain the .bin files from the .c files, which source files are needed in the project and many more things.

    The most important thing you need to put in it are the names of the source files that will be needed to create the binary executable. That is stated in the  lines that read: "OBJS= main.o" and "OBJS += stm32f10x_gpio.o stm32f10x_rcc.o". It is you who should know what to put there. But the examples make it relatively easy to figure that out. "main.o" must obviously be there. If you are using any GPIO pins, "stm32f10x_gpio.o" library file must be there and so on. See the header file inclusions
    in "main.c" for a hint. Note that we are not putting in the names of the '.c' source files, but the names of the object files. It does not need to be like that, but this Makefile was written in that way. The rest of the Makefile can be copied over from project to project with the stated modifications, until you know better.

    main.c

    This is obviously the meat of the matter. It is originally taken from the eaxmples folder in the STM32F10x libraries and Geoffrey Brown's book. Please read it through so that you understand what is going on.

    stm32f103.ld

    The linker script. We are getting into the nuts and bolts of how a program is compiled here. When you prepare the "main.c" file, you will reference some functions and not define them (in standard 'C', the first program that you write, helloworld.c, generally contains the function "printf()". Where is it defined?). Such functions are defined in a library. The library file that they are defined is specified in the Makefile (remember the "OBJS += stm32f10x_gpio.o" line in the Makefile?). After all the '.c' files are compiled into separate object files '.o', the function references are still not in one place. The main job of the linker (called 'arm-none-eabi-ld' in GCC, or just 'ld') is to look into each object file, find the function calls that are not defined in that file, try to match the definition of the function in the other specified object files, and "link the call with the definition"  (that being why it is called a linker).
    But the file "stm32f103.ld" was never mentioned in this discussion? The second
    major job of the linker is to place the data, variables, functions etc. in the proper positions of the processor memory. This script describes the processor memory to the linker. It defines how much RAM and programmable ROM memory the processor has, where they are located in the memory map; which locations must the code (called 'text') be written, which locations the uninitialized variables (.bss), constants (.rodata) and initialized variables (.data) etc. be placed. If you move on to another processor, the linker script must be modified to reflect the memory structure of the new processor, otherwise the program will not work. It is worth looking through the linker script file to get acquainted with it.

    stm32f10x_conf.h

    This is a configuration file for the processor. Not used extensively in this application.

    startup_stm32f10x.c

    This is one of the unsung heros of all 'C' programs; the startup program. It sets up the processor. See the function void Reset_Handler(void) which initializes the initialized data (declarations like int x=5;), calls the SystemInit() function from the library which, among other things, initializes and declares the system clock frequency, and finally branches into our famous 'main()' function. "main" is no magic function name, but something simply defined as such in the startup program. In the second part of the file are the declarations of the interrupt handlers, which are defined as weak aliases to dummy functions. When you declare your own interrupt handler in your source code, they will override the original definitions.


    So this is all that makes a "project" for plain GCC. The beauty of this is that all the components are there in plain sight. None of the file names and even extensions are magic values.  You can modify anything as you wish, and structure your programs to your requirements and taste. You do not need to follow complicated directory structures created by commercial development environment manufacturers, aimed mostly at development of large programs, which intimidate our simple blinking lights programs. However, this simple looking setup has unlimited potential, in which it can be extended to work with the most complicated of projects. Indeed many commercial development environments are nothing more than "nice" frontends to this very same GCC setup that we have built up!