Developing C/C++ Firmware for the ESP32 WROVER Module

This tutorial shows how to create a basic project for the ESP32 WROVER-KIT-3 module, program the FLASH memory and debug it via the on-board JTAG. We will create a basic project that will blink the red, green and blue on-board LEDs from different FreeRTOS threads and will show how to debug it and change various configuration-related settings.

Before you begin, install VisualGDB 5.4 or later.

  1. Start Visual Studio and open the ESP-IDF project wizard:01-newprj
  2. Select “Create a new project based on a sample project”:02-newsample
  3. On the next page select the location of your ESP32 toolchain. If you don’t have any toolchains installed yet, click “Download more toolchains” and VisualGDB will automatically install a compatible ESP32 toolchain:03-toolchain
  4. The next step is to select the sample project that will be used as a template for our project. Pick the “Blink” project from the “get-started” folder and click “next”:04-blink
  5. In order to enable the on-board JTAG debugging functionality, install the 7 jumpers (may not included with the board) as shown below:wroverconnWARNING: the picture above shows the previous version of the ESP-WROVER board. If you are using ESP-WROVER v4.1 or later, see this page for the exact names and locations of the jumpers. Once the jumpers are installed, connect the board via USB.
  6. VisualGDB should automatically recognize the board as long as you are using the latest ESP32 toolchain:05-devkit
  7. Click “Test” to automatically test the JTAG connection. VisualGDB will automatically install all necessary drivers and will use the correct JTAG settings:06-testFinally Press “Finish” to create the project.
  8. By default, the “ledblink” project will toggle the GPIO #5 that is not connected to any on-board LEDs. To change this, we will first need to look up the GPIO numbers for the RGB LED from the ESP-WROVER-KIT schematic:rgbThen open VisualGDB Project Properties and set the “Blink GPIO Number” to 0, corresponding to the red LED:
    07-blink
  9. If you build and run your project now, it will repeatedly blink the red LED. To support 3 independent LED channels, we will now modify the KConfig.projbuild file to have 3 separate configuration options instead of just 1:
    menu "Example Configuration"
     
    config BLINK_GPIO_RED
     int "Red LED GPIO number"
     range 0 34
     default 5
     help
     GPIO number (IOxx) to blink on and off.
     Some GPIOs are used for other purposes (flash connections, etc.) and cannot be used to blink.
     GPIOs 35-39 are input-only so cannot be used as outputs.
     
    config BLINK_GPIO_GREEN
     int "Green LED GPIO number"
     range 0 34
     default 5
     help
     GPIO number (IOxx) to blink on and off.
     Some GPIOs are used for other purposes (flash connections, etc.) and cannot be used to blink.
     GPIOs 35-39 are input-only so cannot be used as outputs.
     
    config BLINK_GPIO_BLUE
     int "Blue LED GPIO number"
     range 0 34
     default 5
     help
     GPIO number (IOxx) to blink on and off.
     Some GPIOs are used for other purposes (flash connections, etc.) and cannot be used to blink.
     GPIOs 35-39 are input-only so cannot be used as outputs.
     
     
    endmenu

    08-rgbconfig

  10. Save the file and reopen VisualGDB Project Properties. Now you can set the pin numbers for the red, green and blue LEDs via the regular ESP-IDF configuration GUI:09-gpios
  11. Change the main file extension to .cpp and replace its contents with the following code:
    struct BlinkParameters
    {
        gpio_num_t Pin;
        unsigned Period;
    };
     
    void blink_task(void *pvParameter)
    {
        struct BlinkParameters *pBlinkParameters = (struct BlinkParameters *)pvParameter;
     
        gpio_pad_select_gpio(pBlinkParameters->Pin);
        /* Set the GPIO as a push/pull output */
        gpio_set_direction(pBlinkParameters->Pin, GPIO_MODE_OUTPUT);
        while(1) {
            /* Blink off (output low) */
            gpio_set_level(pBlinkParameters->Pin, 0);
            vTaskDelay(pBlinkParameters->Period / 2 / portTICK_PERIOD_MS);
            /* Blink on (output high) */
            gpio_set_level(pBlinkParameters->Pin, 1);
            vTaskDelay(pBlinkParameters->Period / 2 / portTICK_PERIOD_MS);
        }
    }
     
    extern "C" void app_main()
    {
        //The period definitions must be static, as otherwise they would be located on the stack 
        //and would get overwritten once the threads actually start up.
        static struct BlinkParameters pins[] = {
            { .Pin = (gpio_num_t)CONFIG_BLINK_GPIO_RED, .Period = 200}, 
            { .Pin = (gpio_num_t)CONFIG_BLINK_GPIO_GREEN, .Period = 500, },
            { .Pin = (gpio_num_t)CONFIG_BLINK_GPIO_BLUE, .Period = 1000 }
        };
     
        for (auto &pin : pins)
            xTaskCreate(&blink_task, "blink_task", configMINIMAL_STACK_SIZE, &pin, 5, NULL);
    }

    It will create 3 instances of the blink_task thread, each one targeting a different LED with a different period:10-code

  12. Press F5 to start debugging and observe the RGB LED. You will see each channel toggling with its own period:wroverled
  13. Set a breakpoint after one of the gpio_set_level() calls. The breakpoint will get immediately triggered by one of the threads. You can see the other threads via the Debug->Windows->Threads command:
    11-stack
  14. Another option to quickly view various ESP-IDF threads would be via Debug->Parallel Stacks command. It will immediately show that 2 threads are waiting inside the vTaskDelay() function called from blink_task() while 1 thread is directly executing the blink_task():12-pstack