AGENT SKILL

rp2350-c-cpp

Expert RP2350 C/C++ development with Pico SDK, covering CMake configuration, peripheral drivers (GPIO, SPI, I2C, PWM, UART), hardware optimization, FreeRTOS integration, and bare-metal programming. Use when developing C/C++ firmware for RP2350/RP2040 boards, implementing hardware drivers, optimizing performance, or building real-time embedded applications.

License 许可
MIT
最近更新
2026-11-01
Stars
★ 3
Forks
1

01 前言 Front Matter

name
rp2350-c-cpp
description
Expert RP2350 C/C++ development with Pico SDK, covering CMake configuration, peripheral drivers (GPIO, SPI, I2C, PWM, UART), hardware optimization, FreeRTOS integration, and bare-metal programming. Use when developing C/C++ firmware for RP2350/RP2040 boards, implementing hardware drivers, optimizing performance, or building real-time embedded applications.

02 资源文件 12

03 SKILL.md 正文

RP2350 C/C++ Development with Pico SDK

Overview

This skill provides comprehensive guidance for developing high-performance embedded applications on RP2350 and RP2040 hardware using C/C++ and the official Raspberry Pi Pico SDK. It covers project setup, CMake configuration, peripheral programming, memory optimization, multicore development, and FreeRTOS integration.

When to Use This Skill

Use this skill when:

  • Developing C/C++ firmware for RP2350 or RP2040 boards
  • Setting up Pico SDK projects with CMake
  • Implementing hardware drivers (GPIO, SPI, I2C, PWM, UART, ADC)
  • Writing interrupt service routines and DMA transfers
  • Building multicore applications utilizing both ARM cores
  • Integrating FreeRTOS for real-time task management
  • Optimizing memory usage and execution speed
  • Implementing USB device or host functionality
  • Working with PIO (Programmable I/O) for custom protocols
  • Debugging with picoprobe or SWD interfaces
  • Porting applications from RP2040 to RP2350

Hardware Context

RP2350 Features

  • Processor: Dual ARM Cortex-M33 @ 150MHz (or dual RISC-V Hazard3 @ 150MHz)
  • Memory: 520KB SRAM, up to 16MB external flash
  • Security: ARM TrustZone-M, secure boot, signed firmware
  • Peripherals:
    • 30 multifunction GPIO pins
    • 2× UART, 2× SPI, 2× I2C
    • 12-bit ADC with up to 5 channels
    • 24× PWM channels
    • 12× PIO state machines
    • USB 1.1 host/device
    • DMA controller with 12 channels
  • Power: 1.8-3.6V operation, sleep modes down to 180µA

RP2040 Features (for comparison)

  • Processor: Dual ARM Cortex-M0+ @ 133MHz
  • Memory: 264KB SRAM, up to 16MB external flash
  • Peripherals: Similar to RP2350 but without TrustZone and with lower performance

Core Capabilities

1. Project Setup with CMake

Use assets/project_template/ for a complete CMake-based project structure.

Key Components:

  • CMakeLists.txt - Main build configuration
  • pico_sdk_import.cmake - SDK integration
  • .vscode/ - VSCode configuration for debugging
  • src/ - Source code directory

Quick Start:

# Copy template
cp -r assets/project_template/ my_project
cd my_project

# Configure environment
export PICO_SDK_PATH=/path/to/pico-sdk

# Build
mkdir build && cd build
cmake ..
make -j4

CMakeLists.txt Structure:

cmake_minimum_required(VERSION 3.13)

# Include SDK
include(pico_sdk_import.cmake)

project(my_project C CXX ASM)
set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 17)

# Initialize SDK
pico_sdk_init()

# Add executable
add_executable(my_project
    src/main.c
    src/peripheral_init.c
)

# Link libraries
target_link_libraries(my_project
    pico_stdlib
    hardware_spi
    hardware_i2c
    hardware_pwm
    hardware_adc
)

# Enable USB output, disable UART
pico_enable_stdio_usb(my_project 1)
pico_enable_stdio_uart(my_project 0)

# Create map/bin/hex/uf2 files
pico_add_extra_outputs(my_project)

Refer to references/cmake_configuration.md for advanced CMake patterns including multicore builds, FreeRTOS integration, and custom linker scripts.

2. GPIO and Basic I/O

Initialization:

#include "pico/stdlib.h"

// Configure GPIO as output
const uint LED_PIN = 25;
gpio_init(LED_PIN);
gpio_set_dir(LED_PIN, GPIO_OUT);

// Configure GPIO as input with pull-up
const uint BUTTON_PIN = 15;
gpio_init(BUTTON_PIN);
gpio_set_dir(BUTTON_PIN, GPIO_IN);
gpio_pull_up(BUTTON_PIN);

Interrupt Handling:

void gpio_callback(uint gpio, uint32_t events) {
    if (gpio == BUTTON_PIN && (events & GPIO_IRQ_EDGE_FALL)) {
        // Button pressed
        gpio_put(LED_PIN, !gpio_get(LED_PIN));
    }
}

int main() {
    stdio_init_all();

    gpio_init(LED_PIN);
    gpio_set_dir(LED_PIN, GPIO_OUT);

    gpio_init(BUTTON_PIN);
    gpio_set_dir(BUTTON_PIN, GPIO_IN);
    gpio_pull_up(BUTTON_PIN);

    // Enable interrupt
    gpio_set_irq_enabled_with_callback(
        BUTTON_PIN,
        GPIO_IRQ_EDGE_FALL,
        true,
        &gpio_callback
    );

    while (1) {
        tight_loop_contents();
    }
}

3. SPI Communication

Standard SPI Setup:

#include "hardware/spi.h"

#define SPI_PORT spi0
#define PIN_MISO 16
#define PIN_CS   17
#define PIN_SCK  18
#define PIN_MOSI 19

void spi_init_device() {
    // Initialize SPI at 10 MHz
    spi_init(SPI_PORT, 10 * 1000 * 1000);

    // Configure GPIO for SPI
    gpio_set_function(PIN_MISO, GPIO_FUNC_SPI);
    gpio_set_function(PIN_SCK,  GPIO_FUNC_SPI);
    gpio_set_function(PIN_MOSI, GPIO_FUNC_SPI);

    // Initialize CS pin as GPIO output
    gpio_init(PIN_CS);
    gpio_set_dir(PIN_CS, GPIO_OUT);
    gpio_put(PIN_CS, 1);  // CS high (inactive)
}

uint8_t spi_read_register(uint8_t reg) {
    uint8_t data;
    gpio_put(PIN_CS, 0);  // CS low
    spi_write_blocking(SPI_PORT, &reg, 1);
    spi_read_blocking(SPI_PORT, 0, &data, 1);
    gpio_put(PIN_CS, 1);  // CS high
    return data;
}

void spi_write_register(uint8_t reg, uint8_t value) {
    uint8_t buf[2] = {reg, value};
    gpio_put(PIN_CS, 0);
    spi_write_blocking(SPI_PORT, buf, 2);
    gpio_put(PIN_CS, 1);
}

DMA-Based SPI Transfer:

#include "hardware/dma.h"

void spi_dma_transfer(uint8_t *tx_buf, uint8_t *rx_buf, size_t len) {
    int dma_tx = dma_claim_unused_channel(true);
    int dma_rx = dma_claim_unused_channel(true);

    // Configure TX DMA
    dma_channel_config c_tx = dma_channel_get_default_config(dma_tx);
    channel_config_set_transfer_data_size(&c_tx, DMA_SIZE_8);
    channel_config_set_dreq(&c_tx, spi_get_dreq(SPI_PORT, true));

    dma_channel_configure(
        dma_tx, &c_tx,
        &spi_get_hw(SPI_PORT)->dr,  // dst
        tx_buf,                      // src
        len,                         // transfer count
        false                        // don't start yet
    );

    // Configure RX DMA
    dma_channel_config c_rx = dma_channel_get_default_config(dma_rx);
    channel_config_set_transfer_data_size(&c_rx, DMA_SIZE_8);
    channel_config_set_dreq(&c_rx, spi_get_dreq(SPI_PORT, false));
    channel_config_set_read_increment(&c_rx, false);
    channel_config_set_write_increment(&c_rx, true);

    dma_channel_configure(
        dma_rx, &c_rx,
        rx_buf,                      // dst
        &spi_get_hw(SPI_PORT)->dr,  // src
        len,                         // transfer count
        false                        // don't start yet
    );

    // Start both channels
    gpio_put(PIN_CS, 0);
    dma_start_channel_mask((1u << dma_tx) | (1u << dma_rx));

    // Wait for completion
    dma_channel_wait_for_finish_blocking(dma_rx);
    gpio_put(PIN_CS, 1);

    // Release channels
    dma_channel_unclaim(dma_tx);
    dma_channel_unclaim(dma_rx);
}

4. I2C Communication

I2C Setup and Operations:

#include "hardware/i2c.h"

#define I2C_PORT i2c0
#define I2C_SDA 4
#define I2C_SCL 5
#define I2C_FREQ 400000  // 400 kHz

void i2c_init_device() {
    // Initialize I2C at 400 kHz
    i2c_init(I2C_PORT, I2C_FREQ);

    // Configure GPIO for I2C
    gpio_set_function(I2C_SDA, GPIO_FUNC_I2C);
    gpio_set_function(I2C_SCL, GPIO_FUNC_I2C);
    gpio_pull_up(I2C_SDA);
    gpio_pull_up(I2C_SCL);
}

// Read single byte
uint8_t i2c_read_byte(uint8_t addr, uint8_t reg) {
    uint8_t data;
    i2c_write_blocking(I2C_PORT, addr, &reg, 1, true);
    i2c_read_blocking(I2C_PORT, addr, &data, 1, false);
    return data;
}

// Write single byte
void i2c_write_byte(uint8_t addr, uint8_t reg, uint8_t value) {
    uint8_t buf[2] = {reg, value};
    i2c_write_blocking(I2C_PORT, addr, buf, 2, false);
}

// Read multiple bytes
int i2c_read_bytes(uint8_t addr, uint8_t reg, uint8_t *buf, size_t len) {
    i2c_write_blocking(I2C_PORT, addr, &reg, 1, true);
    return i2c_read_blocking(I2C_PORT, addr, buf, len, false);
}

// I2C scanner
void i2c_scan() {
    printf("\nI2C Bus Scan\n");
    printf("   0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F\n");

    for (int addr = 0; addr < (1 << 7); ++addr) {
        if (addr % 16 == 0) {
            printf("%02x ", addr);
        }

        int ret;
        uint8_t rxdata;
        ret = i2c_read_blocking(I2C_PORT, addr, &rxdata, 1, false);

        printf(ret < 0 ? "." : "@");
        printf(addr % 16 == 15 ? "\n" : "  ");
    }
}

5. PWM for LED/Motor Control

PWM Configuration:

#include "hardware/pwm.h"

void pwm_init_pin(uint gpio, uint freq_hz, float duty_cycle) {
    // Configure GPIO for PWM
    gpio_set_function(gpio, GPIO_FUNC_PWM);

    // Find PWM slice
    uint slice_num = pwm_gpio_to_slice_num(gpio);

    // Calculate divider and wrap for desired frequency
    uint32_t clock_freq = 125000000;  // 125 MHz
    uint32_t divider = clock_freq / (freq_hz * 65536);
    if (divider < 1) divider = 1;

    uint32_t wrap = (clock_freq / (freq_hz * divider)) - 1;

    // Configure PWM
    pwm_set_clkdiv(slice_num, divider);
    pwm_set_wrap(slice_num, wrap);

    // Set duty cycle
    uint16_t level = (uint16_t)(wrap * duty_cycle);
    pwm_set_gpio_level(gpio, level);

    // Enable PWM
    pwm_set_enabled(slice_num, true);
}

// Example: RGB LED control
void rgb_led_init(uint pin_r, uint pin_g, uint pin_b) {
    pwm_init_pin(pin_r, 1000, 0.0);  // 1 kHz, 0% duty
    pwm_init_pin(pin_g, 1000, 0.0);
    pwm_init_pin(pin_b, 1000, 0.0);
}

void rgb_led_set_color(uint pin_r, uint pin_g, uint pin_b,
                       float r, float g, float b) {
    uint slice_r = pwm_gpio_to_slice_num(pin_r);
    uint slice_g = pwm_gpio_to_slice_num(pin_g);
    uint slice_b = pwm_gpio_to_slice_num(pin_b);

    uint16_t wrap = pwm_get_wrap(slice_r);

    pwm_set_gpio_level(pin_r, (uint16_t)(wrap * r));
    pwm_set_gpio_level(pin_g, (uint16_t)(wrap * g));
    pwm_set_gpio_level(pin_b, (uint16_t)(wrap * b));
}

6. ADC (Analog-to-Digital Converter)

ADC Reading:

#include "hardware/adc.h"

void adc_init_all() {
    adc_init();

    // Make sure GPIO is high-impedance, no pullups etc
    adc_gpio_init(26);  // ADC0
    adc_gpio_init(27);  // ADC1
    adc_gpio_init(28);  // ADC2
}

uint16_t adc_read_channel(uint channel) {
    adc_select_input(channel);
    return adc_read();
}

float adc_read_voltage(uint channel) {
    adc_select_input(channel);
    uint16_t raw = adc_read();
    // Convert to voltage (3.3V reference, 12-bit ADC)
    return raw * 3.3f / 4096.0f;
}

// Read internal temperature sensor
float read_onboard_temperature() {
    adc_select_input(4);  // Temperature sensor on ADC4
    uint16_t raw = adc_read();

    // Convert to temperature (from RP2040 datasheet)
    const float conversion = 3.3f / 4096.0f;
    float voltage = raw * conversion;
    float temp_c = 27.0f - (voltage - 0.706f) / 0.001721f;

    return temp_c;
}

7. Multicore Programming

Core1 Launch:

#include "pico/multicore.h"

void core1_entry() {
    while (1) {
        // Core 1 work here
        printf("Running on core 1\n");
        sleep_ms(1000);
    }
}

int main() {
    stdio_init_all();

    printf("Starting core 1\n");
    multicore_launch_core1(core1_entry);

    while (1) {
        // Core 0 work here
        printf("Running on core 0\n");
        sleep_ms(1000);
    }
}

Intercore Communication:

#include "pico/multicore.h"

// Core 0 to Core 1 FIFO
void core0_send_to_core1(uint32_t data) {
    multicore_fifo_push_blocking(data);
}

// Core 1 receives from Core 0
uint32_t core1_receive_from_core0() {
    return multicore_fifo_pop_blocking();
}

// Example: Core 1 worker
void core1_worker() {
    while (1) {
        uint32_t cmd = multicore_fifo_pop_blocking();

        switch (cmd) {
            case 1:
                // Process command 1
                break;
            case 2:
                // Process command 2
                break;
        }

        // Send result back to Core 0
        multicore_fifo_push_blocking(42);
    }
}

8. USB Device Implementation

USB Serial (CDC): Already enabled with pico_enable_stdio_usb() in CMakeLists.txt.

Custom USB Device:

#include "tusb.h"

// USB HID Keyboard example
void send_key_press(uint8_t keycode) {
    if (tud_hid_ready()) {
        uint8_t report[8] = {0};
        report[2] = keycode;  // Keycode
        tud_hid_keyboard_report(0, 0, report);

        // Release key
        sleep_ms(10);
        tud_hid_keyboard_report(0, 0, NULL);
    }
}

Refer to references/pico_sdk_reference.md for comprehensive USB API documentation including HID, MSC, and CDC examples.

Development Workflow

Step 1: Environment Setup

Install Dependencies:

# Linux/Raspberry Pi
sudo apt install cmake gcc-arm-none-eabi libnewlib-arm-none-eabi \
                 build-essential libstdc++-arm-none-eabi-newlib

# macOS
brew install cmake
brew install --cask gcc-arm-embedded

Clone Pico SDK:

cd ~
git clone https://github.com/raspberrypi/pico-sdk.git
cd pico-sdk
git submodule update --init
export PICO_SDK_PATH=$(pwd)

Step 2: Create Project from Template

Use the provided project template:

cp -r assets/project_template/ my_project
cd my_project

Edit CMakeLists.txt to configure your project name and dependencies.

Step 3: Build

mkdir build
cd build
cmake ..
make -j4

Output files:

  • my_project.elf - ELF executable
  • my_project.bin - Binary image
  • my_project.uf2 - USB bootloader format
  • my_project.hex - Intel HEX format

Step 4: Flash Firmware

Method 1: USB Bootloader (BOOTSEL mode)

# 1. Hold BOOTSEL button while plugging in USB
# 2. Copy UF2 file to mounted drive
cp my_project.uf2 /media/$USER/RPI-RP2/

Method 2: Using Picoprobe/SWD

# Using OpenOCD with picoprobe
openocd -f interface/cmsis-dap.cfg \
        -f target/rp2040.cfg \
        -c "program my_project.elf verify reset exit"

Method 3: Using Flash Script Use scripts/flash.sh for automated flashing:

./scripts/flash.sh build/my_project.uf2

Step 5: Debug

Serial Debug Output:

#include "pico/stdlib.h"

int main() {
    stdio_init_all();

    while (!tud_cdc_connected()) {
        sleep_ms(100);
    }

    printf("Debug: System initialized\n");
    // Your code here
}

GDB Debugging with Picoprobe:

# Terminal 1: Start OpenOCD
openocd -f interface/cmsis-dap.cfg -f target/rp2040.cfg

# Terminal 2: Start GDB
gdb-multiarch my_project.elf
(gdb) target remote localhost:3333
(gdb) load
(gdb) break main
(gdb) continue

Refer to .vscode/launch.json in the project template for VSCode debugging configuration.

Common Patterns

Pattern: Non-Blocking Timer

#include "pico/time.h"

typedef struct {
    absolute_time_t last_trigger;
    uint32_t interval_ms;
} timer_t;

void timer_init(timer_t *timer, uint32_t interval_ms) {
    timer->interval_ms = interval_ms;
    timer->last_trigger = get_absolute_time();
}

bool timer_expired(timer_t *timer) {
    absolute_time_t now = get_absolute_time();
    int64_t elapsed = absolute_time_diff_us(timer->last_trigger, now);

    if (elapsed >= timer->interval_ms * 1000) {
        timer->last_trigger = now;
        return true;
    }
    return false;
}

// Usage
int main() {
    timer_t blink_timer;
    timer_init(&blink_timer, 500);  // 500ms interval

    while (1) {
        if (timer_expired(&blink_timer)) {
            gpio_xor_mask(1 << LED_PIN);
        }

        // Other non-blocking work
        tight_loop_contents();
    }
}

Pattern: State Machine

typedef enum {
    STATE_IDLE,
    STATE_RUNNING,
    STATE_PAUSED,
    STATE_COMPLETED
} app_state_t;

typedef struct {
    app_state_t state;
    uint32_t counter;
    bool button_pressed;
} app_context_t;

void state_machine_update(app_context_t *ctx) {
    switch (ctx->state) {
        case STATE_IDLE:
            if (ctx->button_pressed) {
                ctx->state = STATE_RUNNING;
                ctx->counter = 0;
            }
            break;

        case STATE_RUNNING:
            ctx->counter++;
            if (ctx->button_pressed) {
                ctx->state = STATE_PAUSED;
            }
            if (ctx->counter >= 1000) {
                ctx->state = STATE_COMPLETED;
            }
            break;

        case STATE_PAUSED:
            if (ctx->button_pressed) {
                ctx->state = STATE_RUNNING;
            }
            break;

        case STATE_COMPLETED:
            // Reset on button press
            if (ctx->button_pressed) {
                ctx->state = STATE_IDLE;
            }
            break;
    }

    ctx->button_pressed = false;
}

Pattern: Circular Buffer (Ring Buffer)

typedef struct {
    uint8_t *buffer;
    size_t size;
    size_t head;
    size_t tail;
    size_t count;
} ring_buffer_t;

void ring_buffer_init(ring_buffer_t *rb, uint8_t *buffer, size_t size) {
    rb->buffer = buffer;
    rb->size = size;
    rb->head = 0;
    rb->tail = 0;
    rb->count = 0;
}

bool ring_buffer_push(ring_buffer_t *rb, uint8_t data) {
    if (rb->count >= rb->size) {
        return false;  // Buffer full
    }

    rb->buffer[rb->head] = data;
    rb->head = (rb->head + 1) % rb->size;
    rb->count++;
    return true;
}

bool ring_buffer_pop(ring_buffer_t *rb, uint8_t *data) {
    if (rb->count == 0) {
        return false;  // Buffer empty
    }

    *data = rb->buffer[rb->tail];
    rb->tail = (rb->tail + 1) % rb->size;
    rb->count--;
    return true;
}

Performance Optimization

Memory Management

Stack Size Configuration: In CMakeLists.txt:

# Increase stack size if needed
target_compile_definitions(my_project PRIVATE
    PICO_STACK_SIZE=0x2000  # 8KB stack
    PICO_CORE1_STACK_SIZE=0x2000
)

Static vs Dynamic Allocation:

// Prefer static allocation on embedded systems
static uint8_t buffer[1024];

// Avoid malloc/free if possible
// If needed, consider custom allocator

Memory-Mapped I/O:

#include "hardware/regs/addressmap.h"

// Direct register access (faster than SDK functions)
#define GPIO_OUT_REG ((volatile uint32_t*)(SIO_BASE + 0x10))
#define GPIO_OUT_SET ((volatile uint32_t*)(SIO_BASE + 0x14))
#define GPIO_OUT_CLR ((volatile uint32_t*)(SIO_BASE + 0x18))
#define GPIO_OUT_XOR ((volatile uint32_t*)(SIO_BASE + 0x1C))

// Fast GPIO toggle
*GPIO_OUT_XOR = (1 << LED_PIN);

Code Optimization

Compiler Flags in CMakeLists.txt:

# Optimization level
target_compile_options(my_project PRIVATE
    -O3                    # Maximum optimization
    -flto                  # Link-time optimization
    -ffunction-sections    # Each function in own section
    -fdata-sections        # Each data item in own section
)

target_link_options(my_project PRIVATE
    -Wl,--gc-sections      # Remove unused sections
)

Inline Functions:

static inline void fast_gpio_toggle(uint gpio) {
    sio_hw->gpio_togl = 1u << gpio;
}

Use Hardware Features:

  • DMA for large data transfers
  • PIO for bit-banging protocols
  • Hardware interpolators for calculations

Interrupt Optimization

// Keep ISRs short and fast
void __isr __time_critical_func(gpio_isr)() {
    // Clear interrupt
    gpio_acknowledge_irq(BUTTON_PIN, GPIO_IRQ_EDGE_FALL);

    // Set flag for main loop
    volatile bool button_flag = true;

    // Don't call printf or blocking functions in ISR
}

Troubleshooting

Build Issues

SDK Not Found:

export PICO_SDK_PATH=/path/to/pico-sdk

Undefined Reference Errors: Add missing libraries in CMakeLists.txt:

target_link_libraries(my_project
    pico_stdlib
    hardware_spi    # Add this
    hardware_i2c    # Add this
)

Flashing Issues

Device Not Recognized:

  1. Check USB cable (data capable, not charge-only)
  2. Verify BOOTSEL button held during power-on
  3. Check lsusb for RP2040 device (ID 2e8a:0003)

Permission Denied (Linux):

sudo usermod -a -G dialout $USER
# Log out and back in

Runtime Issues

Crash on Startup:

  • Check stack size (increase if needed)
  • Verify all peripherals initialized before use
  • Check for buffer overflows

GPIO Not Working:

  • Verify pin numbers match board pinout
  • Check if pin already used by another peripheral
  • Ensure gpio_init() called before use

SPI/I2C No Response:

  • Verify wiring and pull-up resistors
  • Check clock frequencies
  • Use oscilloscope to verify signals
  • Try i2c_scan() to detect devices

Memory Issues

Out of RAM:

// Check memory usage
extern char __StackLimit, __bss_end__;
printf("Heap end: %p\n", &__bss_end__);
printf("Stack limit: %p\n", &__StackLimit);

Reduce Memory Usage:

  • Use smaller buffers
  • Move large arrays to flash: const uint8_t data[] = {...};
  • Optimize struct packing
  • Use bit fields for flags

Resources

This skill includes:

scripts/

Build and deployment automation:

  • build.sh - Automated build script with error handling
  • flash.sh - Automated firmware flashing (supports BOOTSEL and picoprobe)
  • monitor.sh - Serial monitor for debugging output

references/

Comprehensive technical documentation:

  • pico_sdk_reference.md - Complete Pico SDK API reference and examples
  • cmake_configuration.md - Advanced CMake patterns and build configurations
  • hardware_interfaces.md - Detailed hardware peripheral programming guide
  • freertos_integration.md - FreeRTOS setup and real-time task patterns

assets/

Ready-to-use project templates and boilerplate:

  • project_template/ - Complete CMake project structure with examples
    • CMakeLists.txt - Configured build system
    • pico_sdk_import.cmake - SDK integration
    • .vscode/ - VSCode debugging configuration
    • src/main.c - Minimal example application

All scripts and templates are production-ready and can be used directly or customized for specific applications.

04 同仓库更多 Skills

shengdabai
shengdabai/Tony-Claude-Code-Skills

xiaolai-methodology

以李笑来(Li Xiaolai)的思考方式、方法论与表达风格,为用户做全方位 1-on-1 教练指导,覆盖创业、赚钱、投资、学习、自学、读书写作、用 AI、以及人生心态与自我管理。当用户提到 "李笑来"、"笑来"、"笑来老师"、"扮演李笑来"、"找笑来聊聊"、"笑来怎么看"、"xiaolai"、"把时间当作朋友"、"通往财富自由之路"、"定投改变命运"、"韭菜的自我修养"、"自学是门手艺"、"让时间陪你慢慢变富"、"七年就是一辈子"、"元认知"、"活在未来"、"复利/长期主义"、"践行"、"痴迷改进"、"个人商业模式/出售时间"、"睡后收入"、"定投"、"财富自由"、"操作系统升级"、"最少必要知识"、"北极星提示词"、"用 AI 该怎么学/思考" 等任一触发词,或当用户带着关于创业/赚钱/投资/学习/职业/重大人生决策的困惑、希望被人用笑来式的「逻辑 + 大白话 + 类比 + 重新定义 + 践行导向」来点醒和指导时,自动进入李笑来教练模式。

写作与文案
★ 3
shengdabai
shengdabai/Tony-Claude-Code-Skills

zread

Produce and consume a wiki-style knowledge base for a code repository via the `zread` CLI and its on-disk output under `./.zread/wiki/`. Use this skill whenever the user wants to understand, onboard onto, explore, summarize, map, or get an overview of an unfamiliar codebase; asks for architecture docs, a project wiki, a repo walkthrough, module/package explanations, or "what does this repo do"; wants to generate, regenerate, resume, browse, or serve code documentation locally; or mentions zread / zread.ai directly. Also use it proactively before diving into a large unknown repo — if `./.zread/wiki/current` exists, read the generated pages instead of crawling source file-by-file; if it doesn't, consider offering to run `zread generate`. The trigger is the intent (understand a codebase through generated docs), not the literal word "zread".

开发工程师Skill与智能体开发
★ 3
shengdabai
shengdabai/Tony-Claude-Code-Skills

youtube

Launch the YouTube Creator Agent to auto-generate videos. Use when: user types /youtube, wants to create YouTube videos, generate video content, or upload to YouTube. Keywords: youtube, video, 视频, 创作视频, 发布视频

内容创作者Skill与智能体开发
★ 3
shengdabai
shengdabai/Tony-Claude-Code-Skills

youtube-script-sync

Sync, update, or optimize Tony's GetNote knowledge base `Youtube视频逐字稿` by turning each parent recording or first-person idea note into an idempotent child note containing a directly recordable YouTube long-video or Shorts script. Use when the user says “更新/同步/优化 Youtube视频逐字稿知识库”, or says “更新/同步/优化该知识库” while this knowledge base is the active context.

Skill与智能体开发
★ 3
shengdabai
shengdabai/Tony-Claude-Code-Skills

writing-skills

How to write SKILL.md files that trigger reliably and teach effectively. Use when creating, improving, or reviewing Claude Code skills.

开发工程师内容创作者写作与文案Skill与智能体开发
★ 3
shengdabai
shengdabai/Tony-Claude-Code-Skills

writing-rules

How to write .claude/rules/ files that Claude actually follows. Use when creating, improving, or reviewing project rules.

内容创作者写作与文案
★ 3