ESP32 Programming in Espressif IDE

Mary MbuguaMary Mbugua
7 min read

Introduction

For the longest time in my ESP32 programming journey I have been using Arduino IDE; while it is friendly for beginners, as I have advanced in my programming journey, I have found it constricting and to be honest, not built for professional firmware development at scale. While I appreciate the simple and friendly nature of Arduino IDE and the vast supply of libraries, I have felt it is time to scale into professional development for the ESP32. I have found some significant advantages of using Espressif IDE over Arduino IDE:

Advantages of Espressif IDE for ESP32 Programming

  • Native SDK access- direct access to low-level features of the ESP32: FreeRTOS tasks, memory management, flash partitions, power management, etc

  • Professional debugging tools- breakpoints, variable watches, step through debugging.

  • Advanced project structure- modular, component based structure enables the developer to have clear separation of libraries, drivers and main code and also enables configuration of project structure e.g cmakelists

  • Build and performance optimization - full control over compiler flags, memory usage, partition tables, and optimization levels and ability to strip unused code and optimize firmware size.

  • RTOS awareness- access to FreeRTOS environment enabling me to create tasks, queues, semaphores, and take full advantage of dual-core processing.

  • Industry standard development- Espressif IDE provides:

    • Code auto-completion & IntelliSense

    • Git integration

    • CMake build system

    • Unit testing support

Just to mention a few advantages of the Espressif IDE. With that being said, let’s dive into a few tasks I did in Esperessif IDE to get me started in my journey:

Running code from Terminal using Powershell or ESP-IDF CMD

  1. Open the project and navigate to its path in the file explorer and cd (change directory to it). Ensure you are in the project folder:

  1. Build the project
C:\Users\Administrator\workspace\hello_world>idf.py build

  1. After build is complete, connect your ESP32 board to computer, use device manager to identify COM port.

Flash code:

C:\Users\Administrator\workspace\hello_world>idf.py -p COM10 flash

However, this can easily be done in Espressif IDE by right clicking on the project to build and using UI components to flash the code.

Creating and running tasks using FreeRTOS

FreeRTOS was the whole reason I wanted to migrate to Espressif IDE; so I could’t wait to use it to run a task! Here I created a task using FreeRTOS and run it:

In my main.c file:

#include "freertos/idf_additions.h"
#include "portmacro.h"
#include <stdio.h>

#include "freertos/FreeRTOS.h"
#include "freertos/task.h"


void vTask1Function(void *pvParameters){
    for(;;){
        printf("This is task 1");
        vTaskDelay(2000/portTICK_PERIOD_MS);

    }    
}

void app_main(void){
    xTaskCreate(vTask1Function, "TASK 1", 2048, NULL, 1, NULL);
}

Running the code:

Running tasks on different cores on ESP32

ESP32 boards feature two cores which means they can execute tasks in pararell! In this code I created two print tasks running on the two cores of ESP32:

In my main.c file:

#include <stdio.h>
#include <sys/unistd.h>
#include "freertos/FreeRTOS.h"
#include "freertos/idf_additions.h"
#include "portmacro.h"

void code_for_Task1_core(void *parameter){
    for(;;){
        printf("Task 1 running on core: %d\n", xPortGetCoreID());    
        sleep(5);
    }

}

void code_for_Task2_core(void *parameter){
    for(;;){
        printf("Task 2 running on core: %d\n", xPortGetCoreID());
        sleep(5);
    }

}

void app_main(void)
{
    xTaskCreatePinnedToCore(code_for_Task1_core, "core 0", 2048, NULL, 0, NULL, 0);
    xTaskCreatePinnedToCore(code_for_Task2_core, "core 1", 2048, NULL, 0, NULL, 1);
}

From Espressif documentation:

Running the code:

Importing Espressif project from file system

Suppose you forked a repo from github containing a project built on the ESP-IDF framework, you can easily import it to your IDE and start working on it:

Search for project in directory and import:

Creating components in Espressif IDE

In ESP-IDF (Espressif IoT Development Framework), a component is basically a modular piece of code (library + headers + config) that implements a certain functionality.

Components can be:

  • System components (provided by Espressif inside ESP-IDF).

  • Project components (your own code).

  • External components (downloaded from GitHub or ESP-IDF Component Registry).

Right click on the parent project folder and click “Espressif IDF component“:

The component is created with its header and code files and cmakelists.txt file for additional configurations:

I will use “print_statements“ component I had earlier created.

While using this “print_statements“ component:

this code in print_statements.c file:

#include <stdio.h>
#include "print_statements.h"

void printer_statement(void)
{
    printf("I am a baddie!\r\n");
}

this code in print_statements.h file:

void printer_statement(void);

and this code in main.c file:

#include <stdio.h>
#include <stdbool.h>
#include <unistd.h>
#include "print_statements.h"

void app_main(void)
{
    while (true) {
        printer_statement();
        sleep(3);
    }
}

Running the code:

Editing partition table using ESP- IDF Powershell

The partition table defines how flash memory is divided into sections like:

    • Bootloader

      * Application(s) (factory app, OTA apps)

      * NVS (Non-Volatile Storage)

      * SPIFFS/FATFS (file systems)

      * Custom data partitions

The default table is usually enough for small apps, but advanced use cases require modifications. Suppose you have a large application, you may need to do away with SPIFFS (file systems) assuming you are not using an SD card in your project. Another situation is if you have alot of key value pairs to store in NVS and default allocated memory for NVS is not sufficient. Here is how to do it:

  1. Create a partition table CSV file e.g partitions_example.csv file in the spiffs example in Espressif ide and save it in the project root folder

    Divisions used here:

    1. nvs

      • Type: data

      • SubType: nvs

      • Offset: 0x9000

      • Size: 0x6000 (24 KB)

      • Purpose:

        • Used for Non-Volatile Storage (NVS).

        • Stores Wi-Fi credentials, key-value pairs, calibration values, etc.


  1. phy_init

    • Type: data

    • SubType: phy

    • Offset: 0xf000

    • Size: 0x1000 (4 KB)

    • Purpose:

      • Stores PHY (radio calibration data).

      • Needed for correct Wi-Fi and Bluetooth operation.


  1. factory

    • Type: app

    • SubType: factory

    • Offset: 0x10000 (64 KB)

    • Size: 1M (1 MB)

    • Purpose:

      • The main application firmware will be stored here.

      • Called "factory app" because it's the default firmware that gets flashed.


  1. storage

    • Type: data

    • SubType: spiffs

    • Offset: 0xF0000

    • Size: (large, almost the rest of flash — looks like 0xF0000 in your sheet, ~960 KB)

    • Purpose:

      • This is a SPIFFS filesystem partition.

      • Used for storing files, logs, configuration, web pages, or other data.

Open up menu to configure the partition table via this command to enable the project to use our custom partitions:

C:\Users\Administrator\workspace\spiffs>idf.py menuconfig
  1. In “serial flasher config“ we set up the size of flash memory we have; in my case 2MB. Click “Enter“ key to go in, up and down arrows to navigate, left arrow/ esc key to go back.

  1. Using left arrow, go back then use down arrow to select “Partition Table“. Use “Enter“ key to go into configuration of partition table.

Go in to “Partition Table (Single factory app, no OTA)“ to now change to our custom csv file.

  1. Go down using down arrow and select “Custom partition table CSV“

  1. Enter the name of the CSV file we created in our case “partitions_example.csv“ and ensure to click on “Save“ button.

  1. On going back, you should now see ““Partition Table (Custom partition table CSV); meaning we have changed from initial setting to using a CSV file. Hurray!!!

  1. Click “esc“ key to exit the menuconfig window.

  2. Navigate to project folder in Powershell and run the command “idf.py partition_table“.

The command builds the CSV file we have in our case, partitions_example.csv and generates the binary partition table file (partition-table.bin).

C:\Users\Administrator\workspace\spiffs> idf.py partition-table
  • It places the generated files inside the build/partition_table/ directory:

    • partition-table.bin → binary image that will be flashed.

We are now able to use our custom partition table to set up memory allocation for our ESP32 project in Espreffif IDE!

Credits

  1. Espressif Documentation

  2. YouTube

👉 🤝 Let’s Connect! 🚀

LinkedIn

X

0
Subscribe to my newsletter

Read articles from Mary Mbugua directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Mary Mbugua
Mary Mbugua

Hello reader! Am super excited to have you visit my page! I am Mary Mbaire Mbugua, a lifelong learner in embedded systems. I am constantly in awe by the world of hardware and continuously doing my best to upskill in it. This blog page is my gateway for sharing with the world what I know and continue to lern on a daily. I am particularly passionate about PCB design, hardware troubleshooting, embedded machine learning, firmware development and IoT. Let's learn together!