Streamlined Embedded Development: Raspberry Pi Pico with CLion and J-Link on macOS

This article will provide a comprehensive guide to building an embedded development environment for Raspberry Pi Pico using CLion and the J-Link debugger tool RTT (Real-Time Transfer) on macOS. I will provide the Ubuntu setup instructions in a separate article.

Getting Started with Pico

The official documentation by Raspberry Pi Pico provide a general instruction to install Pico SDK and also necessary toolchain. Please read the following chapters in this PDF (https://datasheets.raspberrypi.com/pico/getting-started-with-pico.pdf).

CLion and J-Link

After installing the Pico SDK and toolchain, the next step is to install the CLion and J-Link applications. Please download the latest J-Link application from its official website (https://www.segger.com/downloads/jlink/). Since it is a .pkg file, simply click on the downloaded file and follow its instructions.

// Run the following command in the terminal to check if all J-Link applications are installed.

ls /usr/local/bin/JLink*

For CLion, please download the latest version from its official website (https://www.jetbrains.com/clion/download/#section=mac). It comes in a .dmg file format, so all you need to do is click on the file and follow the instructions to install it (typically, by dragging the file into your Applications folder). After the installation is finished, verify in your Applications folder to ensure that it has been successfully installed.

Configuring CLion

When you run CLion, you will be asked to run is as 30-day trial or active your license. If you are a student or educator, you can get a free license, so please check out their website (https://www.jetbrains.com/community/education/).

Please choose a new project.

Then, choose “C Executable” and set a location folder (I created ~/home/Dev/hello-pico/).

After creating your project, you may see a small window titled “Open Project Wizard.” Simply click “OK” to close it.

Now, we will edit the CMakeLists.txt file as follows:

cmake_minimum_required(VERSION 3.27)

# please change the account name as yours
include (/Users/ACCOUNT_NAME_HERE/pico/pico-sdk/external/pico_sdk_import.cmake)

set (PROJECT_NAME "hello_pico")

project(PROJECT_NAME C CXX ASM)

set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 17)
set(JLINK_RTT_USE_SYSCALLS ON)

# You may want to change the WiFi login information here.
set(WIFI_SSID "sustainable-music.org")
set(WIFI_PASSWORD "systainable-music.org")

set(PICO_BOARD pico_w)
add_subdirectory(/Users/hamoonyoung/RTT/ ${CMAKE_CURRENT_BINARY_DIR}/jlink_rtt) #hamoonyoung is my account name, so please change it to yours.

pico_sdk_init()

add_executable(PROJECT_NAME main.c)

pico_add_extra_outputs (PROJECT_NAME)
target_link_libraries(PROJECT_NAME
        PUBLIC pico_stdlib
               pico_cyw43_arch_none
        PRIVATE jlink_rtt
)

target_compile_definitions(PROJECT_NAME
        PRIVATE
        WIFI_SSID=\"${WIFI_SSID}\"
        WIFI_PASSWORD=\"${WIFI_PASSWORD}\"
)

target_include_directories(PROJECT_NAME
        PRIVATE
        ${CMAKE_CURRENT_LIST_DIR}
)

pico_enable_stdio_usb(PROJECT_NAME 1)
pico_enable_stdio_uart(PROJECT_NAME 0)

Click on “Edit CMake Profiles…”

Edit the Generator to “Unix Makefiles”, and add an Environment variable with PICO_SDK_PATH=/Users/Your_Account_Name/pico/pico-sdk.

Edit CMake Profiles
-> Add
J-Link Debug
Generator: Unix Makefiles
Environment: PICO_SDK_PATH=/User/Your_Account_Name/pico/pico-sdk

Then, you are ready to run CMake to build! Click the CMake icon at the bottom left (triangle shape) and then click the “Reload CMake Project” button (recycling shape).

At this moment, if you click the “Build” button (hammer icon), you should be able to compile your program. Let’s add the following code to the main.c file, which will flash the onboard LED of Raspberry Pi Pico W and also send messages to the J-Link debugger.

#include <stdio.h>
#include "pico/stdlib.h"
#include "pico/cyw43_arch.h"
#include "SEGGER_RTT.h"

char buff [100];

int main() {
    stdio_init_all();
    if (cyw43_arch_init()){
        sprintf(buff, "Wi-Fi init failed!\n");
        SEGGER_RTT_WriteString(0, buff);
        return -1;
    } else {
        sprintf(buff, "Wi-Fi init succeeded!\n");
        SEGGER_RTT_WriteString(0, buff);
    }
    while (1) {
        cyw43_arch_gpio_put(CYW43_WL_GPIO_LED_PIN, 1);
        sprintf(buff, "Light is on!\n");
        SEGGER_RTT_WriteString(0, buff);
        sleep_ms(500);

        cyw43_arch_gpio_put(CYW43_WL_GPIO_LED_PIN, 0);
        sprintf(buff, "Light is off!\n");
        SEGGER_RTT_WriteString(0, buff);
        sleep_ms(500);
    }
    return 0;
}

Let’s add the Embedded GDB server. (Click the pull-down menu on the right of the Build button, and select “Edit Configurations…”)

Click the left top plus (+) button to add Embedded GDB Server. Then, change the configuration as shown above.

Edit Configuration
	-> Add Configuration: Embedded GDB Server
Name: J-Link
‘Target remot’ argos: localhost:2331
GDB Server: /usr/local/bin/JLinkGDBServerCLExe
GDB Server argos: -if SWD -device RP2040_M0_0

At this point, if you attempt to compile or build, you will encounter an error because RTT is not yet configured. To address this, we need to create an RTT folder in the home directory, ensuring its availability for future projects and enhancing its universality.

cd
mkdir RTT
cd RTT
cp /Applications/SEGGER/JLink/Samples/RTT/*.tgz ~/RTT
tar -xvzf *.tgz
nano CMakeLists.txt

Copy the following code to CMakeLists.txt in RTT.

cmake_minimum_required(VERSION 3.21)
project(RTT)
set(RTT_DIR /Users/Your_Account_Name/RTT/SEGGER_RTT_V794l)
add_library(jlink_rtt STATIC ${RTT_DIR}/RTT/SEGGER_RTT.c ${RTT_DIR}/RTT/SEGGER_RTT_printf.c)
target_include_directories(jlink_rtt
        PUBLIC ${RTT_DIR}/RTT
                ${RTT_DIR}/Config
        )

if (JLINK_RTT_USE_SYSCALLS)
        # Compile all syscall files - their content is protected by ifdefs against using wrong ones
        target_sources(
                jlink_rtt PRIVATE
                        ${RTT_DIR}/Syscalls/SEGGER_RTT_Syscalls_GCC.c
                        ${RTT_DIR}/Syscalls/SEGGER_RTT_Syscalls_IAR.c
                        ${RTT_DIR}/Syscalls/SEGGER_RTT_Syscalls_KEIL.c
                        ${RTT_DIR}/Syscalls/SEGGER_RTT_Syscalls_SES.c
                )
        target_compile_options(jlink_rtt PRIVATE -Wno-pedantic -Wno-sign-conversion -Wno-cast-align)
        target_link_options(jlink_rtt INTERFACE -u_write) #This makes sure that implementation from std would be ignored (i.e. when linking with nosys.spec)
endif()

When you click the debugger button (bug icon), your code must be uploaded to Pico, and the onboard LED should start flashing. Additionally, if you run the RTT Client in your terminal (/usr/local/bin/JLinkRTTClient), you will see messages from Pico in your terminal.

Source Code on Github

The above source code including main.c and CMakeLists.txt are available on Github:

https://github.com/hamoonyoung/hello-pico/

Reply

Your email address will not be published. Required fields are marked *