C/C++

mbed STM32 timer interrupt example

You can use the mbed Ticker API to add a timer interrupt to your mbed application. This example will use a Ticker-based timer interrupt to toggle the LED once per second, for example on the STM32F429I-DISCO board:

#include <mbed.h>

DigitalOut led1(LED1);
Ticker ticker;

/**
 * This function will be run once per second
 */
void timerTick() {
  // Toggle LED
  led1 = !led1;
}

int main() {
  ticker.attach(timerTick, 1.0 /* seconds */);

  // What you do in the main loop is not important
  while(1) {
  }
}

 

Posted by Uli Köhler in C/C++, mbed

How to fix PlatformIO fatal error: stm32f429i_discovery_lcd.h: No such file or directory

Problem:

You are trying to compile your PlatformIO application using  the LCD_DISCO_F429ZI library, but you see an error message like

 #include "stm32f429i_discovery_lcd.h"
          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
compilation terminated.
*** [.pio\build\disco_f429zi\src\main.o] Error 1
In file included from .pio\libdeps\disco_f429zi\LCD_DISCO_F429ZI_ID2432\LCD_DISCO_F429ZI.cpp:19:0:
.pio\libdeps\disco_f429zi\LCD_DISCO_F429ZI_ID2432\LCD_DISCO_F429ZI.h:25:10: fatal error: stm32f429i_discovery_lcd.h: No such file or directory

Solution:

First, ensure that BSP_DISCO_F429ZI is listed is library dependency in platformio.ini like this:

[env:disco_f429zi]
platform = ststm32
board = disco_f429zi
framework = mbed
lib_deps =
    LCD_DISCO_F429ZI
    BSP_DISCO_F429ZI

 

Replace the line

#include "stm32f429i_discovery_lcd.h"

in LCD_DISCO_F429ZI.h with

#include "Drivers/BSP/STM32F429I-Discovery/stm32f429i_discovery_lcd.h"

 

Posted by Uli Köhler in C/C++, PlatformIO

How to fix PlatformIO fatal error: ../Fonts/fonts.h: No such file or directory

Problem:

You are trying to compile a PlatformIO application using the BSP_DISCO_F429ZI library, but you see an error message like

In file included from .pio\libdeps\disco_f429zi\BSP_DISCO_F429ZI_ID2208\Drivers\BSP\STM32F429I-Discovery\stm32f429i_discovery_lcd.c:75:0:
.pio\libdeps\disco_f429zi\BSP_DISCO_F429ZI_ID2208\Drivers\BSP\STM32F429I-Discovery\stm32f429i_discovery_lcd.h:49:10: fatal error: ../Fonts/fonts.h: No such file or directory
 #include "../Fonts/fonts.h"
          ^~~~~~~~~~~~~~~~~~
compilation terminated.

Solution:

The BSP_DISCO_F429ZI package includes fonts.h from the wrong directory. Replace

#include "../Fonts/fonts.h"

by

#include "Utilities/Fonts/fonts.h"

in order to fix the issue. You might need to do that multiple times (in multiple files) in order to fix your build.

Posted by Uli Köhler in C/C++, PlatformIO

How to toggle the STM32F429I-DISCOVERY LED using mbed + PlatformIO

This simple firmare toggles the LED on the STM32F429I-DISC1 discovery board.

#include <mbed.h>

DigitalOut myled(LED1);

int main() {
  while(1) {
    myled = !myled;
    wait(0.5);
  }
}

This will toggle the green (PG13) LED twice per second.

The program is simple: We toggle the LED using myled = !myled; and then use wait(0.5) for 0.5 seconds.

Posted by Uli Köhler in C/C++, mbed

How to fix C/C++ error: call of overloaded ‘abs(uint32_t)’ is ambiguous

Problem:

You are trying to compile a C/C++ program but you see an error message like

src\main.cpp:127:21: error: call of overloaded 'abs(uint32_t)' is ambiguous

that refers to a line like

long timedelta = abs(millis() - startTime);

Solution:

Cast the argument to abs() to int or another suitable type:

long timedelta = abs(((int)millis() - startTime));

That should fix the error.

The reason for the error message is that millis() and startTime are both unsigned integers (uint32_t), hence their difference (millis() - startTime) is also an uint32_t. However it makes no sense to compute the abs() of an unsigned integer since the absolute value of an absolute-value integer is  always the same as the input argument.

Then, the compiler tries to cast the uint32_t to any type that is compatible with abs(), like int, float, double, … but it doesn’t know which of those types is the correct one to cast it to.

By saying call of overloaded abs() the compiler is trying to tell you that there are multBiple argument types with which you can call abs(), including intfloat, double, … – a function with the same name but different argument types is called overloaded.

By saying is ambiguous, the compiler is telling you that it doesn’t know which of those variants of abs() it should call.

Note that the compiler does not know that all overloaded variants of abs() fundamentally do the same thing, so it won’t just cast your uint32_t into any arbitrary type. Also, there are tiny details in how the abs() variants work – for example, float abs(float) will do a different calculation compared to double abs(double) since it computes with 32-bit floating point numbers (float) as opposed to 64-bit floating point numbers (double).

Hence, the compiler can’t just assume that they are all the same and it doesn’t matter which one it calls, even though they represent the same underlying mathematical operation

Posted by Uli Köhler in C/C++, GCC errors

How to fix C/C++ round(): error: invalid operands of types ‘float’ and ‘int’ to binary ‘operator&’

Problem:

You are trying to compile a C/C++ program but you see an error message like

src\main.cpp:357:21: error: invalid operands of types 'float' and 'int' to binary 'operator&'

that refers to a line like

long m = round(v) & 0x7FF;

Solution:

The result of round() is a floating point number. You are trying to use the & operator to perform bitwise AND of a float and an int (0x7FF in the example above). However, you can not perform bitwise operation on floats in C/C++.

In order to fix this, case the result of round() to int:

long m = ((int)round(v)) & 0x7FF;

That should fix the compiler error.

 

Posted by Uli Köhler in C/C++, GCC errors

How to fix Keil EFM8 Warning C280: unreferenced local variable

Problem:

You have a C function like

int myfunc(int value) {
  return 0;
}

but you see a Keil compiler warning like

*** WARNING C280 IN LINE 7 OF C:\Users\uli\MyProject\src\main.c: 'value': unreferenced local variable

Solution:

'value': unreferenced local variable means that you don’t use that variable value in any way.

In the function shown above, you can see that value is the argument of myfunc but myfunc never actually uses the variable.

Do you think that variable should be used in this function?

You need to check your function for typos – the variable is never used at all. Possibly you are using the wrong variable or your function is missing some part of its logic.

Don’t want to use that variable at all?

Usually you can tell the compiler that you don’t want to use that variable by using

(void)value;

but that will produce an expression with possibly no effect warning.

*** WARNING C275 IN LINE 7 OF C:\Users\uli\MyProject\src\main.c: expression with possibly no effect

You can use this hack to avoid this warning:

r = r; // Avoid unused local variable

 

Posted by Uli Köhler in C/C++, EFM8

Minimal ESP-IDF UART transmit example for ESP32 & PlatformIO

The following example writes the string CAFE to UART continously, waiting for 100ms in between:

#include <driver/gpio.h>
#include <driver/uart.h>
// Include FreeRTOS for delay
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>

int app_main() {
    uart_config_t uart_config = {
        .baud_rate = 115200,
        .data_bits = UART_DATA_8_BITS,
        .parity    = UART_PARITY_DISABLE,
        .stop_bits = UART_STOP_BITS_1,
        .flow_ctrl = UART_HW_FLOWCTRL_DISABLE
    };
    uart_driver_install(UART_NUM_1, 2048, 0, 0, NULL, 0);
    uart_param_config(UART_NUM_1, &uart_config);
    uart_set_pin(UART_NUM_1, 10, 9, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);

    // Main loop
    while(true) {
        uart_write_bytes(UART_NUM_1, "CAFE", 5);
        vTaskDelay(100 / portTICK_RATE_MS);
    }
}

 

Posted by Uli Köhler in C/C++, Embedded, PlatformIO

ESP-IDF equivalent to Arduino delay()

You can use the FreeRTOS API to provide a delay similar to the Arduino delay() function in the ESP-IDF framework. FreeRTOS is included in the PlatformIO ESP-IDF default configuration.

First, include the FreeRTOS headers

// Include FreeRTOS for delay
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>

After that, you can use vTaskDelay(...) to perform the delay. This example delays by 500ms:

vTaskDelay(500 / portTICK_RATE_MS);

You can use vTaskDelay() even if not using FreeRTOS tasks.

For a full example, refer to PlatformIO ESP-IDF ESP32 blink example

Posted by Uli Köhler in C/C++, Embedded, PlatformIO

How to set pin to output mode using ESP-IDF

Use this snippet to define a pin as output using the ESP-IDF framework (e.g. using PlatformIO):

gpio_config_t io_conf;
io_conf.intr_type = GPIO_PIN_INTR_DISABLE;
io_conf.mode = GPIO_MODE_OUTPUT;
// Define the pin here (e.g. (1ULL << 2) for GPIO9)
io_conf.pin_bit_mask = (1ULL << 2);
io_conf.pull_down_en = 0;
io_conf.pull_up_en = 0;
gpio_config(&io_conf);

The example above configures GPIO2 as an output. Use (1ULL << 3) to configure GPIO3 as an output

Posted by Uli Köhler in C/C++, Embedded, PlatformIO

How to fix ESP-IDF ‘undefined reference to app_main’

Problem:

You are trying to compile your C/C++ ESP8266/ESP32 firmware using the ESP-IDF framework. Your source code looks like this:

int main() {
    // ...
}

but you only see an error message like this:

.platformio/packages/toolchain-xtensa32/bin/../lib/gcc/xtensa-esp32-elf/8.2.0/../../../../xtensa-esp32-elf/bin/ld.exe: .pio\build\nodemcu-32s\esp-idf\esp32\libesp32.a(cpu_start.c.o):(.literal.main_task+0x18): undefined reference to `app_main'
.platformio/packages/toolchain-xtensa32/bin/../lib/gcc/xtensa-esp32-elf/8.2.0/../../../../xtensa-esp32-elf/bin/ld.exe: .pio\build\nodemcu-32s\esp-idf\esp32\libesp32.a(cpu_start.c.o): in function `main_task':
.platformio\packages\framework-espidf\components\esp32/cpu_start.c:540: undefined reference to `app_main'
collect2.exe: error: ld returned 1 exit status
*** [.pio\build\nodemcu-32s\firmware.elf] Error 1

Solution:

For the ESP-IDF framework, the main() function needs to be named app_main():

int app_main() {
    // ...
}

See PlatformIO ESP-IDF ESP32 blink example for a complete example.

Posted by Uli Köhler in C/C++, Embedded, PlatformIO

PlatformIO ESP-IDF ESP32 blink example

This example is the equivalent of the simple Arduino blink example for ESP32 boards when using the ESP-IDF framework:

#include <driver/gpio.h>
// Include FreeRTOS for delay
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>

#define LED 2 // LED connected to GPIO2

int app_main() {
    // Configure pin
    gpio_config_t io_conf;
    io_conf.intr_type = GPIO_PIN_INTR_DISABLE;
    io_conf.mode = GPIO_MODE_OUTPUT;
    io_conf.pin_bit_mask = (1ULL << LED);
    io_conf.pull_down_en = 0;
    io_conf.pull_up_en = 0;
    gpio_config(&io_conf);

    // Main loop
    while(true) {
        gpio_set_level(LED, 0);
        vTaskDelay(500 / portTICK_RATE_MS);
        gpio_set_level(LED, 1);
        vTaskDelay(500 / portTICK_RATE_MS);
    }
}

 

Posted by Uli Köhler in C/C++, Embedded, PlatformIO

How to read TSV (tab-separated values) in C++

This minimal example show your how to read & parse a tab-separated values (TSV) file in C++. We use boost::algorithm::split to split each line into its tab-separated components.

#include <fstream>
#include <iostream>
#include <string>
#include <vector>
#include <boost/algorithm/string.hpp>

using namespace std;
using namespace boost::algorithm;

int main(int argc, char** argv) {
    ifstream fin("test.tsv");
    string line;
    while (getline(fin, line)) {
        // Split line into tab-separated parts
        vector<string> parts;
        split(parts, line, boost::is_any_of("\t"));
        // TODO Your code goes here!
        cout << "First of " << parts.size() << " elements: " << parts[0] << endl;
    }
    fin.close();
}

 

 

Posted by Uli Köhler in C/C++

C++ read file line by line minimal example

This minimal example reads a file line-by-line using std::getline and prints out each line on stdout.

#include <fstream>
#include <iostream>
#include <string>

using namespace std;

int main(int argc, char** argv) {
    ifstream fin("test.tsv");
    string line;
    while (getline(fin, line)) {
        // TODO Your code goes here. This is just an example!
        cout << line << endl;
    }
    fin.close();
}

 

Posted by Uli Köhler in C/C++

RocksDB minimal example in C++

This minimal example shows how to open a RocksDB database, write a key and how to read it.

#include <cassert>
#include <string>
#include <rocksdb/db.h>

using namespace std;

int main(int argc, char** argv) {
    rocksdb::DB* db;
    rocksdb::Options options;
    options.create_if_missing = true;
    rocksdb::Status status =
    rocksdb::DB::Open(options, "/tmp/testdb", &db);
    assert(status.ok());

    // Insert value
    status = db->Put(rocksdb::WriteOptions(), "Test key", "Test value");
    assert(status.ok());

    // Read back value
    std::string value;
    status = db->Get(rocksdb::ReadOptions(), "Test key", &value);
    assert(status.ok());
    assert(!status.IsNotFound());

    // Read key which does not exist
    status = db->Get(rocksdb::ReadOptions(), "This key does not exist", &value);
    assert(status.IsNotFound());
}

Build using this CMakeLists.txt

add_executable(rocksdb-example rocksdb-example.cpp)
target_link_libraries(rocksdb-example rocksdb dl)

Compile using

cmake .
make
./rocksdb-example

 

Posted by Uli Köhler in C/C++, Databases

How to install RocksDB on Ubuntu

deb-buildscripts provides a convenient build script for building RocksDB as a deb package. Since RocksDB optimizes for the current computer’s CPU instruction set extensions (-march=native), it is required to build RocksDB on the computer where you will run it, or at least one with the same CPU type (generation)

First install the prerequisites:

sudo apt-get -y install devscripts debhelper build-essential fakeroot zlib1g-dev libbz2-dev libsnappy-dev libgflags-dev libzstd-dev

then build RocksDB:

git clone https://github.com/ulikoehler/deb-buildscripts.git
cd deb-buildscripts
./deb-rocksdb.py

This will build the librocksdb and librocksdb-dev packages in the deb-buildscripts directory.

Posted by Uli Köhler in C/C++, Linux

How to download & sync PubMed baseline + updates

In our previous post How to download PubMed baseline data using rsync we showed how you can update PubMed’s baseline data. This dataset is only updated yearly – however, you can download the updatefiles which are typically updated once per day.

The commands to download & sync both sets of files into the PubMed directory:

rsync -Pav --delete ftp.ncbi.nlm.nih.gov::pubmed/baseline/\*.xml.gz PubMed/
rsync -Pav --delete ftp.ncbi.nlm.nih.gov::pubmed/updatefiles/\*.xml.gz PubMed/

The --delete option will ensure that files that are deleted on the server will also be deleted locally. For example, when a new baseline dataset is being published, you need to delete the old year’s files to avoid having to process duplicate data.

Posted by Uli Köhler in Bioinformatics, C/C++

How to control boost::iostreams gzip compression level

In our previous post How to gzip-compress on-the-fly in C++ using boost::iostreams we showed how to create a gzip-compressing output stream using the boost::iostreams library.

This example shows how to control the compression rate of gzip_compressor:

Instead of constructing boost::iostreams::gzip_compressor() without arguments, use boost::iostreams::gzip_params(level) as the argument, where level (1..9) represents the compression level with 9 representing the highest compression level and 1 representing the lowest compression level. Higher levels of compression lead to reduced filesizes but are slower (i.e. consume more CPU time) during compression.

If filesize matters to you, I recommend choosing level 9 since compression even with the high level is extremely fast on modern computers.

Full example:

#include <fstream>
#include <iostream>
#include <boost/iostreams/filtering_streambuf.hpp>
#include <boost/iostreams/copy.hpp>
#include <boost/iostreams/filter/gzip.hpp>
using namespace std;

int main(int argc, char** argv) {
    if(argc < 2) {
        cerr << "Usage: " << argv[0] << " <output .gz file>" << endl;
    }
    //Read filename from the first command line argument
    ofstream file(argv[1], ios_base::out | ios_base::binary);
    boost::iostreams::filtering_streambuf<boost::iostreams::output> outbuf;
    outbuf.push(boost::iostreams::gzip_compressor(
        boost::iostreams::gzip_params(9)
    ));
    outbuf.push(file);
    //Convert streambuf to ostream
    ostream out(&outbuf);
    //Write some test data
    out << "This is a test text!\n";
    //Cleanup
    boost::iostreams::close(outbuf); // Don't forget this!
    file.close();
}
cmake_minimum_required(VERSION 3.0)
find_package(Boost 1.36.0 COMPONENTS iostreams)

include_directories(${Boost_INCLUDE_DIRS})
add_executable(iostreams-gz-compress iostreams-gz-compress.cpp)
target_link_libraries(iostreams-gz-compress ${Boost_LIBRARIES})

 

Posted by Uli Köhler in C/C++

How to check if XML element exists in PugiXML

Checking if an element exists in PugiXML is simple: Just call bool(element) or use the element directly inside an if clause:

// Example on using bool(element)
cout << "<root-element> exists: " << std::boolalpha
     << bool(doc.child("root-element")) << endl;
cout << "<not-root-element> exists: " << std::boolalpha
     << bool(doc.child("not-root-element")) << endl;

// Example on using the element directly inside an if clause
if(doc.child("root-element")) {
    cout << "Yes, <root-element> exists!" << endl;
}

Full example:

#include <iostream>
#include <pugixml.hpp>
using namespace std;
using namespace pugi;

int main() {
    xml_document doc;
    xml_parse_result result = doc.load_file("test.xml");

    // Example on using bool(element)
    cout << "<root-element> exists: " << std::boolalpha
         << bool(doc.child("root-element")) << endl;
    cout << "<not-root-element> exists: " << std::boolalpha
         << bool(doc.child("not-root-element")) << endl;

    // Example on using the element directly inside an if clause
    if(doc.child("root-element")) {
        cout << "Yes, <root-element> exists!" << endl;
    }
}
add_executable(pugixml-example pugixml-example.cpp)
target_link_libraries(pugixml-example pugixml)
<?xml version="1.0" encoding="UTF-8"?>
<root-element>Test text</root-element>

Compile using

cmake .
make
Posted by Uli Köhler in C/C++

How to gzip-compress on-the-fly in C++ using boost::iostreams

This minimal example shows you how to write data to a .gz file in C++, compressing the data on-the-fly using boost::iostreams. Using the modern iostreams layer, as opposed to a block-based approach like zlib allows you to use the full power and ease-of-use of std::ostream.

#include <fstream>
#include <iostream>
#include <boost/iostreams/filtering_streambuf.hpp>
#include <boost/iostreams/copy.hpp>
#include <boost/iostreams/filter/gzip.hpp>
using namespace std;

int main(int argc, char** argv) {
    if(argc < 2) {
        cerr << "Usage: " << argv[0] << " <output .gz file>" << endl;
    }
    //Read filename from the first command line argument
    ofstream file(argv[1], ios_base::out | ios_base::binary);
    boost::iostreams::filtering_streambuf<boost::iostreams::output> outbuf;
    outbuf.push(boost::iostreams::gzip_compressor());
    outbuf.push(file);
    //Convert streambuf to ostream
    ostream out(&outbuf);
    //Write some test data
    out << "This is a test text!\n";
    //Cleanup
    boost::iostreams::close(outbuf); // Don't forget this!
    file.close();
}
cmake_minimum_required(VERSION 3.0)
find_package(Boost 1.36.0 COMPONENTS iostreams)

include_directories(${Boost_INCLUDE_DIRS})
add_executable(iostreams-gz-compress iostreams-gz-compress.cpp)
target_link_libraries(iostreams-gz-compress ${Boost_LIBRARIES})

 

Posted by Uli Köhler in Boost, C/C++