Работаем с Raspberry Pi Pico RP2040 в Eclipse под Windows

Сайт: 

Автор: Андрей Осипов

Дата: 30/12/2022

Бродя по просторам Aliexpress в поисках очередной интересной отладочной платы или модуля обратил внимание на Raspberry Pi Pico на чипе RP2040. Сначала меня удивила низкая цена платы (около 4$ на декабрь 2022). Удивила, потому что миникомпьютер, пусть даже на базе Arm-процессора, просто не может стоить так дешево. При более детальном изучении информации понял, что это обычный микроконтроллер с двумя ядрами Cortex-M0+. Тем не менее для своей ценовой категории он обладает достаточно неплохими характеристиками и вполне может использоваться в любительских проектах:

  • Два ядра Arm Cortex-M0+ @ 133 МГц
  • 264 КБ памяти (284 КБ если отключить XIP кеширование и использовать память USB)
  • 2 МБ флеш-память с XIP кешированием. В RP2040 нет встроенной флеш-памяти, поэтому чип распаян на плате. У RP2040 есть поддержка до 16 МБ внешней флеш-памяти
  • DMA контроллер
  • 4 x 12-разрядных аналоговых входа (на Pico доступно для пользователя 3 из них)
  • 2 × UART
  • 2 × SPI
  • 2 × I2C
  • 16 × PWM каналов
  • Встроенный сенсор температуры
  • Всего 30 GPIO пинов (3,3 вольта)
  • MicroUSB B порт с USB 1.1 контроллером и поддержкой хоста
  • 2 × PIO блока для своих собственных интерфейсов
  • 2 x PLL (один для USB, второй для остального)
  • Поддержка UF2 для загрузки бинарников
  • Поддержка SWD для загрузки и отладки
  • Поддержка спящих режимов и пониженной частоты для снижения потребления

Raspberry Pi Pico RP2040

Официальная распиновка платы:

Распиновка Raspberry Pi Pico RP2040

Для разработки программ под микроконтроллер RP2040 производитель предлагает два комплекта:

Т.к. с языком программирование Python я не знаком, то для себя я выбрал привычный вариант SDK под C/C++. Также на github есть SDK под Arduino. Так что любителям этой платформы рекомендую его рассмотреть. Сам комплект Pi Pico C/C++ SDK базируется на системе сборки CMake. На официальном сайте есть ссылка на репозиторий с примерами и хорошая документация по их сборке с помощью CMake, а также импорте проекта в Eclipse. Кроме официальных источников информации по работе с платой Pico на данный момент есть неплохие статьи и на других сайтах, ссылками на которые я бы хотел поделиться:

Казалось бы информации по RP2040 предостаточно. Но все же есть несколько неприятных вещей, которые побудили меня написать эту статью:

  • все примеры прекрасно собираются в ОС Linux, но сделать то же самое в Windows не так-то просто. Лично для меня по прежнему основной рабочей системой остается Windows 7 и хотелось бы вести разработку в ней;
  • даже если скачать готовый Toolchain под Windows и собрать примеры в MSYS2 (что на практике не получается сделать двумя командами cmake и make, а сопровождается кучей геморроя неустановленных зависимостей/неподходящих версий пакетов и т.д... Да что говорить, когда такое даже под Linux не всегда собирается?), то после иморта проекта в Eclipse оказывается, что работать с ним дико неудобно. Например: чтобы добавить новый исходный файл в проект, необходимо прописать его в CMakeLists.txt, а если придется добавить целую библиотеку, то для нее нужно писать отдельный CMakeLists.txt. Для меня, как для человека не знакомого с CMake, эта задача достаточно нетривиальна. Также при сборке примеров в MSYS2 CMake создаст Makefile-ы, в которых будут указаны пути к исходникам в стиле Linux, что-то типа /d/pico-sdk/src вместо D:\pico-sdk\src, что так же станет камнем преткновения при попытке пересборки проекта в Eclipse. На мой взгляд сборка с помощью CMake удобна только для готового проекта, когда нужно получить файл прошивки на выходе, но никак не для разрабатываемого;
  • RP2040 подерживает отладку по интерфейсу SWD, но у вас под рукой может не оказаться подходящего отладчика. На данный момент известно несколько инструментов отладки:
    1. Отладка с помощью J-Link. Вполне рабочий вариант, если у вас в наличии есть оригинальный девайс, а не китайский клон древней версии (в чем я сильно сомневаюсь). Как настроить отладку с помощью J-Link описано в статьях, ссылки на которые приведены выше. Мой китайский G-Link v8 не смог подключиться к чипу по SWD, потому этот вариант я отбросил
    2. Отладка с помощью Black Magic Probe. По сути это опенсорсный проект JTAG/SWD отладчика на чипе STM32F103. Официальный сайт проекта: https://black-magic.org. Black Magic Probe на GitHub: https://github.com/blackmagic-debug/blackmagic. Некоторые компании выпускают отладчики на базе Black Magic Probe, но вряд ли у кого-то они есть в наличии. Зато у многих в хозяйстве есть китайский клон ST-Link v2, который можно перепрошить прошивкой Black Magic Probe. На хабре есть статья как превратить широко известную плату Blue Pill в Black Magic Probe: Черная магия голубой таблетки (делаем программатор Black Magic Probe из модуля на базе STM32F103). Но ничто не мешает нам проделать те же действия для ST-Link. Конечно сделать это через UART будет не совсем удобно, т.к. придется припаивать провода прямо к ногам микроконтроллера, зато на плате выведены линии SWD-интерфейса и можно воспользовать вторым программатором ST-Link. Как это делается хорошо описано здесь: Делаем ST-Link V2.1 из китайского ST-Link V2. Т.е. подводя итог, вам нужно выполнить следующие шаги: собрать прошивку Black Magic Probe, зашить через UART или SWD файл blackmagic_dfu.bin - это загрузчик, позволяющий обновлять прошивки программатора, с помощью утилиты dfu-util прошить устройство основной прошивкой blackmagic.bin После этого устройство в системе будет представлено двумя последовательными портами, из которых понадобится только GDB Server. Кстати, если вы хотите, чтобы ваш программатор по прежнему определялся как ST_Link, то есть вариант воспользоваться утилитой stlink-tool, подробнее об этом читайте здесь: https://electronics.stackexchange.com/questions/592979/programming-rp2040-with-st-link На сколько я понял, stlink-tool записывает прошивку blackmagic.bin по определенному смещению в памяти контроллера, не затирая программу самого ST-Link. Но у этого метода есть один недостаток: каждый раз при подключении устройства к компьютеру вам необходимо будет запускать stlink-tool, чтобы программатор запустился с нужной версии программы. И наверняка при обновлении прошивки ST-Link будет затерта программа Black Magic Probe. Ну и вот казалось бы - идеальный вариант для отладки! Но на практике оказалось, что в связке с Eclipse отладка запускается только один раз, потом отладчик зависает и помогает только переподключение устройства к USB. В общем все работает очень глючно и нам не подходит;
    3. Отладка с помощью второй платы Pico. Для этого необходимо одну из них прошить специальной программой, которую можно взять здесь: https://github.com/raspberrypi/picoprobe. Этот вариант я еще не успел попробовать, потому как не имею второй платы в наличии. Возможно позже напишу об этом. Наверняка многие читатели так же как и я не подозревали о том, что им нужно купить две платы Pico вместо одной. Потому этот вариант отладки пока тоже отбрасываем;
    4. Отладка с помощью прошивки pico-debug, которую можно найти здесь: https://github.com/majbthrd/pico-debug. Там же можно найти готовые бинарные файлы *.uf2 для программирование через USB. Отладчик работает по следующему принципу: зажав кнопку Boot подключаем плату Pico к компьютеру, на компьютере она определяется как флеш-накопитель, на флеш-накопитель копируется файл прошивки pico-debug-gimmecache.uf2, после чего загрузчик (bootrom) производит загрузку программы в RAM и далее она исполняется на ядре 2 микроконтроллера и абсолютно не мешает загружать код во Flash и остальную область RAM, и исполнять программу на ядре 1. Естественно, в данном случае ядро 2 не может быть использовано. Неприятное ограничение, но не критичное на первых порах работы с микроконтроллером. Устройство на шине USB определяется системой как USB-HID и реализует интерфейс CMSIS-DAP. Далее с помощью OpenOCD запускается GDB-сервер. Этот вариант отладки мне показался более приемлемым, потому о нем пойдет речь ниже;

Никогда не был большим любителем CMake и работы в командной строке, да и просто не хочется пока тратить время на его изучение. Потому предлагаю рассмотреть свой простой и понятный вариант сборки проекта. Все операции я проделывал в системе Windows 7, но, думаю, все будет работать и в более новых версиях Windows.

Инструменты

Если не установлены, качаем и устанавливаем следующие программы:

Условимся, что распаковку Toolchain и OpenOCD мы произведем в каталог с:\pico.

При установке Eclipse необходимо выбрать версию Eclipse IDE for Embedded C/C++ Developers.

Так же нам нужно клонировать репозиторий pico-sdk в каталог с:\pico\pico-sdk. Для этого запускаем Git Bash и выполняем следующие команды:

cd /c/pico
git clone https://github.com/raspberrypi/pico-sdk.git
cd pico-sdk
git submodule init
git submodule update

В результате содержимое каталога c:\pico должно быть примерно таким:

30.12.2022  11:22    DIR          gcc-arm-none-eabi-10.3-2021.10
30.12.2022  11:23    DIR          OpenOCD-20211118-0.11.0
30.12.2022  11:24    DIR          pico-sdk

И последнее, что нужно сделать - создать переменную окружения PICO_TOOLCHAIN_PATH и в качестве ее значения указать путь к папке bin тулчейна, т.е. c:\pico\gcc-arm-none-eabi-10.3-2021.10\bin (далее станет понятно зачем это нужно).

Создание проекта

Запускаем Eclipse и в качестве рабочего каталога выбираем любой отличный от с:\pico, например пусть будет с:\workspace

Далее создаем C Project, предварительно создав пустой каталог c:\pico\RP2040Minimal. В визарде нужно изменить путь к проекту (по умолчанию он будет c:\workspace) и выбрать в качестве тулчейна Arm Cross GCC. Имя проекта зададим RP2040Minimal.

Далее будет предложено указать путь к тулчейну. Оставляем поле пустым, потому как уже задали путь в переменной окружения PICO_TOOLCHAIN_PATH. Для чего использовать переменную окружения? Причина в следующем: путь к тулчейну, прописанный в настройках Eclipse, добавляется во внутренюю переменную PATH проекта только при его создании и после этого никак в ней не меняется, что в свою очередь неудобно при переносе проекта на другой компьютер, где местонахождение компилятора может быть другим. Гораздо проще исправить значение системной переменной окружения, чем потом делать это вручную в каждом проекте (далее мы увидим что их будет несколько). Почему я просто не прописал путь в переменной PATH? Ответ прост: в ней уже может быть прописан путь к другому тулчейну, что вызовет конфликт при сборке либо сборка произведется не тем компилятором, который нужен.

Проект создан. Переходим к его настройке. Сначала зададим везде, где нужно путь к SDK. Открываем окно настроек Project->Properties и переходим на вкладку Resource/Linked Resource. Создаем переменную SDK_PATH = c:\pico\pico-sdk

Область видимости переменной SDK_PATH, созданной в разделе Linked Resources ограничена и ее значение доступно только при импорте файлов в проект в качестве пути, относительно которого создается ссылка на файлы. Потому нам нужно ее еще раз продублировать на вкладке С/С++ Build/Environment. Также здесь объявим переменную PATH (или переопределим, если она существует), значением который будет системная переменная окружения PICO_TOOLCHAIN_PATH:

Переходим к настройкам микроконтроллера - вкладка C/C++ Build/Settings/Tool Settings/Target Processor. Здесь нужно указать семейство ARM-контроллера и архитектуру - Cortex M0+/armv6_m. Остальные настройки можно пока оставить по умолчанию.

Далее производим настройку компоновщика. Переходим на вкладку C/C++ Build/Settings/Tool Settings/GNU Arm Cross C Linker/Miscellaneous. Здесь необходимо отметить флаг "Do not use syscalls"

На вкладке C/C++ Build в качестве сборщика выбираем Internal builder.

Когда произведены данные настройки, можно попробовать скомпилировать минимальную программу. Создаем файл main.c следующего содержания:

int main(int argc, char **argv) {
	return 0;
}

Запускаем компиляцию и убеждаемся, что проект успешно собран, а результатом сборки является файл RP2040Minmal.elf 

Теперь перейдем к более сложной задаче. Создадим программу для мигания светодиодом на базе пакета SDK. Сначала удалим файл main.c, вместо него создадим файл blink.c в каталоге Application следующего содержания:

#include "pico/stdlib.h"
#include "boards/pico.h"

int main() {
#ifndef PICO_DEFAULT_LED_PIN
#warning blink example requires a board with a regular LED
#else
    const uint LED_PIN = PICO_DEFAULT_LED_PIN;
    gpio_init(LED_PIN);
    gpio_set_dir(LED_PIN, GPIO_OUT);
    while (true) {
        gpio_put(LED_PIN, 1);
        sleep_ms(500);
        gpio_put(LED_PIN, 0);
        sleep_ms(500);
    }
#endif
}

Теперь, если запустить сборку проекта, то мы получим ошибку: fatal error: pico/stdlib.h: No such file or directory

В этом нет ничего неожиданного, потому что сборщик не знает где искать заголовочный файл stdlib.h. Когда мы собираем проект с помощью CMake,то в сценариях сборки прописаны включаемые в сборку каталоги для того или иного исходного c-файла. В нашем же случае подключаемые директории (include) придется добавить вручную в свойствах проекта на вкладке C/C++ Build/Settings/Tool Settings/GNU Arm Cross C Compiler/Includes для *.c-файлов и на вкладке C/C++ Build/Settings/Tool Settings/GNU Arm Cross C Assembler/Includes для *.s - файлов. Первым делом в Includes добавляем путь к проекту, который хранится в переменной Eclipse ${ProjDirPath} - он пригодится нам позже. Файл stdlib.h находится в каталоге c:\pico\pico-sdk\src\common\pico_stdlib\include\pico\, но в коде программы он подключает относительно каталога c:\pico\pico-sdk\src\common\pico_stdlib\include\, потому его мы и укажем. Для того, чтобы проект был легко переносим на другую машину, все пути к файлам и каталогам нужно указывать через созданную переменную окружения ${SDK_PATH}. Т.е. в итоге получаем путь вида ${SDK_PATH}\src\common\pico_stdlib\include\pico\

Если теперь попытаться собрать проект, то мы получим новую ошибку: c:\pico\pico-sdk\src\common\pico_stdlib\include/pico/stdlib.h:10:10: fatal error: pico.h: No such file or directory. И может сложиться впечатление, что таких неразрешенных зависимостей будет миллион. Но не стоит отчаиваться, на самом деле список Includes для проекта мигания светодиодом не такой уж и большой. Настроив один раз минимальный проект в последующем нужно будет только добавлять некоторое небольшое число дополнительных директорий и исходников, в зависимости от используемой периферии и библиотек. Чтобы читатель не мучался, я составил список необходимых каталогов, который нужно просто скопировать в поле Include paths.

Для GNU Arm Cross C Compiler список следующий:

"${ProjDirPath}"
"${SDK_PATH}\src\boards\include"
"${SDK_PATH}\src\common\pico_stdlib\include"
"${SDK_PATH}\src\common\pico_base\include"
"${SDK_PATH}\src\common\pico_sync\include"
"${SDK_PATH}\src\common\pico_time\include"
"${SDK_PATH}\src\common\pico_util\include"
"${SDK_PATH}\src\rp2_common\hardware_irq\include"
"${SDK_PATH}\src\rp2_common\hardware_clocks\include"
"${SDK_PATH}\src\rp2_common\hardware_resets\include"
"${SDK_PATH}\src\rp2_common\hardware_sync\include"
"${SDK_PATH}\src\rp2_common\cmsis\include"
"${SDK_PATH}\src\rp2_common\pico_platform\include"
"${SDK_PATH}\src\rp2_common\hardware_base\include"
"${SDK_PATH}\src\rp2_common\hardware_timer\include"
"${SDK_PATH}\src\rp2_common\pico_bootrom\include"
"${SDK_PATH}\src\rp2_common\hardware_watchdog\include"
"${SDK_PATH}\src\rp2_common\hardware_gpio\include"
"${SDK_PATH}\src\rp2_common\hardware_pll\include"
"${SDK_PATH}\src\rp2_common\hardware_xosc\include"
"${SDK_PATH}\src\rp2_common\hardware_claim\include"
"${SDK_PATH}\src\rp2_common\pico_printf\include"
"${SDK_PATH}\src\rp2_common\pico_mem_ops\include"
"${SDK_PATH}\src\rp2_common\pico_stdio\include"
"${SDK_PATH}\src\rp2_common\hardware_uart\include"
"${SDK_PATH}\src\rp2040\hardware_regs\include"
"${SDK_PATH}\src\rp2040\hardware_structs\include"

Список включений для GNU Arm Cross Assembler:

"${ProjDirPath}"
"${SDK_PATH}\src\boards\include"
"${SDK_PATH}\src\common\pico_base\include"
"${SDK_PATH}\src\common\pico_sync\include"
"${SDK_PATH}\src\common\pico_time\include"
"${SDK_PATH}\src\common\pico_binary_info\include"
"${SDK_PATH}\src\rp2_common\hardware_irq\include"
"${SDK_PATH}\src\rp2_common\hardware_clocks\include"
"${SDK_PATH}\src\rp2_common\hardware_resets\include"
"${SDK_PATH}\src\rp2_common\hardware_sync\include"
"${SDK_PATH}\src\rp2_common\cmsis\include"
"${SDK_PATH}\src\rp2_common\pico_platform\include"
"${SDK_PATH}\src\rp2_common\hardware_base\include"
"${SDK_PATH}\src\rp2_common\hardware_timer\include"
"${SDK_PATH}\src\rp2_common\pico_mem_ops\include"
"${SDK_PATH}\src\rp2_common\pico_bootrom\include"
"${SDK_PATH}\src\rp2040\hardware_regs\include"
"${SDK_PATH}\src\rp2040\hardware_structs\include"

Кроме статических h-файлов, хращихся в каталоге pico-sdk, есть еще два файла, которые генерируются с помощью Python-скриптов в момент стандартной сборки с помощью CMake. Это файлы version.h (содержит номер версии SDK) и config_autogen.h. Не вникая в детали я просто скопировал эти файлы из собранного проекта, внеся небольшие правки относительно путей. Вот их содержимое:

Файл version.h:

#ifndef _PICO_VERSION_H
#define _PICO_VERSION_H

#define PICO_SDK_VERSION_MAJOR    1
#define PICO_SDK_VERSION_MINOR    4
#define PICO_SDK_VERSION_REVISION 0
#define PICO_SDK_VERSION_STRING   "1.4.0"

#endif

Файл config_autogen.h:

// based on PICO_CONFIG_HEADER_FILES:

#include "boards/pico.h"

// based on PICO_RP2040_CONFIG_HEADER_FILES:

#include "cmsis/rename_exceptions.h"

Данные файлы помещаем в каталог pico внутри проекта, т.е в c:\pico\RP2040Minimal\pico

Заголовочные файлы это конечно хорошо. Но нам нужны в первую очередь исходные c- и s-файлы. Механизм их добавления в проект отличается. Нам необходимо прибегнуть к импорту из файловой системы, т.е. Import->General->File System:

Указываем путь к директории C:\pico\pico-sdk

Далее по отдельности нужно выбрать следующие файлы:

В окне импорта это будет выглядеть вот так:

Здесь также важно отметить, что мы хотим создать ссылки на файлы, а не получить их копию - Create links in workspace.  И второй момент - указать, что ссылки должны быть относительно каталога SDK. Здесь как раз нам и пригождается переменная SDK_PATH, созданная в разделе Resource/Linked Resource. Таким образом мы получим древовидную структуру виртуальных каталогов, по которой проще ориентироваться. Если возникнет необходимость обновить драйвера и библиотеки, нам не придется копировать новые файлы в проект - достаточно будет только изменить значение переменной SDK_PATH.

Теперь, когда исходные файлы добавлены в проект, мы должны сообщить компоновщику как располагать код в памяти. Для этого нужно подключить скрипт memmap_default.ld из каталога c:\pico\pico-sdk\src\rp2_common\pico_standard_link. Сделать это нужно в свойствах проекта на вкладке C/C++ Build/Settings/Tool Settings/GNU Arm Cross C Linker/General

Пробуем собрать проект и снова сталкиваемся с ошибкой: ERROR: Pico second stage bootloader must be 256 bytes in size.

Дело в том, что в нашем проекте не хватает кода вторичного загрузчика. Вторичный загрузчик запускается тогда, когда первичный загрузчик bootrom заканчивает свою работу. Он производит настройку периферии для работы с конкретной внешней flash-памятью (изначально работа выполняется по общему для всех микросхем алгоритму, но в таком случае она может быть не оптимальной, например на более низкой скорости чтения/записи). Вторичный загрузчик располагается во внешней флеш по смещению 0x00000000. Его размер не должен превышать 256 Байт, а если быть более точным, то 252 Байта, потому как 4 последних байта используются под контрольную сумму. Вторичный загрузчик, выполнив свою работу, передает управление основной программе, находящейся по смещению 0x0010000. 

Чтобы добавить загрузчик в программу, мы можем его собрать из исходников, которые находятся в каталоге c:\pico\pico-sdk\src\rp2_common\boot_stage2\, выбрав подходящий тип микросхемы памяти. Однако можно пойти более простым путем, взяв уже скомпилированный байт-код загрузчика (из SDK под Arduino) и просто поместив его в проект в виде массива байтов:

Файл boot.c:

#include "stdint.h"

const uint8_t __attribute__((section(".boot2"))) boot_stage2[256] =
{
	0x00, 0xb5, 0x32, 0x4b, 0x21, 0x20, 0x58, 0x60, 0x98, 0x68, 0x02, 0x21, 0x88, 0x43, 0x98, 0x60,
	0xd8, 0x60, 0x18, 0x61, 0x58, 0x61, 0x2e, 0x4b, 0x00, 0x21, 0x99, 0x60, 0x04, 0x21, 0x59, 0x61,
	0x01, 0x21, 0xf0, 0x22, 0x99, 0x50, 0x2b, 0x49, 0x19, 0x60, 0x01, 0x21, 0x99, 0x60, 0x35, 0x20,
	0x00, 0xf0, 0x44, 0xf8, 0x02, 0x22, 0x90, 0x42, 0x14, 0xd0, 0x06, 0x21, 0x19, 0x66, 0x00, 0xf0,
	0x34, 0xf8, 0x19, 0x6e, 0x01, 0x21, 0x19, 0x66, 0x00, 0x20, 0x18, 0x66, 0x1a, 0x66, 0x00, 0xf0,
	0x2c, 0xf8, 0x19, 0x6e, 0x19, 0x6e, 0x19, 0x6e, 0x05, 0x20, 0x00, 0xf0, 0x2f, 0xf8, 0x01, 0x21,
	0x08, 0x42, 0xf9, 0xd1, 0x00, 0x21, 0x99, 0x60, 0x1b, 0x49, 0x19, 0x60, 0x00, 0x21, 0x59, 0x60,
	0x1a, 0x49, 0x1b, 0x48, 0x01, 0x60, 0x01, 0x21, 0x99, 0x60, 0xeb, 0x21, 0x19, 0x66, 0xa0, 0x21,
	0x19, 0x66, 0x00, 0xf0, 0x12, 0xf8, 0x00, 0x21, 0x99, 0x60, 0x16, 0x49, 0x14, 0x48, 0x01, 0x60,
	0x01, 0x21, 0x99, 0x60, 0x01, 0xbc, 0x00, 0x28, 0x00, 0xd0, 0x00, 0x47, 0x12, 0x48, 0x13, 0x49,
	0x08, 0x60, 0x03, 0xc8, 0x80, 0xf3, 0x08, 0x88, 0x08, 0x47, 0x03, 0xb5, 0x99, 0x6a, 0x04, 0x20,
	0x01, 0x42, 0xfb, 0xd0, 0x01, 0x20, 0x01, 0x42, 0xf8, 0xd1, 0x03, 0xbd, 0x02, 0xb5, 0x18, 0x66,
	0x18, 0x66, 0xff, 0xf7, 0xf2, 0xff, 0x18, 0x6e, 0x18, 0x6e, 0x02, 0xbd, 0x00, 0x00, 0x02, 0x40,
	0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x07, 0x00, 0x00, 0x03, 0x5f, 0x00, 0x21, 0x22, 0x00, 0x00,
	0xf4, 0x00, 0x00, 0x18, 0x22, 0x20, 0x00, 0xa0, 0x00, 0x01, 0x00, 0x10, 0x08, 0xed, 0x00, 0xe0,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x0b, 0x8f, 0xd5,
};

Здесь важно указать, что мы должны поместить код загрузчика в секцию boot2 флеш-памяти.

Поместив файл boot.c в каталог Application пробуем собрать проект. И наконец-то мы получаем желаемый результат в виде файлов прошивки *.elf и *.hex. Но нам бы хотелось зашить нашу программу через USB, а для этого нужна прошивка в формате *.uf2.

Преобразованием elf-файла в uf2-файл занимается поставляемае в пакете SDK утилита elf2uf2, исходный код которой находится в каталоге c:\pico\pico-sdk\tools\elf2uf2. Данную утилиту я собрал под Windows X64, скачать ее можно здесь.

Копируем файл elf2uf2.exe в каталог c:\pico. Чтобы Eclipse производил конвертацию файлов по окончанию сборки, необходимо в свойствах проекта на влкадке C/C++ Build/Settings/Build Steps в поле Post-build steps задать следующую команду:

${ProjDirPath}\..\elf2uf2 ${PWD}\${BuildArtifactFileName} ${PWD}\${BuildArtifactFileBaseName}.uf2

После пересборки проекта в каталоге Debug видим нужный нам файл RP2040Minimal.uf2. Пробуем зашить его в микроконтроллер через USB - и наблюдаем как мигает наш светодиод!

Таким образом мы теперь можем вести удобную разработку программ для RP2040 в ОС Windows в среде Eclipse. Добавить драйвера необходимой периферии не составит труда - все делается по аналогии с драйвером gpio, который имеется в текущем проекте.

На данном этапе я хочу закончить статью, так как она получилась достаточно объемной. В следующий раз я опишу настройку процесса отладки в Eclipse.

Архив проекта с исходными файлами можно скачать здесь: RP2040Minimal.zip

Также на GitLab я создал репозиторий с примерами для Raspberry Pi Pico RP2040 под Windows: https://gitlab.com/osandr/pico-examples-windows.git

Примеры из репозитория можно импортировать в Eclipse практически без каких-либо настроек (не забываем о переменной PICO_TOOLCHAIN_PATH). Инструкция по клонированию проекта находится в файле readme.md

На этом все. Надеюсь, что данный материал будет кому-то полезен.