树莓派Pico硬件重置失效?试试这个C语言强制重置方案(附完整代码)
当你在开发树莓派Pico项目时,可能会遇到这样的情况:硬件重置按钮突然失效,外围设备(比如LED)无法正常复位。传统的BOOTSEL按钮组合操作在某些场景下可能无法彻底解决问题。这时候,我们就需要一种更可靠的软件重置方案。
1. 为什么需要软件重置方案
硬件重置失效通常发生在以下几种场景:
- 外围设备(如PWM控制的LED)在程序崩溃后仍保持活动状态
- 固件更新后部分硬件模块未正确初始化
- 多线程程序中某个硬件模块被意外锁定
传统的硬件重置方法(BOOTSEL+RUN)虽然简单,但存在明显局限性:
- 不完全复位:某些硬件模块可能不会随主芯片一起复位
- 状态保留:部分外设寄存器值可能被保留
- 依赖物理按钮:在嵌入式系统中可能无法随时操作
提示:当发现LED持续闪烁或外设无响应时,建议优先尝试软件重置方案
2. 准备开发环境
在开始编写重置程序前,需要确保开发环境配置正确:
2.1 安装必要工具链
# 安装编译工具 sudo apt install cmake gcc-arm-none-eabi libnewlib-arm-none-eabi2.2 获取Pico SDK
git clone -b master https://github.com/raspberrypi/pico-sdk.git cd pico-sdk git submodule update --init export PICO_SDK_PATH=`pwd`2.3 项目目录结构
建议按以下结构组织代码:
hello_reset/ ├── CMakeLists.txt ├── pico_sdk_import.cmake └── hello_reset.c3. 编写重置程序
3.1 核心代码解析
下面是完整的hello_reset.c实现:
#include <stdio.h> #include "pico/stdlib.h" #include "hardware/resets.h" int main() { stdio_init_all(); printf("Starting hardware reset...\n"); // 重置PWM模块 reset_block(RESETS_RESET_PWM_BITS); unreset_block_wait(RESETS_RESET_PWM_BITS); // 重置PWM和RTC模块 reset_block(RESETS_RESET_PWM_BITS | RESETS_RESET_RTC_BITS); unreset_block_wait(RESETS_RESET_PWM_BITS | RESETS_RESET_RTC_BITS); // 添加更多需要重置的模块 reset_block(RESETS_RESET_ADC_BITS); unreset_block_wait(RESETS_RESET_ADC_BITS); printf("Reset completed successfully!\n"); return 0; }关键函数说明:
reset_block():将指定硬件模块置入复位状态unreset_block_wait():解除复位并等待模块就绪
3.2 可重置的硬件模块
Pico支持重置的硬件模块如下表所示:
| 模块名称 | 宏定义 | 典型应用场景 |
|---|---|---|
| PWM | RESETS_RESET_PWM_BITS | LED控制异常 |
| RTC | RESETS_RESET_RTC_BITS | 时钟不同步 |
| ADC | RESETS_RESET_ADC_BITS | 采样值异常 |
| SPI | RESETS_RESET_SPI0_BITS | 通信失败 |
| UART | RESETS_RESET_UART0_BITS | 串口无响应 |
4. 构建与部署
4.1 CMake配置
创建CMakeLists.txt文件:
cmake_minimum_required(VERSION 3.12) include(pico_sdk_import.cmake) project(hello_reset) pico_sdk_init() add_executable(hello_reset hello_reset.c) target_link_libraries(hello_reset pico_stdlib) pico_add_extra_outputs(hello_reset)4.2 构建流程
# 复制CMake配置文件 cp $PICO_SDK_PATH/external/pico_sdk_import.cmake . # 创建构建目录 mkdir build cd build # 生成Makefile并编译 cmake .. make -j4构建完成后,会在build目录下生成hello_reset.uf2文件。
4.3 部署到Pico
- 按住BOOTSEL按钮连接Pico到电脑
- 将生成的
hello_reset.uf2拖入出现的U盘 - 程序会自动运行并执行重置操作
5. 高级应用技巧
5.1 批量重置多个模块
可以一次性重置多个硬件模块:
// 同时重置PWM、RTC和ADC模块 uint32_t reset_mask = RESETS_RESET_PWM_BITS | RESETS_RESET_RTC_BITS | RESETS_RESET_# 1. 题目 #### [93. 复原 IP 地址](https://leetcode-cn.com/problems/restore-ip-addresses/) 难度中等857 **有效 IP 地址** 正好由四个整数(每个整数位于 `0` 到 `255` 之间组成,且不能含有前导 `0`),整数之间用 `'.'` 分隔。 - 例如:`"0.1.2.201"` 和` "192.168.1.1"` 是 **有效** IP 地址,但是 `"0.011.255.245"`、`"192.168.1.312"` 和 `"192.168@1.1"` 是 **无效** IP 地址。 给定一个只包含数字的字符串 `s` ,用以表示一个 IP 地址,返回所有可能的**有效 IP 地址**,这些地址可以通过在 `s` 中插入 `'.'` 来形成。你 **不能** 重新排序或删除 `s` 中的任何数字。你可以按 **任何** 顺序返回答案。 **示例 1:**输入:s = "25525511135" 输出:["255.255.11.135","255.255.111.35"]
**示例 2:**输入:s = "0000" 输出:["0.0.0.0"]
**示例 3:**输入:s = "101023" 输出:["1.0.10.23","1.0.102.3","10.1.0.23","10.10.2.3","101.0.2.3"]
**提示:** - `1 <= s.length <= 20` - `s` 仅由数字组成 # 2. 题解 # 3. code ```c++ class Solution { public: vector<string> ans; bool isValid(const string& s, int start, int end) { if (start > end) { return false; } if (s[start] == '0' && start != end) { return false; } int num = 0; for (int i = start; i <= end; i++) { if (s[i] > '9' || s[i] < '0') { return false; } num = num * 10 + (s[i] - '0'); if (num > 255) { return false; } } return true; } void backtracking(string s, int startIdx, int pointNum) { if (pointNum == 3) { if (isValid(s, startIdx, s.size() - 1)) { ans.push_back(s); } return; } for (int i = startIdx; i < s.size(); i++) { if (isValid(s, startIdx, i)) { s.insert(s.begin() + i + 1, '.'); pointNum++; backtracking(s, i + 2, pointNum); pointNum--; s.erase(s.begin() + i + 1); } else { break; } } return; } vector<string> restoreIpAddresses(string s) { if (s.size() < 4 || s.size() > 12) return ans; backtracking(s, 0, 0); return ans; } };4. 心得
回溯法,注意终止条件,以及判断是否有效。