June 4, 2015

New(ish) Tools for STM32 Development – STM32Cube

About 2 years ago, I authored a five-part tutorial on setting up a free/open source toolchain with Eclipse and GCC to develop code on ST's line of STM32 microcontrollers. (Part 1, Part 2, Part 3, Part 4, Part 5, Followup) That series demonstrated how challenging it can be to properly set up these tools and get them configured for the microcontroller of your choice.

Since then, ST has really upped their game and has introduced two tools that really make the process of developing for the STM32 line of parts much, much easier. In fact, I'd go so far as to say my tutorial series has been made obsolete.

The first tool is STM32Cube. STM32Cube (also called STM32CubeMX) is a Java based GUI tool that assists in the selection of an appropriate microcontroller, in the setup and configuration of on-chip peripherals, and in building a project that has all of the proper dependencies and initialization code built in. I haven't used this tool a whole lot yet, but I can tell you that I'm already wowed by it. STM32Cube is a free download from the ST website. It currently is packaged as a .zip file that includes an .exe. Running the .exe opens the GUI. Though it is a Java tool, ST only provides a version of the tool for Windows, though if you do some searching on the web you'll see that others have managed to get it working on other operating systems.

The other tool, which I'll discuss in my next blog post, is STM32 Workbench, which is a preconfigured Eclipse environment for STM32 development.

Can you see why my previous tutorial series is now obsolete?

Let's first take a look at STM32Cube. Here's an example of using the tool for a project I'm currently designing. Launching the tool, the user is given a couple of pretty obvious choices: create a new project, or load an existing project (as always, click on the thumbnail for fullsize graphics):

The STM32CubeMX Splash Screen

The STM32CubeMX Splash Screen

After clicking New Project, a parametric product selector is displayed. Check the onboard peripherals you want, select the chip series and package(s) you want, and the tool will tell you which parts meet your needs. Much easier than browsing Digi-Key or Mouser!

Choosing a part

Choosing a part

In my case, I'm designing a project that needs 3 UARTs, two I2C, one SPI, and has some EEPROM. I ended up selecting the STM32L051C6Tx chip:

The microcontrollers that are suitable for my application.

The microcontrollers that are suitable for my application.

(Note that even though my project requires 3 UARTs, I still had to juggle my requirements between UARTs, USARTs, and the LPUART. I suppose no tool is perfect.)

After highlighting the part and clicking OK, STM32CubeMX brings up an interface that allows you to configure the selected part. The four tabs are Pinout, Clock Configuration, Configuration, and Power Consumption Calculator. This is where STM32Cube gets really interesting.

Choosing a pinout from a blank slate.

Choosing a pinout from a blank slate.

From this blank slate, I made the following selections:

  • I expanded the FATFS node and checked the box to include this middleware in my project.
  • I enabled I2C1 and I2C2.
  • I set LPUART1 to Asynchronous mode.
  • In the RCC, I set both the HSE and LSE clocks to Crystal/Ceramic Resonator.
  • I enabled SPI1 in full-duplex master mode.
  • I checked the SWD debug function in the SYS node.
  • I set USART1 and USART2 to Asynchronous mode.

As you can see, the pin planner tells me which pins are connected to which peripherals. If I want to map a peripheral to a pin other than the one selected, I can CTRL-click on the pin and the tool will show me which other pins can be used for that function. Red X's indicate functions that cannot be used because another peripheral is already on the required pin(s). Yellow exclamation marks show peripherals that have one or more subfeatures that are not available because required pins are in use by other peripherals.

Pin Planning in STM32CubeMX.

Pin Planning in STM32CubeMX.

After placing the on-chip peripherals on pins, you can assign GPIO pins. Click on a pin to bring up a dropdown that lists the pin's available functions.

Selecting a use for PB5.

Selecting a use for PB5.

Here I've set PB3, PB4, PB5, and PA15 to digital outputs to drive LEDs, and PB8 and PB9 to digital inputs to accept signals from pushbuttons. Note that STM32CubeMX allows me to label the pins here as well. These labels will become symbols in the generated C code as well.

Pushpin icons show the manually placed pin functions.

Pushpin icons show the manually placed pin functions.

Once all the pins are assigned, we can look at the Clock Configuration tab. ST used to provide this tool as a rather inconvenient Excel spreadsheet. Now it's integrated into the code generation tool, which is nice. And given the complexity of the STM32 parts' clock systems, it saves a lot of headaches. Here, I've changed the clocking from the HSI (internal) clock to the HSE (external crystal) clock, and I've done the same for the low speed clock that drives the RTC. The system clock and most peripherals are running at 8MHz, which should be fine for my application.

Clock configuration.

Clock configuration.

After pins are mapped and clocking is done, the Configuration tab allows us to configure the selected peripherals and middleware. Here you can see that I have options for the FATFS filesystem, my UARTS, SPIs and I2Cs, the DMA controller, the GPIO pins, the NVIC, RCC and the RTC. (You'll find these terms defined in the STM32 reference manuals.)

Peripheral Configuration

Peripheral Configuration

For this project, I plan on using an SD card in SPI mode to store files in a FAT filesystem. The number of options that can be compiled in or excluded from FatFS are numerous:

Tweaking FATFS.

Tweaking FATFS.

I'm not going to show you all the screenshots for all the peripherals, but here I am putting a pullup resistor on my button inputs so that I don't need an external resistor:

Selecting GPIO options.

Selecting GPIO options.

Once the pins are mapped, the clocks are configured, and the peripherals are configured comes the really fun part: automatic code generation! With the click of a button, STM32CubeMX will automatically generate a project for you, after automatically downloading appropriate libraries for your target MCU if required. The generated project files look a lot like the sample projects I outlined in my earlier tutorial series.

One interesting thing about the generated code is that there are comments embedded in the code files, such as this set in the generated main() function:

int main(void)



/* MCU Configuration----------------------------------------------------------*/

/* Reset of all peripherals, Initializes the Flash interface and the Systick. */

/* Configure the system clock */

/* Initialize all configured peripherals */



/* Infinite loop */
while (1)




Any code that you put between the USER CODE BEGIN and USER CODE END comments will be preserved if you go back and make changes in STM32CubeMX and re-generate your code.

Now, I haven't had a lot of time to play with the tool, but it looks very promising to me, and certainly a lot easier than the hoops I had to jump through in my previous tutorial series.

Next post, I'll look at STM32 Workbench.


January 12, 2015

Thoughts on Technical Interviews

This morning, I was invited to be a part of an interview panel for some candidates for openings we have in my workplace. There were five of us conducting an interview for technical positions. I've done this enough and seen enough facepalms in these interviews that I want to pass on some basic advice. (more…)

July 13, 2014

An Assembly Language Delay Routine for ARM Microcontrollers

I'm in the midst of writing some code to initialize an LCD screen. The initialization requires me to send a command, then wait for at least 50 milliseconds, then send more commands.

If you're using an Arduino, this is easy: you call the delay() function. If you're graduating from the Arduino to a more 'bare metal' development environment, you may find yourself looking for this function that doesn't exist on your platform.

Furthermore, if you do a Google search for delay routines on an ARM microcontroller, the near universal reply is, "you should use a hardware timer for that!" (more…)

June 6, 2014

AVC Boards have arrived!

I had given up all hope of receiving my AVC circuit boards and had convinced myself that they had become forever lost in the mail. And wouldn't you know, today they show up. Ten circuit boards when I only need one. (more…)

June 1, 2014

AVC Proof-of-Concept (sorta) Post

The AVC Proof of Concept deadline is today. (Or maybe it was yesterday.) This is my lame attempt at desperately hoping to still qualify for the contest.

You see, the circuit boards that I ordered from Dirty Boards on the 3rd of May still haven't arrived. Without circuit boards in hand, I really don't have much to show for my AVC entry.

On the off chance that the AVC staff will take mercy on me and allow me to remain in the contestant pool, my robot consists of:

Yeah, without pics, I realize the credibility in this post is near zero. But that's all I have right now- words and ideas. I'm well aware that the chances of me being ready in time are pretty slim, but I'm hoping the decision on whether or not to drop out can be my decision and not the decision of the AVC staff.

So I'll send them a link to this post and see what they say...

May 22, 2014

Udacity Course Review: Artificial Intelligence for Robotics

A couple of months ago, while doing research for the Sparkfun AVC, I posed to the DIYRovers Google Group a question about the Kalman filter. I had discovered through reading that the Kalman filter is a popular algorithm in robotics and the more I read the more it seemed that the Kalman filter is the answer to just about any robotics problem out there. Unfortunately, I was unable to find any good learning resources for this algorithm that didn't require an undergraduate degree in mathematics.

One of the members of the group suggested that a good resource for learning the Kalman filter is the Udacity course "Artificial Intelligence for Robotics."

Udacity, for those who don't know, is a MOOC: A Massively Open Online Courseware site. Udacity hosts online classes that anyone can take free of charge. Udacity is a for-profit educational organization founded by Sebastian Thrun, David Stavens, and Mike Sokolsky. It is the outgrowth of free computer science classes offered in 2011 through Stanford University, where Sebastian is a professor. I'll talk about the for-profit part in a few paragraphs.

So, at the encouragement of another AVC'er, I started taking the course.

The course wasn't at all what I expected. The primary focus of the course is how to deal with uncertainty in robotics applications. For instance, a sensor might be noisy, or a command to move the robot might be affected by wheel slip. The entire course is an introduction to various methods and algorithms (including the Kalman filter) that can be used to deal with this type of uncertainty.

The course starts off with simple one-dimensional examples and considers noise and probability. That is, in the presence of noisy sensors and noisy movement commands, the robot cannot have absolute knowledge of its position. Instead, the course teaches how to track the probability of the robot being in any particular location, and the reliability of any probabilistic guess as to the robot's position.

The course advances into more complex algorithms and into two-dimensional examples. Bayes' Theorem is introduced and conditional probabilities are used. The course proceeds on to the Kalman filter, particle filters, the A* and other search algorithms, PID control, and SLAM algorithms.

The course is taught by Sebastian Thrun. Sebastian is a professor at Stanford, and was a member of the DARPA Grand Challenge  winning team and a member of Google's self-driving car research team. Clearly, the guy has experience in robotics to be teaching this course. In fact, Sebastian uses his experiences with these projects to bring real-world examples to his lectures. This brings home the point that these algorithms are practical and applicable to real-world problems.

The course material proceeds logically and builds in sequential steps. Lessons are broken into short videos, typically 2-6 minutes, followed by a quiz, which is typically a Python programming exercise or a multiple choice question. In most cases, a skeleton Python program is given and the student must write a function to implement the concept just explained in the lecture. I found that the exercises complement the lectures quite well. Sebastian is an outstanding instructor, and the material was paced perfectly for me. The Python programming is done in an in-browser editor and is graded by an autograder in the course engine. Feedback on the exercises is immediate.

I found very few downsides with this class. I was a little disappointed that the Kalman filter wasn't discussed in as much depth as I would have liked. Also, the subtitles on many of the videos are very poor; whoever created the subtitles clearly was not familiar with the material. That combined with Sebastian's German accent make for some truly interesting subtitles.

Be warned that this is not an introductory course! This is the exact same course that Georgia Tech uses in its Online Master of Science in Computer Science program, and I assure you that this course really is graduate level coursework. You'll need to have a semester or two of college level statistics, exposure to linear algebra, and decent programming skills to complete this course. Having said that, it's been over 20 years since I've taken linear algebra and I did just fine.

You can take the course for free, or you can pay $150 a month to get a "certificate" for passing the course. The material is the same in both cases. The difference is that with the paid course you have access to "coaches" and are required to do a final project. As luck would have it, my employer amended our tuition reimbursement program as I was halfway through doing this course for free, which allowed me to get reimbursed for taking the paid version of the course. That was a no-brainer and I immediately signed up for the paid version of the course.

Before my first payment was due, my assigned coach scheduled a Google Hangouts videoconference to ensure that I had the necessary academic background to be successful in the course.

The entire coaching staff is available to answer questions via instant messaging or email. They respond to instant messages immediately in my experience.

The coaching staff was, in a word, fantastic. I was (and still am) simply blown away by these guys. The coaches not only understand the course material, they understand it well, and they understand the broader context of the course material as it applies to real world problems. I kind of think of the coaches as the Teaching Assistants that I had in some of my undergraduate courses at university. I can say that if the TA's in my undergrad career had been as amazing as the Udacity coaches, college would have been a much different experience for me. I cannot say enough good things about the Udacity coaching staff. I don't know where they find these people, or how much they're paid, but they are far and away the best asset for this course.

For example, when I contacted the coaches about a question I had on one of the exercises for the Final Project, the coach looked at my code and quickly observed that my code ran in n^2 time, when, with a little modification it could be made to run in linear n time. I did know this about my code before asking for help, but I was impressed that the coach pointed this out to me so quickly. And that observation had nothing to do with the question for which I was contacting the coaches for help!

It is not necessary to complete all of the lectures or exercises to 'pass' the course and get a certificate. Only completing the final project is required. The final project includes writing some code and writing a short narrative explaining certain features of your code and why you made certain design decisions. The first time I submitted my project it was kicked back to me because I had made some arbitrary decisions without explaining my reasoning in the code comments. The graders are thorough!

In summary, this course was an outstanding experience for me. I probably wouldn't have paid for this course if my employer didn't offer reimbursement, but knowing now what I know about the experience, it would totally have been worth it to pay this out of my own pocket.

Highly recommended.

May 14, 2014

AVC Boards Have Been Ordered!

Well, it's been a while since I posted anything. I've been very heads-down with various priorities and this is the first opportunity I've had to come up and take a breath. I've just shed a few obligations so I'm hoping I'll be able to post more frequently.

I haven't abandoned my AVC project! In fact, I spent several weeks tweaking the schematic and then several more tweaking the PCB design. The inescapable fact of all this is that I just plain suck at PCB design. (more…)

April 7, 2014

Unholy Combinations

I just feel so.... dirty running Python on Windows. Like I'm going against God's Natural Law or something.

OK, I feel better now that I have that off my chest. Back to work.

March 18, 2014

AVC Parts Ordered!

I submitted my order to Mouser today. While that's on its way here I'll lay out my circuit board. When the order gets here, I'll verify footprints and then send off my gerber files to have a custom PCB made.

The June contest date is approaching way too fast! I don't even have my hardware done yet, so I can't do a whole lot of software development. Argh!

March 2, 2014

The Woes of Debugging DMA on the STM32 Platform

I spent a good chunk of today getting frustrated with my AVC code. I have custom firmware on my GPS so that it sends a fixed-length binary sentence to my microcontroller. Rather than polling the USART, or handing an interrupt every time a character comes in, I figured this is a perfect application for the DMA controller... tell the DMA controller how many characters there are, and have it wake up my code when I receive a full GPS sentence.

Well, during debugging, I found that my DMA IRQ was being handled once, but I couldn't get it to trigger a second time. After wrestling with this for hours, I finally thought, what if the second DMA interrupt really is happening, but because I've got the CPU stopped at a breakpoint, I'm missing it?

So, I took out my breakpoint and instead threw a character out the USART every time the DMA IRA was called. And lo and behold, I got a DMA IRQ five times a second, which is just how often the GPS is sending me data.

Embedded programming can be so frustrating.