embedded firmware from scratch - part 3

Which code does execute first when a microcontroller starts to run? Many would say:

Firmware execution starts at the main() function

Eventhough that is a reasanoble and expected answer, a lot should have already happened when the execution gets there.

Let’s take a look at a few crucial steps for embedded development that are usually ignored when coding for complete operating systems like Linux, where the toolchain will probably take care of everything correctly. I’m talking about startup code and the linker script. They will provide the very first instructions that execute when the processor starts and tell the linker where to put the binary bits that the compiler it is creating, every function and most of the variables will get an address in memory base on this.

This is the third article in a series about creating a firmware project from scratch. The other ones are available at PART 1 and PART 2.

Continue reading...

embedded firmware from scratch - part 2

This is the second article of an endeavor to develop an embedded software project for ARM microcontrollers that works standalone. It won’t require any vendor specific tools in its development cycle. Take a look at PART 1 to understand the beginning of this and the main pain points that I see when depending on IDE projects for firmware development.

At this point you may be thinking:

“Yet another ARM embedded tutorial…”

And… yes, but also no. There are multiple steps, configurations and tools that must work together in order to build a functional firmware. Always remember that nothing comes for free when building projects from scratch. There is for sure a lot of information about each one of these tiny subjects scattered in multiple articles in the internet. Although many of them focus on one part and assume that you’ll be able to figure out (or already know) all the other dependencies.

This won’t be a deep dive in each tiny detail, since it would be an endless series of multiple articles. The intention here is documenting the minimum required to get a basic working firmware, explained in a way that I’ve wanted to find some time ago.

Continue reading...

embedded firmware from scratch - part 1

Starting a new firmware development project requires multiple decisions, even after the microcontroller and hardware are already selected. One of the first steps is defining the development environment, that in my conception includes:

  • code versioning system (git)
  • language (C or C++)
  • toolchain (compiler, linker, assembler)
  • build system (shell, make, ninja, CMake)
  • debugger

For many years I’ve let the microcontroller vendor’s IDE take care of most of these decisions. Now I’ve decided to challenge myself and create a new firmware project from scratch, without using an IDE, in order to learn what takes to make everything work together. This has required learning about multiple tools and the workflow to combine their functions.

This is the first article about this endeavor, focusing on a few obstacles that arise due using vendor tools (IDE, toolchain, libraries, etc) instead of assuming full control of your project and setting it up from scratch.

Continue reading...

getting a Black Magic Probe

I’ve heard recently in a C++ conference talk that:

C programmers love debugging, they do all the code just to get to the debugging part”.

Am I going to disagree with that? Yeah, probably.

  • applying TDD and intelligent development practices intend to help on that
  • good tests will avoid a lot of time spent on debugging directly in the target
  • debugging test code in the host machine is a lot easier since it removes limits from the remote debugging.

With that out of the way, a good programmer and debugger is still a required tool for embedded development. A bad one may result in many hard to detect problems and a lot of frustration. Anyone that took some time researching about ARM debuggers has for sure read many talking about the Black Magic Probe from 1BitSquared. I’ve finally decided to take some time and test it to find out how much better it can be than a regular ST-Link.

Continue reading...

continuous UART RX with DMA

This article will continue the analysis and implementation of a UART driver that was started in the last post, but now focusing in data reception instead of transmission. As explained before, there will be no use of TDD at this moment since the main focus are using the UART functions provided by the STM32 hardware abstraction layer libraries, comparison between the methods provided and how to better use them in a firmware project.

Continue reading...

improving UART TX with DMA

There will always be peripherals to use and drivers to implement in embedded programming. And learning how to use them isn’t usually a moment to apply TDD since it’s more about testing configurations and commands than well structured functions that will make their way to production code.

With that out of the way, this post will be the first of a few ones that won’t include test code, they are actually the working result and documentation of a learning through development and testing process I took recently. These efforts tend to get closer to Extreme Go Horse programming than to TDD actually 👀 but they are an important part of the journey.

I’ve been thinking about the development of a communication protocol and drivers for the bugfree-robot. Its hardware design provides three main communication ports: 2 full duplex UARTs and one USB port. None of them would work directly for wireless telemetry (USB for sure not) although it is possible to connect simple and cheap Bluetooth-serial modules like the HC-05, HC-06, HM-10 or similar. They don’t allow a high throughput but it may be enough for transmitting information about its sensors and control parameters.

Continue reading...

returning

Sorry (and thanks for the support) if anyone has been browsing this page in this period looking for new content. The last post was uploaded in the beginning of 2020 and I’ve been putting my efforts in other stuff since then and don’t see any need to get deeper in this matter. After a long time I’m returning to write here.

My main objective of this website/blog/endeavour is still on documenting my studies on embedded development, learning new tools, techniques and help other doing so in the journey.

This robot will probably have another purpose than proposed before, a long time has passed and this challenge does not motivate me much anymore. Since the hardware will stay the same and the resources connected to it as well, that decision is not so important right now.

For now the idea is returning to code and write about development of drivers and libraries, while integrating TDD in the workflow. For the future, probably adding a FreeRTOS or even learning how to use one that I’ve never tried like Zephyr.

I’ve been using more Python lately, learning about databases, MQTT and other technologies, so maybe I’ll come to a cool idea that integrates a lot of stuff and makes (a bit of) sense. That may result in bringing a few diverse topics around here.

I intend to post more regularly, although not sticking to an interval for now, let me first get the momentum back and see at which speed it takes me.

New content uploaded (probably) in the next week!

global return code and log libraries

All my articles in the bugfree_robot project until now were dedicated to detailing Test Driven Development, its setup and basic steps. I’ve described all those steps in a slow pace and very detailed manner. At this moment the project base is ready as well as simpler test features that will reflect the majority of the tests in many embedded projects.

The goal from now on is developing many libraries for the firmware while defining an architecture that will connect all those low and high level libraries. The concepts already shown about setting up test files and inserting them in the Makefile won’t be written in the articles from now on but will always be available in the commits of course. Any new important coding and test technique used in the code will be presented and described in the article.

So with all this out, it is time to move on with the firmware. This step is about coding two new libraries. One of them is nothing more than a header file actually, but it is an important one. They are:

  • return codes library
  • log utility library
Continue reading...

setup build system at Sublime Text Editor

I’m used to coding in Sublime Text 3 while developing code for the tests and the libraries for my projects. It’s a software that provides many smart shortcuts that can get a lot done faster when you get used to them. I know many ones advocate against any kind of visual software for coding and will go hands tied with vim until death but I’ve never gotten there. It may be a good tool after the “getting used to it” period but it never got me into really trying to acquire a relationship. By the way, for those able to read in portuguese, a friend of mine has shared a guide with many pointers in setting up an efficient vim working environment, check it out here.

My standard working setup has a Sublime window open showing the full repository folder tree in the left plus two vertical files open plus a terminal window (in another monitor preferentially) in the test folder so a simple make command will build and run my tests. This works pretty well and causes me no problems but one sometimes: building the tests after modifying a few files on sublime but forgetting to save one of them, getting test results that were not expected and taking a few minutes to realize this simple problem. This problem was fixed as a side effect when I’ve decided to setup a build system inside Sublime to run my tests.

Continue reading...

setting up automatic tests to pinpoint your errors

It is usual to keep building and running the tests in the workstation along the development. This is a main part of the TDD cycle as explained here and shown in this article. Discipline is required in order to never forget running the tests after making changes although every developer take a leap of faith that simple fix that will never go wrong. Those are the risky moments where we change a small thing, go directly to committing/pushing it the Git repository and realizing later that some test is broken.

This is one of the reasons to setup a test build service in the Git repository that will run the tests every commit that is pushed to it. After the tests are built there will be a marker in each commit showing if the tests passed or not and allowing opening the build/run log messages of that test execution.

Continue reading...