© Warren Gay 2018

Warren Gay, Beginning STM32, https://doi.org/10.1007/978-1-4842-3624-6_20

20. New Projects

Warren Gay

(1)St. Catharines, Ontario, Canada

Starting a new project from scratch can be a lot of work. That is why this chapter is focused on helping you get started with the minimum of drudgery. I’m also going to point you to a few details that have been ignored for the sake of simplicity that might be important to your project. This will leave you in the driver’s seat.

Project Creation

The first step in a new project is to create its subdirectory, Makefile, then import the FreeRTOS source modules and a starting configuration file named FreeRTOSConfig.h. Yes, you can do this manually or with a script, but the provided Makefile will do this for you.

First, locate the right starting directory:

$ cd ~/stm32f103c8t6/rtos

Think of a good subdirectory name for your project that doesn’t already exist. For this example, we’ll call it myproj. To create a project named myproj, perform the following make command:

$ make -f Project.mk PROJECT=myproj
...bunch of copies etc...
****************************************************************
Your project in subdirectory myproj is now ready.


1. Edit FreeRTOSConfig.h per project requirements.
2. Edit Makefile SRCFILES as required. This also
   chooses which heap_*.c to use.
3. Edit stm32f103c8t6.ld if necessary.
4. make
5. make flash
6. make clean or make clobber as required
****************************************************************

If you now produce a recursive list of your subdirectory, you will see that it has been populated with several files:

$ ls -R ./myproj
FreeRTOSConfig.h   Makefile     main.c         rtos
stm32f103c8t6.ld


./myproj/rtos:
FreeRTOS.h         heap_1.c     list.h         portmacro.h
task.h             LICENSE      heap_2.c       mpu_prototypes.h
projdefs.h         tasks.c      StackMacros.h  heap_3.c
mpu_wrappers.h     queue.c      timers.h       croutine.h
heap_4.c           opencm3.c    queue.h        deprecated_definitions.h
heap_5.c           port.c       semphr.h       event_groups.h
list.c             portable.h   stdint.readme

Makefile

Listing 20-1 illustrates the Makefile that will be created for you. This file should normally be edited slightly to reflect the source modules that you will use. This Makefile uses several macros to define the overall project. Let’s examine those now.

Listing 20-1 Default Project Makefile
0001: #########################################################
0002: #  Project Makefile
0003: #########################################################
0004:
0005: BINARY     = main
0006: SRCFILES    = main.c rtos/heap_4.c rtos/list.c rtos/port.c
                   rtos/queue.c rtos/tasks.c rtos/opencm3.c
0007: LDSCRIPT   = stm32f103c8t6.ld
0008:
0009: # DEPS      = # Any additional dependencies for your build
0010: # CLOBBER  += # Any additional files to be removed with
                          "make clobber"
0011:
0012: include ../../Makefile.incl
0013: include ../Makefile.rtos
0014:
0015: #########################################################
0016: #  NOTES:
0017: #    1. remove any modules you don't need from SRCFILES
0018: #    2. "make clean" will remove *.o etc., but leaves *.elf, *.bin
0019: #    3. "make clobber" will "clean" and remove *.elf, *.bin etc.
0020: #    4. "make flash" will perform:
0021: #       st-flash write main.bin 0x8000000
0022: #########################################################

Macro BINARY

This macro defines the name of your compiled executable. By default, this is set to main so that main.elf is produced when the project is built. By all means, change this to something more exciting.

Macro SRCFILES

This macro defines the name of the source files that will be compiled into the final executable main.elf. The default is to include the following source files:

  • main.c (main should match the name used in the BINARY macro)

  • rtos/heap_4.c

  • rtos/list.c

  • rtos/port.c

  • rtos/queue.c

  • rtos/tasks.c

  • rtos/opencm3.c

The module main.c (or otherwise named) is the module you will write and develop. The remaining modules are support modules, which will be discussed later on. Some of these are optional. For example, if you don’t use FreeRTOS message queues, you can leave out the module rtos/queue.c (with the appropriate changes to FreeRTOSConfig.h).

If you have additional source files (in addition to main.c), add them to the SRCFILES list. They too will be compiled and linked into the final build.

Macro LDSCRIPT

The provided Makefile sets this to stm32f103c8t6.ld. This points to a file in your project directory, which you have already seen in Chapter 9, “Overlays.” Many projects can use this file unchanged. If your project has special needs like overlays, it can be altered.

Macro DEPS

If you have special dependencies, you can define them with this macro. For example, if you have a text file like mysettings.xml, which affects the build of main.elf, then to force a rebuild of main.elf add the following:

DEPS = mysettings.xml

Macro CLOBBER

The make files have been written to support some basic targets, including clobber. For example:

$ make clobber

This command eliminates files that were built and are unnecessary to keep. For example, all object files (*.o) and executables (*.elf) would be deleted as a cleanup operation. This also guarantees that everything is built from scratch the next time you perform a make.

Sometimes a build procedure creates other objects that can be removed after the build is complete. If a file.dat is generated by the build process and you want it cleaned up after a clobber, add it to the macro:

CLOBBER   = file.dat

Included Makefiles

To reduce the footprint of the project Makefile and centralize other definitions, two more Makefiles are included in your project file:

  • ../../Makefile.incl (~/stm32f103c8t6/Makefile.incl)

  • ../Makefile.rtos (~/stm32f103c8t6/rtos/Makefile.rtos)

The first of these defines macros and rules for building projects. If you need to make project-wide enhancements to the make rules, this is the place to start.

The second of these simply adds the subdirectory ./rtos to be searched for include files for FreeRTOS builds:

TGT_CFLAGS      += -I./rtos -I.
TGT_CXXFLAGS    += -I./rtos -I.

Header Dependencies

The DEPS macro described earlier adds dependencies for building main.elf. What if you have another header file named myproj.h that, if changed, would cause a recompile of main.o? This can be done with the usual Makefile dependency rule added:

main.o: myproj.h

This informs the make command that main.c should be recompiled into main.o if the datestamp of file myproj.h is newer. That might save you from chasing bugs related to a header-file change when main.o was not rebuilt when it should have been.

Compile Options

Sometimes a special compile option is needed for certain modules. In the OLED project, this was used to suppress some compiler warnings from a third-party source module:

ugui.o:  CFLAGS += -Wno-parentheses

This compile option is only added to the compile of ugui.o to suppress warnings about brackets that should be added for clarity.

Flashing 128k

If you haven’t already done so, change to your project subdirectory. After you build your project with

$ cd ./myproj
$ make

you need to program the STM32 flash storage. By default, the make command is set up to do this with the following:

$ make flash
arm-none-eabi-objcopy -Obinary main.elf main.bin
/usr/local/bin/st-flash  write main.bin 0x8000000
...

The first step in this is to convert the elf file (main.elf) to a binary image (main.bin). The ARM version of the objcopy utility performs that duty. After that, the st-flash utility is used to program the STM32.

Most, if not all, STM32F103C8T6 chips will support flashing to 128k. You will need to have the newer version st-flash utility installed. To flash more than 64k, perform the following:

$ make bigflash
arm-none-eabi-objcopy -Obinary main.elf main.bin
/usr/local/bin/st-flash --flash=128k write main.bin 0x8000000
...

The new option --flash= 128k is supplied to the st-flash utility to disregard the device ID and flash up to 128k worth of memory.

The real question is whether all STM32F103C8T6 chips do indeed support 128k. All four of my units did, purchased from different eBay sources. In fact, there is only one online reported instance of this not working. Was this pilot error? Or is it that only the lower 64k is factory tested and guaranteed? If someone knows the answer, I would like to know.

FreeRTOS

An important part of your project is the FreeRTOS components. Some are optional, while others are mandatory. Let’s look at each in turn.

rtos/opencm3.c

This module was written by the author and is not actually part of FreeRTOS. It is required to connect the libopencm3 framework into FreeRTOS. The module is shown in Listing 20-2.

Listing 20-2 Source Module ~/ stm32f103c8t6/rtos/opencm3.c
0001: /* Warren W. Gay VE3WWG
0002:  *
0003:  * To use libopencm3 with FreeRTOS on Cortex-M3 platform, we must
0004:  * define three interlude routines.
0005:  */
0006: #include "FreeRTOS.h"
0007: #include "task.h"
0008: #include <libopencm3/stm32/rcc.h>
0009: #include <libopencm3/stm32/gpio.h>
0010: #include <libopencm3/cm3/nvic.h>
0011:
0012: extern void vPortSVCHandler( void ) __attribute__ (( naked ));
0013: extern void xPortPendSVHandler( void ) __attribute__ (( naked ));
0014: extern void xPortSysTickHandler( void );
0015:
0016: void sv_call_handler(void) {
0017:   vPortSVCHandler();
0018: }
0019:
0020: void pend_sv_handler(void) {
0021:   xPortPendSVHandler();
0022: }
0023:
0024: void sys_tick_handler(void) {
0025:   xPortSysTickHandler();
0026: }
0027:
0028: /* end opncm3.c */

As the source code indicates, these libopencm3 functions call into FreeRTOS. For example, function sys_tick_handler() is invoked by libopencm3 when the system timer tick interrupt occurs. But the call to xPortSysTickHandler() is a FreeRTOS function that handles the system tick operations.

rtos/heap_4.c

This is the FreeRTOS module used throughout this book. However, there are actually multiple choices possible. Quoted from the www.freertos.org web page 1 :

  • heap_1  – the very simplest; does not permit memory to be freed

  • heap_2  – permits memory to be freed, but not does coalescence adjacent free blocks

  • heap_3  – simply wraps the standard malloc() and free() for thread safety

  • heap_4  – coalescences adjacent free blocks to avoid fragmentation; includes absolute address placement option

  • heap_5  – as per heap_4, with the ability to span the heap across multiple non-adjacent memory areas

Some of these source modules can be affected by the FreeRTOSConfig.h macro setting configAPPLICATION_ALLOCATED_HEAP. Simply swap the rtos/heap_4.c mentioned in the Makefile with the module of your choice.

Required Modules

In addition to the dynamic memory module rtos/heap_*.c, the following are normally required modules for FreeRTOS:

  • rtos/list.c (internal list support)

  • rtos/port.c (portability support)

  • rtos/queue.c (queue and semaphore support)

  • rtos/tasks.c (task support)

Depending upon the options chosen in your FreeRTOSConfig.h file, in your project directory, you may be able to exclude one or two modules for a smaller build. For example, if you don’t use queue, mutex, or semaphore support, you can avoid linking in rtos/queue.c.

FreeRTOSConfig.h

This is your project-level FreeRTOS configuration file. This include file contains macro settings that affect the way that the FreeRTOS modules are compiled into your project. They may also affect any macro calls invoked by your application. You should make clobber before you rebuild if any of the values in that file are changed. Remember that you are building both the O/S and the application together.

Listing 20-3 provides a partial listing of what is contained in the FreeRTOSConfig.h file. The first section configures items such as the CPU clock rate (configCPU_CLOCK_HZ). Others determine features like preemption (configUSE_PREEMPTION).

One pair of important macro settings are configCPU_CLOCK_HZ and configSYSTICK_CLOCK_HZ. For use with libopencm3, using a 72 MHz clock, you normally want to configure configSYSTICK_CLOCK_HZ as follows:

#define configSYSTICK_CLOCK_HZ ( configCPU_CLOCK_HZ / 8 )

If you get this wrong, a program using vTaskDelay() or other time-related functions will be incorrect. You can check this by running the demo in stm32f103c8t6/rtos/blinky2. When incorrectly configured, the blink will not be half a second.

Listing 20-3 Partial Listing of FreeRTOSConfig.h, Used in the RTC Project
/*-----------------------------------------------------------
 * Application-specific definitions.
 *
 * These definitions should be adjusted for your particular hardware and
 * application requirements.
 *
 * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE
 * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE.
 *
 * See http://www.freertos.org/a00110.html.
 *----------------------------------------------------------*/


#define configUSE_PREEMPTION            1
#define configUSE_IDLE_HOOK             0
#define configUSE_TICK_HOOK             0
#define configCPU_CLOCK_HZ              ( ( unsigned long ) 72000000 )  
#define configSYSTICK_CLOCK_HZ   ( configCPU_CLOCK_HZ / 8 )
#define configTICK_RATE_HZ       ( ( TickType_t ) 1000 )
#define configMAX_PRIORITIES     ( 5 )
#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 128 )
#define configTOTAL_HEAP_SIZE    ( ( size_t ) ( 17 * 1024 ) )
#define configMAX_TASK_NAME_LEN  ( 16 )
#define configUSE_TRACE_FACILITY      0
#define configUSE_16_BIT_TICKS        0
#define configIDLE_SHOULD_YIELD       0
#define configUSE_MUTEXES             1
#define configUSE_TASK_NOTIFICATIONS  1
#define configUSE_TIME_SLICING        1
#define configUSE_RECURSIVE_MUTEXES   0


/* Co-routine definitions. */
#define configUSE_CO_ROUTINES         0
#define configMAX_CO_ROUTINE_PRIORITIES ( 2 )


/* Set the following definitions to 1 to include the API function, or zero
to exclude the API function. */


#define INCLUDE_vTaskPrioritySet        1
#define INCLUDE_uxTaskPriorityGet       1
#define INCLUDE_vTaskDelete             0
#define INCLUDE_vTaskCleanUpResources   0
#define INCLUDE_vTaskSuspend            1
#define INCLUDE_vTaskDelayUntil         1
#define INCLUDE_vTaskDelay              1

The macro configTOTAL_HEAP_SIZE is important to configure if you encounter the following error:

section '.bss' will not fit in region 'ram'

As defined:

#define configTOTAL_HEAP_SIZE        ( ( size_t ) ( 17 * 1024 ) )

FreeRTOS will allocate 17k to the heap. But as you develop your killer application and use more static memory areas, the remaining SRAM storage may shrink to the point where the heap won’t fit. This will prevent the link step from completing. What you can do is reduce the heap size until it builds. Advanced users can look at the memory map produced to see how much you can re-increase the heap. Or you could just guess by increasing the heap until it fails to build.

Other configuration macros like INCLUDE_vTaskDelete simply determine whether that level of support should be compiled into FreeRTOS for your application. If you never delete a task, why include code for it?

All of these configuration options are documented at the FreeRTOS website and in their fine free manual.

User Libraries

It is common practice to place commonly used routines like USB or UART drivers in a library. Once you develop these, you want to reuse them. You may have noticed that this was done in some of our demo projects in this book. By default, all programs include headers from ~/stm32f103c8t6/rtos/libwwg/include and link to the library directory ~/stm32f103c8t6/rtos/libwwg, linking with libwwg.a.

Within the directory ~/ stm32f103c8t6/rtos/libwwg/src are some source modules that go into that static library. These get compiled and the object modules placed into libwwg.a. But there is a problem here that you should be aware of.

These are all compiled against the following header file:

~/stm32f103c8t6/rtos/libwwg/src/rtos/FreeRTOSConfig.h

This is likely different from your project-level file FreeRTOSConfig.h. If the configurations differ in a material way, the best approach is to copy the needed source files into your project directory and add them to your Makefile (SRCFILES). When you do that, you guarantee that the subroutines use the FreeRTOSConfig. h that the rest of your application is compiled with.

Once again, this is related to the fact that every build of your application also includes the build of the operating system. Much of it is driven by macros, so header files play a significant role.

Rookie Mistakes

One rookie mistake that all of us get bitten by from time to time is to make a change to a structure in a header file that affects modules that don’t get recompiled. When a structure is altered, the offsets of members change. A previously compiled module will continue to use the old member offsets.

Ideally, the Makefile would list every dependency or have it generated and then included. However, this isn’t always done, or done perfectly enough, especially during frantic project development.

If you have changed a struct (or class in C++), it is recommended practice to perform a make clobber first so that everything is recompiled from scratch. In huge projects, this approach is impractical. But for small projects, this ensures that all modules are compiled from the same headers.

Do you have a bug that doesn’t make sense? The impossible is happening? Perhaps you need to rebuild your project from scratch to make sure that you aren’t chasing toolchain problems.

Summary

This chapter has prepared you for creating your own STM32 projects using FreeRTOS. You’ve reviewed the FreeRTOS modules that go into your build, as well as the glue module that links libopencm3 to FreeRTOS. With the ability to configure FreeRTOSConfig.h, you can direct how your project is built.

Bibliography

  1. “Memory Management [More Advanced].” FreeRTOS—Memory management options for the FreeRTOS small footprint, professional grade, real time kernel (scheduler). Accessed February 1, 2018. https://www.freertos.org/a00111.html .

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.16.48.181