Setting Up A Development Environment

Part I in “Building REXIS, a Cortex-M microcontroller Real Time OS”

As we stopped development of the ImageCraft embedded tools in 2020, when I decided to rewrite my message passing kernel REXIS (Real-time EXecutive for Intelligent Systems) in modern C++ and planning to eventually evolve it into a full operating system, I needed to set up a new development environment. In this post, I described the tools I ended up using, and why I made the decisions that I did.

To do basic C++ embedded development with the Cortex-M microcontrollers, at the minimum, you need:

  • A C/C++ compiler
  • An IDE, or an editor with separate build system
  • A hardware development board
  • Hardware debug pod
  • Software debugger

My Selections

My desktop runs Windows 10. Here’s what I ended up with:

  • Compiler: GNU embedded ARM C++ compiler 
  • Editor: Microsoft’s VSCode 
  • Build system: make 
  • Source control: git
  • Visual debugger: Segger’s Ozone
  • Hardware board and debug pod: ST-Nucleo with STMF411RE M4 microcontroller
  • MSYS2 for Linux tools

The total cost is less than $15 for the ST-Nucleo. Everything else is free or free for noncommercial use. MSYS2 is only needed for my convenience. None of the tools requires it.

The choice for the compiler is obvious as the GNU embedded compiler is the standard. It’s free, generates excellent code, and is well supported by the silicon vendors and others.

VSCode (“Visual Studio Code”) is a highly extendable editor that works fast and well. It comes from Microsoft, but is not related to their traditional Visual Studio IDE. It’s built on top of the Electron platform, meaning that it actually uses the same Javascript NodeJS engine that powers web applications. Even though it is built on web technologies, it is as fast as other editors I have used, with great support for C++ (and other languages) using extensions. In particular, the Intellisense C++ support makes it easy to navigate C++ source files.

As a long time Unix / Linux user, using make is second nature to me and is a no-brainer for a generic build system. When the project gets more complex, I will switch to using a more capable build system such as CMake or Ninja.

Although I can debug using the command line gdb GNU debugger, it is much nicer to have a GUI debugger. Toward that goal, Segger’s Ozone is a natural choice. You can use the built-in file browser to set breakpoints, and it has the usual set of tools such as stack trace, step-over and step-into, code disassembly etc. The best feature is the seamless integration of assembly and C++ instruction-aware stepping

Finally, for hardware prototyping, the ST-Nucleo lines of development boards are true bargains. For an average sale price of around $15, there are versions with different STM microcontrollers, from the low power L0 series, to the powerful F7 and H7 series. They come with a built-in debug pod on board, and for the best experience with Segger’s tools, you can program the debug pod to act as a Segger JLINK pod. You can even reverse the change if you wish.

Alternatives

There are many alternatives. You can use the silicon vendors’ supplied (usually free) IDE and graphical tools. They usually (always?) include the GNU C/C++ compilers. For example, ST’s CubeIDE is competent. It’s slow since it is based on Eclipse and the code generated by the graphical tools are the bloated “LL” low level or “HL” high level ST API code, but it does work well. It can be a daunting experience to program using the ST IO registers directly, so this is a good compromise.

Other silicon vendors offer similar software and hardware development solutions. The cost is usually free or low since they want you to buy millions of their chips, and providing no / low cost development tools is one way for them to grab developers’ attention.

I generally prefer to roll-my-own, and eschew the bloatware, but for people just starting, these can be good choices.

What’s Next

In the next part, I will describe how to set up the GNU environment.

Posted in Uncategorized | Leave a comment

From C to C++

As a long time C programmer and compiler writer (I even wrote a book on C), when I pivoted away from running ImageCraft (see below if you missed the announcement on our website), I knew I would need to beef up on my C++ skills.

Like most C programmers who learned about C++ in the earlier days, I know about classes, inheritances, virtual methods and all the Object Oriented concepts. As a compiler writer, I even know how I would go about implementing them. In the last decade, even though I was not using C++ much, I kept up to date with the development news, and read about templates, template metaprogramming, and other new C++ features. Without actual usage experience, some of them just sound very odd, for example, template metaprogramming sounds like one of those “if they are so weird, they better be very useful” items.

Spoiler alert, you can write a Fibonacci function or something similarly, and have the compiler evaluate it at compile time using template metaprogramming. Indeed, C++ template metaprogramming is Turing Complete, a fact that was surprising even to the designers.

No matter, I dived in and did a small project writing a Lisp interpreter in C++. I even used lambda functions! Then at my new $dayjob, I pushed to implement the project in C++, utilizing the power of the Standard Template Library (STL) and more.

After six months of development, the upshot is that an equivalent C implementation would probably be at least three times as large in source code size, and would have taken at least two or three times as long to write. Using STL and utilizing the “algorithm” helper functions, the code is readable, succinct, and without baggage.

While I have not done outrageously weird stuff with templates, judicious use of template does exactly what it promises: compile time type checking polymorphism. Unlike Object Oriented Programming using virtual functions et al, there is no runtime penalty.

On top of that, utilizing the implicit memory allocation and deallocation in the class’ constructors and destructors and lifetime scoping rules, there is no explicit calls to “new” (or “malloc”, in C parlance) or “delete” even though dynamic data structures are being used. It’s almost as good as runtime garbage collection, without the overhead.

STL’s ease of use and the runtime performance of the class design allow us to come up with innovative data architecture that is superior to traditional designs. While I cannot discuss the product in any details, further posts will explore some of these features of C++.

Posted in Uncategorized | Leave a comment

OpenCart 3.x Forgotten Password Error

We are setting up a new site for our CANUSB product shop (currently at https://canusb-shop.com) using OpenCart 3.x. While testing various functions, I found that when using the “forgotten password” feature, the system correctly sent a recovery email with a link, but clicking the link resulted in an error message:

Password reset code is invalid or was used previously!

Searching for the errors on the web did not result in promising fixes. There are some similar problems with OpenCart 2.x but the issues do not apply. Certainly, the fixes do not help.

Time to do some bug chasing myself then. To send a reset code, OC sends a randomly generated string as a validating code. Looking at the sent email carefully, I noticed something wonky:

Do you see it? The words “The IP” does not have a space in front, and “The” became part of the code, so when the link is clicked, the incorrect code is posted to the server and the server rejects it.

The fix is simple, edit the file catalog/controller/mail/forgotten.php on the OpenCart installation directory, and change the following line:

$data[‘reset’] = str_replace(‘&’, ‘&’, $this->url->link(‘account/reset’, ‘code=’ . $args[1] . ‘ ‘ /* rfm add space to protect the code */, true));

Basically, as ” . ‘ ‘” after “$args[1]” to add a space (‘.’ is the PHP string concatenation character.

Posted in Uncategorized | Leave a comment

Connecting a Smart.IO Module to a ST-Nucleo With Jumper Wires

Flash sales announcement: you can now purchase a ST-Nucleo F411 for just $1 if you also purchase any version of the JumpStart Embedded Tools for Cortex. Click here for more details, and here to browse the different Cortex tools.

With Smart.IO, you can create an app for your embedded system with no wireless or app coding. It’s perfect for when you are making prototypes and wish to easily add some fancy app-based UI controls to your gadget (because who wants to use hard-to-see LCD displays or twiddly little knobs and buttons?).

The Smart.IO module has a 12-pin header, and you can use an optional shield carrier to attach the module to an Arduino style board such as the ST-Nucleo. However, for quick prototyping, you can forego using the shield and just use a set of jumper wires to connect between the module and a prototyping board.

Here’s an example of the module connected to an ST-Nucleo Morpho connector using female-to-female jumper wires. Conveniently, all the signals on the ST-Nucleo that are used by Smart.IO are located in a line.

Pin 1 of the Smart.IO header is located at the lower right position if you put the header at the top with the top of the module facing up.

12 10 8 6 4 2
11 9 7 5 3 1

pin numbering of the Smart.IO header

If you’d like to do this yourself, the pin diagrams are documented in the Smart.IO user guide here:
https://imagecraft.com/documentation/smart-io-documentation. The relevant information is:

ST Morpho Connector on the right hand side

Morpho PinSmart.IO PinNOTES
4 – AVDD 3 – VddAVDD is not available in all Arduino
boards. Use 3V3 in that case.
5 – GND12 – GND
6 – SCK 9 – SCKSTM32F411 PA5
7 – MISO 8 – MISOSTM32F411 PA6
8 – MOSI 7 – MOSISTM32F411 PA7
9 -nCS10 – nCSSTM32F411 PB6
10 – nReset 4 – nResetSTM32F411 PC7
11 – Host IRQ11 – Host IRQSTM32F411 PA9

To use the Arduino connector instead of the Morpho connector, shift the pins up by one position, i.e. AVDD<->Vdd is now pin 3 instead of pin 4.

This is a simple way to evaluate and use Smart.IO. As jumper wires are prone to failure if you insert and remove them too many times, we will be releasing a low-cost PCB with connectors to avoid using jumper wires. Stay tuned for more information when it becomes available.

Whoa! Last minute update. Here’s a 3-D rendering of the connector PCB, tentatively named SmartConnect. The PCB and Gerber files will be uploaded to github and we will sell assembled and blank PCBs for low prices.

Posted in Uncategorized | 1 Comment

ctxLink – A Wireless Debug Pod With Built-in GDB Server

What’s better than a debug pod for the Cortex MCU with built-in GDB server? Make a wireless pod version of course (it also works with a USB cable), and now it’s $50 off preproduction price. Get it now for just $99:

https://www.crowdsupply.com/sid-price/ctxlink

Posted in Uncategorized | Leave a comment

Stepping Up to C++ Templates

In the first decade after C++ was released, there were two frequent statements made about the new programming language, especially in the C community:

  1. C allows you to shoot your foot off, but C++ allows you to shoot the whole leg off.
  2. C++ is “just an object-oriented language”.

If you have heard of either of these, it’s time to put those ideas away. Looking at C++ in 2019, it’s clearly a rich language that provides many features for writing safe, efficient code, using concepts such as generic programming. The expressive power of modern C++ comes mainly from the use of templates and their uses in generic programming, and not so much from object-oriented concepts (although it does support object-oriented programming with class inheritance and virtual functions). This article introduces some of the basic ideas with templates.

Over their years of programming, most C programmers will have accumulated sets of routines for linked lists, arrays, stacks etc. in their coding libraries; for example, stack routines for pushing, popping, and searching for items on a stack. In C++, you may implement a stack for holding integer data with code that looks something like this:

class int_stack {
 public :
     bool push(int item);
     int pop(void);
 …
 };

A class is basically a struct declaration that includes member functions and other advanced features. The declaration above declares a class name “int_stack”, which contains two member functions, push and pop, and other items not listed here (shown as “…”).

In C, a set of such routines would only work for one data type (e.g., int). If you want stack routines for double data types, you will have to duplicate the routines, and change the names and internals to work with double data types, though most of the code would be identical. If you are clever, perhaps you might use void pointers and such to make the same set of routines work with different data types, but it would be a hack.

C++ templates solve that. Here’s an example of a template stack class:

template <typename T> stack {
public:
 bool push (T item);
 T pop(void);
…
};

Note 1: This is just a simple example. The actual implementation of the stack in the standard C++ library STL (Standard Template Library) is far more capable and complex than this example.

Note 2: You may also write the template declaration with the word “class” instead of “typename”, e.g. “template <class T> stack { …”.

A template declaration such as above does not create anything per se, not even a class type. However, if you use it to declare variables, e.g.:

stack<int> int_stack;
stack<double> double_stack; 

“stack<int>” is known as a parameterized type. With these two declarations, the compiler creates two declarations, as if you have written something akin to:

class int_stack {
public :
 bool push(int item);
 int pop(void);
…
};

class d_stack {
public :
 bool push(double item);
 double pop(void);
…
};

Templates eliminate having to write similar-looking code, reducing the effort to write and maintain a project. Note that there is only one template name (“stack”) which is decorated with the actual data type to declare a class type (e.g. “stack<int>”). While this simple example might be done using clever C preprocessing macros, the full power of templates cannot be replaced by C macros.

If you use the template declaration multiple times, e.g:

stack<int> stack1; 
stack<int> stack2; 

The compiler is smart enough to know that the two implicitly created stack classes are the same. 

Baby Steps to Generic Programming

Now imagine you want to add an “==” equality operator to the stack class (in C++, you can overload the meaning of any C operator symbol within a class, but you cannot create new operator symbols that do not exist in the base language):

To do this, first, let’s look at an example of non-template operator definition:

class int_stack {
 public :
    bool push(int item);
    int pop(void);
    bool operator==(int_stack &);
 …
 };
 

The definition of the operator, if written outside of the class declaration, starts with:

 bool int_stack::operator==(int_stack &stack2) ... 

This declaration is for an == operator of a non-template class “int_stack”. In this example, there are two symbols not used in C:

  1. :: is the scope resolution operator. The left-hand side is either a class name or a namespace name (we will not be discussing namespace in this short article). In this example, you can think of the words “int_stack::operator==” to mean “this is the == operator for the int_stack class”.
  2. &, as used in a variable declaration, after the type name and before the variable name as shown above, signifies that this is a reference to the variable. A reference has the same semantic as a pointer-to a variable (i.e. in a function call, a reference parameter allows efficient passing of the argument, and allows the function to modify the argument), except that you don’t use the * indirect operator to access the variable, as the variable name itself suffices. For a struct/class variable, this means that you use the dot “.” field member operator, instead of the “->” field member operator.

For a template, operator declaration is just a little bit more complicated:

template <typename T> stack {
 public:
     bool push (T item);
     T pop(void);
     bool operator==(stack<T> &stack2);
 …
 };

The definition of the operator, if written outside of the class declaration, starts with:

template <typename T> bool stack<T>::operator==(stack<T> &stack2) … 

A parameterized type “stack<T>” is used in place of a concrete type “int_stack” and the whole declaration is prefixed with “template <typename T>” to tell the compiler that this is a template declaration. Once you understand the basics of operator declaration, this is just a bit more syntactic sugar on top.

The code for the template == operator could be something as follows:

template <typename T> bool stack<T>::operator==(stack<T> &stack2)
     {
     if (size() != stack2.size())
         return false;
     for (unsigned i = 0; i < size(); i++)     
         if (elems[i] != stack2[i])         
             return false; 
    return true; 
    }

There is a lot to unpack here. Looking at the code, you may make the following observations:

  1. The stack class supports a size() function, presumably to indicate the number of elements in the class.
  2. The stack class includes a member named “elems”, presumably containing the actual elements of the stack.
  3. The stack class supports an array indexing [i] operator, where [i] presumably returns the i’th sequential member of the stack.
  4. You may apply the array indexing [] to either a class object (e.g. stack2[i]) or to the elements member (e.g. elems[i]), presumably with the same semantic effect.
  5. Each element is compared against the element in the other stack in the same position. This implies that the element data type must support the == and != operators as well.

Taking together, the function returns true if and only if the stacks have the same number of elements and each element compares equality. 

Power of Templates

So why is this important? The template mechanism allows the above code to work for any stack<T> objects, as long as they implement the features as noted above. Not only does this reduce the amount of code you have to write, it allows you to use templates (and their routines) written by other people, saving you much design, implementation, and debugging time.

I have already mentioned the STL (Standard Template Library), which provides templates for stacks, vectors, lists, hash tables, etc. There are more advanced libraries such as Boost, which provides support for linear algebra, pseudorandom number generation, multithreading, image processing, regular expressions, and unit testing. Boost contains over eighty individual libraries. Without templates, STL and Boost would not have been possible.

Any C++ programmers who haven’t done so yet should get familiar with STL and Boost libraries.

More C++: Iterators and New FOR loop

Instead of using array indexing syntax, most classes that support sequential access also provides iterators, and the above function can be rewritten (only the main loop is given here) as:

for (auto & iter = elems.begin(); iter != elems.end(); iter++)
    {
    if (iter != stack2[i])
        return false;
    ++i;
    }

So what are the differences?

  1. The C keyword “auto” has now been repurposed to request the compiler to deduce the data type of the variable automatically. The compiler does this by looking at the type of the right hand side of the assignment expression. There is no need to write out the data type for “iter”. This is a powerful feature, especially if the data type declaration is complex (the data type for an iterator is indeed fairly complex).
  2. There are iterator functions and idioms that allow you to sequentially access the elements of the stack just like using the array indexing [i].

As they say, there’s more! Instead of using explicit iterator, you can also write:

for (auto & elem::elems)
    {
    if (elem != stack2[i])
        return false;
    } 

This new “for” loop syntax, which assumes an iterator over a class object, combined with “auto” type deduction, allow you to iterate through the elements simply and elegantly.

A Stupid Implementation

If you just want to get your feet wet and become familiar with C++ syntax, you can implement a dumb version of the stack template based on the STL’s vector class. Of course the STL has a far more capable version of stack template with a lot more features, but nothing beats learning a language by actually typing in some code:

#include <vector>

template <typename T>
class stack {
public:
    bool push(T item) { elems.push_back(item); return true; }
    T pop(void) { T val = elems.back(); elems.pop_back(); return val; }
    bool operator==(stack<T> &stack2);
    unsigned size(void) { return elems.size(); }
    T& operator[](int i);

private:
    vector<T> elems;
};

The “==” operator is as described above, and I will leave it as an exercise to the readers to implement the [] array indexing operator.

You can write a simple test like this:

int main() 
    {
    stack<int> istack, istack2;

    istack.push(42);
    istack.push(1000);
    int x = istack.pop();

    cout << "Hello world! x is " << x << endl;

    if (istack == istack2)
        cout << "stacks equal" << endl;

    cout << istack.pop() << endl;
    if (istack == istack2)
        cout << "stacks equal" << endl;
    } 

When run, you should see:

Hello world! x is 1000
42
stacks equal

Summary

C++ is a mature programming language, capable to efficiently write high performance programs. The core of its usability and efficiency is the extensive use of templates. This article only briefly scratches what is possible.

Posted in Uncategorized | Leave a comment

Flatten the Learning Curve for Programming STM32 MCUs

One of the most difficult issues in moving to Cortex-M MCU development from an 8-bit ecosystem is the complexity of the I/O peripherals. The Cortex-M peripherals are more capable and more flexible, but are also more difficult to use and write programs for. To help users gain proficiency as quickly as possible, we created the JumpStart API. You can see on the linked page how it clearly beats the competition such as mBed and ST’s libraries. In this post, we will look at some practical examples.

Challenge 1: Write a program that toggles an LED using a timer interrupt – let’s say, timer1 – with your favorite programming platform for an STM32F MCU. Let’s assume that the LED is attached to PA5, which will be toggling at 1Hz . Ready? Here is the complete code fragment if you are using JumpStart API. :

Continue reading
Posted in Uncategorized | Leave a comment

Your chance to JUMPSTART Cortex MCU development

Are you interested in upgrading your ease-and-speed-of-programming options?

Are you still working with 8-bit MCUs and wish to take advantage of the more powerful and even lower cost Cortex-M MCU, but are worried about making the jump? Are you working with slow Eclipse-based IDE or ST CubeMX and wish that just loading the tools won’t require taking a long coffee break? Are you daunted by how difficult it can be to just get an LED blinking and wish for an easier way to do it? Are you frustrated with unsupported free tools that cost you time and money to get started?

Your wish has now come true. With ImageCraft’s latest 9.12 release of the JumpStart C++ for Cortex, you can develop for most popular Cortex-M MCUs, with great visual debugging as well. Thanks to the efficiently-written JumpStart API (JSAPI), if you are using a supported $13 ST-Nucleo board, you can get “Hello World” and blinking LEDs working in literally minutes after you install the programs.

ImageCraft makes JumpStart C++ easy to use because we also use it ourselves. Confused by the difference between newlib or nanolib, and which to use? So are many other people, so we make it simple to use (a single checkbox is all you need to switch between the two libraries) and we even wrote a blog article about it to demystify the issues:

And now: ImageCraft is the first compiler vendor to provide seamless one-checkbox support for QFPlib, an alternative floating-point library that takes just over 1K bytes of code, including trigonometric functions! https://imagecraft.com/blog/2019/05/qfplib-a-compact-floating-point-library-for-cortex-m/

You may currently purchase the compiler plus the visual debugger for $300, a discount of $100! And, what could make this even better? How about taking an additional 10% off until June 15, 2019? Use the coupon code CRAZY10OFF (valid for the bundle purchase only) and follow the instructions here: https://imagecraft.com/buy/how-to-use-coupon-code

Posted in Uncategorized | Leave a comment

QFPlib, A Compact Floating Point Library for Cortex-M

Cortex-M0 based MCUs are notable for their low cost and relatively smaller amount of available flash memory. If you wish to use floating point operations but are running tight on space, QFPlib is a great alternative. The core single-precision floating-point add/sub/mul/div/cmp operations take less than 400 bytes. According to QFPlib’s author, the corresponding routines in the GCC native library, by contrast, are over 2700 bytes in size, and the whole M0 library, including some trigonometric routines, comes in just slightly over 1K bytes.

QFPlib is even smaller than floating-point routines for other micros, including some such as the one for MSP430, which is known to have high code density. This table is a screencap from the author’s page at https://www.quinapalus.com/qfplib.html This is a comparison for the core arithmetic routines only:

But how about the downsides of QFPlib? There are two major ones:

1. QFPlib is released using GNU GPL V2 license with alternate licensing possible from the author. This means that your code will also have to be released under GPL V2 if you use QFPLib (however, see below).

2. You have to manually call QFPlib functions to perform even the basic operations such as add, e.g.: instead of writing “float_a + float_b”, you write “qfp_fadd(float_a, float_b)”

For licensing issues for a commercial firmware developer, practically this means that you can try out QFPlib if you are running low in memory, and if you later want to use it in a final product where you will not be releasing your code under GPL, then you will have to contact the author and purchase a commercial use license. I do not know what the cost of a commercial license is, but the author has said that it is reasonable.

Regarding ease of use, if you are using JumpStart C++ for Cortex, now you can use QFPlib by just enabling it with a checkbox:

Once done, your (single precision) floating-point operations will be done “automagically” using the compact QFPlib with no source code changes needed! Just write “float_a + float_b”, and QFPlib will be used.

QFPlib also includes trigonometric functions that are much smaller than the default GCC code. For those, you will have to explicitly call the functions due to the way GCC works. You can find out more details in our online manual: https://imagecraft.com/documentation/jumpstart-c-documentation

Finally, QFPlib also comes in a Cortex-M3 version where the focus is on high-accuracy operations rather than small size. Again, the single checkbox shown above will enable it for -M3/M4/M7 based MCUs.

Posted in Uncategorized | Leave a comment

How Much Flash and SRAM Does My Project Use?

When developing firmware for an embedded project, it is important to know how much flash and SRAM the program is using. This allows you to make the best decision on whether the chosen MCU has sufficient resources for your needs.

By default, GCC does not give any information regarding program size. However, GCC does include a utility that can help, sensibly it is called “size.exe” (or “arm-none-eabi-size.exe” for the embedded GCC version). If you run the program as follows:

c:\iccv9cortex\gnuarm\bin\arm-none-eabi-size -A -x bin\Debug\Test.elf

The /path/to/ is as installed by ImageCraft’s JumpStart C++ program, but any embedded GCC installation will have this program. The last argument is the input file (in default ELF format). “-A” means to output in SysV format (Berkeley format is the other option), and “-x” is to use hexadecimal output. The above produces something as follows:

bin\Debug\TestDriver.elf  :
section size addr
.text 0x6720 0x8000000
.ARM.extab 0x258 0x8006720
.ARM.exidx 0x2f0 0x8006978
.ARM.attributes 0x2a 0x8006c68
.data 0x804 0x20000000
.bss 0x9c0 0x20000804
._user_heap_stack 0x2804 0x200011c4
.debug_line 0x405a 0x0
.debug_info 0x24c75 0x0
...
.debug_ranges 0x60 0x0
.comment 0x75 0x0
.debug_frame 0x2dd4 0x0
.stab 0x9c 0x0
.stabstr 0x14f 0x0
Total 0x3d8f3

Each line represents a “region” in the output file. If a region has an address of 0x0, it means that it is not using any space in the target MCU and most likely only contains debug information, and will be used for debugging only. The regions’ names and allocations are controlled by the linker script used so your output may look slightly different.

The entries of interest are: .text this is the size of your program, i.e. flash usage. In this example, 0x6720 or 26400 bytes of flash is used, plenty left over from the 512K STM32F411RE that I am using.

.data and .bss are the static SRAM usage. .data has the global/static variables that have initialization, and .bss has the global/static variables that have no initialization (but are initialized to zero per C/C++ definition). In this case, 4548 bytes are needed, also significantly less than the 128K bytes of SRAM available on the F411RE.

Finally, ._user_heap_stack is the area reserved for memory allocated at runtime, heap is for memory used by malloc/free, and C++’s “new” etc., and stack is used for mainly for local variables and function context. As the runtime memory size changes as your program is run, this is only the minimum amount set in the linker script. Your program controls how much dynamic memory it uses. Stack usage depends on the call patterns in your program and how much stack space (e.g. local variables) a function uses. A future blog post will describe one way to determine stack usage of a program.

You can write a simple utility program to process the “size” output to give a simple summary, which is what we have done with the JumpStart C++ tools. A typical post-build message looks like this:

ELF file output size
Code size: 26400 bytes starting at 0x08000000
SRAM data: 4548 bytes starting at 0x20000000
Heap and Stack: 10244 bytes heap starts 0x200011C4 stack starts 0x200039C8

With size.exe and some processing, it is simple to see your program’s flash and SRAM requirements.

Posted in Uncategorized | Leave a comment