3.1. PIKA - WIRELESS 开发板
我们骄傲地推出PIKA 派 - WIRELESS开发板,这是PikaPython官方首次推出的全流程、手把手教程的开发板。
在这个信息爆炸的新时代,嵌入式编程与Python结合,创造出了前所未有的应用可能性。而PikaPython,作为嵌入式Python的领军力量,成为了许多创新项目的核心动力。
为了培养与帮助下一代的开发者掌握这一创新技术,我们荣誉推出专为技术爱好者与新世代研发者设计的“PIKA 派 - WIRELESS”开发学习板。
“PIKA 派 - WIRELESS”的核心采用了业界知名、学习友好的ESP32S3。该芯片性能卓越、功能多样,绝对能满足您对嵌入式Python的所有探索与实验需求。这块开发板集成了大量的硬件资源(8M的Flash、WIFI与4G通信、众多传感器),并且提供了许多扩展接口,为您在各种项目中展翅翱翔创造了条件。配合此开发学习板,您将得以深度体验PikaPython的魅力,锻炼自己的编程能力,并为未来的技术挑战做好万全的准备。
🛠 技术参数一览:
主控:ESP32S3
存储:FLASH 8M, PSRAM 8M, nand FLASH 128MB
通信:WIFI、4G、RS485 接口
显示:LCD 屏幕
传感器:板载温湿度传感器、光敏电阻
其他:蜂鸣器、继电器、12V供电、WS2812
此款开发板完整覆盖了内核移植、驱动适配、模块开发、事件驱动、应用开发到最佳实践的全流程。它旨在帮助开发者快速并深入地学习PikaPython在项目实战中的各种技术,并迅速掌握实战开发能力。
📚 课程亮点:
PikaPython基础移植与脚本启动模式深入讲解
ESP32实战系列,包括驱动适配、事件驱动等核心技术
深入嵌入式驱动框架设计与应用
嵌入式编程思想与最佳实践
我们精心准备的课程不仅确保您能在此开发板上掌握PikaPython的核心技能,还设计了许多案例和实战,确保您可以举一反三,轻松拓展到任何新的平台上。
探索、学习,然后再创新。这不仅是我们的信念,更是我们希望与大家共同实现的目标。期待与您共同探索PikaPython的无限可能!💡
购买链接:https://m.tb.cn/h.5eu8O7B?tk=AgpWdB6P4Op
下面是程住气大佬结合开发板和课程的内容编写的课程笔记,非常值得一读!
3.1.1. CMAKE 内核编译和应用
教程中的 makefile 和 CMake 工程可以在 Win 上运行,这样可以快速进行测试和进行仿真运行,后面可以移植到你的实际硬件平台上(例如 STM32、ESP32等)。
3.1.1.1. 官网
https://pikapython.com/
3.1.1.2. 先下载包管理器:用于拉取pikapython的源码
http://pikapython.com/doc//%E5%8C%85%E7%AE%A1%E7%90%86%E5%99%A8%E4%B8%8E%E6%A8%A1%E5%9D%97%E7%AE%A1%E7%90%86.html
3.1.1.3. 拉取内核源码
新建记事本requestment.txt,输入下面内容。
(不过即使没有这步,包管理器也会自动新建requestment.txt)
pikascript-core
PikaStdLib
其他可用版本查看:https://gitee.com/Lyon1998/pikascript/blob/master/packages.toml
然后执行包管理器,进行拉取代码。
运行预编译rust-msc-latest-win10.exe,它会将python文件预编译到pikascript-api中的C文件中去
3.1.1.4. 编写应用主程序
新建main.c文件,代码如下:
#include<stdio.h>
#include"pikascript.h"
int main(int argc,char **argv)
{
printf("hello world\r\n");
//固件启动,需要编译
PikaObj* pikaMain = pikaScriptInit();
}
3.1.1.5. 内核编译
官方视频是用 visual studio 来做的,这个软件太大了,家里网速慢,同时电脑有现成的 vscode,所以将分别采用 WIN 环境下 makefile 和 CMAKE 来编译。(其实是后续的 ESP32 视频,编译用的是 CMAKE,看不懂所以回头学了 CMAKE + makefile)
下载和安装MinGW32
下载地址: https://www.onlinedown.net/soft/10056269.htm
解压后,添加环境变量后:
makefile:
1.新建makefile文件,代码如下
2.执行make
TAR = pikapython
# 添加头文件搜索路径
INC = -I ./ -I ./pikascript-core -I ./pikascript-api -I ./pikascript-lib/PikaStdLib
# 寻找源文件.c
SOURCES = $(wildcard *.c ./pikascript-api/*.c ./pikascript-core/*.c ./pikascript-lib/PikaStdLib/*.c)
OBJ = $(patsubst %.c,%.o,$(SOURCES))
# test:
# @echo $(SOURCES)
$(TAR):$(OBJ)
gcc $^ -o $@ $(INC)
%.o:%.c
gcc -c $^ -o $@ $(INC)
clean:
rm -rf *.o ./**/*.o ./**/**/*.o $(TAR)
CMAKE:
CMAKE环境搭建:下载地址:https://cmake.org/download/
CMAKE开始:
1.新建CMakeLists.txt文件,代码如下.
2.新建build文件夹,然后进入build文件,
3.cmake ..
4.make
(2.3的步骤是为了简洁工程,cmake会生成一堆中间文件,这样中间文件全部在build文件夹里了)
# 指定使用的 cmake 的最低版本,可选,非必须,如果不加可能会有警告
cmake_minimum_required(VERSION 3.10)
# 生成工程名字
project(pikapython)
# GLOB查找.c文件
file(GLOB API_SRC ${CMAKE_CURRENT_SOURCE_DIR}/pikascript-api/*.c)
file(GLOB CORE_SRC ${CMAKE_CURRENT_SOURCE_DIR}/pikascript-core/*.c)
file(GLOB LIB_SRC ${CMAKE_CURRENT_SOURCE_DIR}/pikascript-lib/PikaStdLib/*.c)
# 将所有的源文件组合在一起
set(SOURCE_FILES ${API_SRC} ${CORE_SRC} ${LIB_SRC} main.c)
# message("所有的.c文件:",${SOURCE_FILES})
# 添加头文件搜索路径
include_directories(${CMAKE_SOURCE_DIR}/pikascript-core)
include_directories(${CMAKE_SOURCE_DIR}/pikascript-api)
include_directories(${CMAKE_SOURCE_DIR}/pikascript-lib/PikaStdLib)
# 定义工程会生成一个可执行程序
add_executable(pikapython ${SOURCE_FILES})
3.1.1.6. 应用入门
修改main.py文件,加一句print(’hello world!’)
运行预编译rust-msc-latest-win10.exe
编译内核makefile/cmake
执行
3.1.2. ESP32 入门体验
3.1.2.1. 安装
3.1.2.1.1. 官方入门指南:入门指南
3.1.2.1.2. 下载地址:ESP-IDF下载地址
这里选择 v5.1 版本,【一定一定一定】 要选 v5.1,v5.1.1不行!,v5.1.2也不行,后面会导致奇怪的问题!!!
(后面的截图中可能出现了 v5.1.2,这是当初使用 v5.1.2 的时候的截图,v5.1.2 已经掉坑里了!换回 v5.1 了! 一切以 v5.1 为准!)
下载完,一路next就行
3.1.2.2. 新建工程、编译、下载
# 打开esp-idf,切目录(这个目录后续用于插件,创建使用模板)
cd esample/get-start
# 新建工程
idf.py create-project hello
# 设置芯片
idf.py set-target esp32s3
# 编写代码hello.c
#include <stdio.h>
void app_main(void)
{
printf("hello world,god bless you");
}
# 编译
idf.py build
# 下载代码并开启监听(串口的查看,参看下图)
idf.py flash -p COM8 monitor
# 退出监听,键盘快捷键
ctrl+]
3.1.2.3. vscode插件
之前的操作都是使用命令行,使用vscode+esp32插件,快乐加倍
3.1.2.4. vscode插件复制
打开命令面板:ctrl+shift+p
3.1.2.5. 点灯
插件新建工程
原理图
插件按钮
#include <stdio.h>
#include "driver/gpio.h"
#include "FreeRTOS/freertos.h"
#include "FreeRTOS/task.h"
#define LED2_PIN 4
#define LED1_PIN 7
void led_init(int index)
{
gpio_config_t led_pin_config;
led_pin_config.pin_bit_mask = 1<<index;
led_pin_config.mode = GPIO_MODE_OUTPUT;
led_pin_config.intr_type = GPIO_INTR_DISABLE;
led_pin_config.pull_up_en = GPIO_PULLUP_DISABLE;
led_pin_config.pull_down_en = GPIO_PULLDOWN_DISABLE;
gpio_config(&led_pin_config);
}
void led_on(int index)
{
gpio_set_level(index, 1);
}
void led_off(int index)
{
gpio_set_level(index, 0);
}
void app_main(void)
{
printf("hello gogogo");
led_init(LED1_PIN);
led_init(LED2_PIN);
while(1)
{
led_on(LED1_PIN);
led_off(LED2_PIN);
vTaskDelay(50);
led_off(LED1_PIN);
led_on(LED2_PIN);
vTaskDelay(50);
}
}
3.1.2.6. 组件开发
在ESP32的开发中,我们经常需要使用一些特定的功能模块,比如OLED显示屏、温湿度传感器、红外遥控器等等。为了方便使用这些模块,我们可以将它们封装成自定义组件,以便在不同的项目中重复使用。pikapython也是以组件形式来做的,可以方便让你移植pika,事半功倍。(我当时不懂组件,移植都是懵的)
本文将介绍如何在ESP32中创建自定义组件。
3.1.2.6.1. 创建组件目录
首先,我们需要在ESP32的工程目录下创建一个名为components的目录,用于存放自定义组件。
在components目录下,我们可以创建一个名为test的子目录,用于存放自定义组件的代码和头文件。
3.1.2.6.2. 创建组件代码
在test目录下,我们可以创建一个名为test.c的文件,用于实现自定义组件的功能。
例如,我们可以在test.c中实现一个名为my_function的函数,用于打印一条消息:
// test.c:
#include "test.h"
#include "stdio.h"
void my_function(void)
{
printf("test component!\n");
}
3.1.2.6.3. 创建组件头文件
在test目录下,我们还需要创建一个名为test.h的头文件,用于声明自定义组件的接口。
例如,我们可以在test.h中声明my_function函数:
// test.h:
#ifndef test_H
#define test_H
void my_function(void);
#endif
3.1.2.6.4. 在工程中使用自定义组件
现在,我们已经创建了一个名为test的自定义组件。接下来,我们需要在工程中使用它。
首先,我们需要在工程的CMakeLists.txt文件中添加以下代码,以便告诉ESP32编译器在编译时包含test目录:
idf_component_register(SRCS "test.c"
INCLUDE_DIRS ".")
然后,我们可以在工程的主代码中包含test.h头文件,并调用my_function函数:
// hello.c:
#include "test.h"
void app_main(void)
{
my_function();
}
3.1.2.6.5. 编译和运行工程
如果一切正常,你应该能够在终端中看到”Hello, world!”这条消息。
3.1.2.6.6. 更改组件名字,需要在主cmake中修改:
!
3.1.2.7. 总结
在ESP32的开发中,自定义组件是一个非常有用的工具,可以帮助我们更好地组织和重用代码。在本文中,我们介绍了如何创建和使用自定义组件,希望对你有所帮助。
3.1.3. ESP32 移植 PikaPython
3.1.3.1. 近况
有点惭愧,鸽了将近三个月!年中公司在裁员,年底了项目没减,人却少了,工作996二个月,年底不好找工作忍了(万恶的资本)!
等忙完工作,好不容易抽出身。然后就是咳嗽、甲乙丙各种流,低烧、咳嗽、鼻涕将近一个月。肺都要咳出来,我太难了~
3.1.3.2. 下载pika包
3.1.3.3. 新建工程
参考第二遍教程,新建工程。
3.1.3.4. pikapython作为组件
新建文件夹components/pikapyhon
将pika包放入pikapyhon文件夹中
运行pikaPackage.exe
3.1.3.5. 修改CMAKE
新建CMakeLists.txt文件,这个跟esp32组件开发有关,每个组件都是由一个CMake来编译
编写CMake,需要懂CMake知识,
# 匹配所有.c的文件,并赋值给SOURCES变量
file(GLOB_RECURSE SOURCES *.c)
# 组件注册
# SRCS ${SOURCES} 编译SOURCES变量下的文件
# INCLUDE_DIRS ... 头文件包含
idf_component_register(SRCS ${SOURCES}
INCLUDE_DIRS
"pikascript-api"
"pikascript-core"
"pikascript-lib/PikaStdLib"
)
3.1.3.6. 编写主函数
#include <stdio.h>
#include "pikascript.h"
void app_main(void)
{
printf("aaaa");
PikaObj* pikaMain = pikaScriptInit();
}
3.1.3.7. 心得
移植这个还是挺简单的,跟pikapython内核编译差不多。
主要需要熟悉gcc、CMake、freertos、esp32开发的知识,不然真的无法下手。 如果对上面不是很了解,建议先熟悉上面的知识点,磨刀不误砍柴工。
3.1.4. 串口通信
3.1.4.1. 通过串口进行交互,先熟悉下ESP32的串口代码。下面esp32s3的串口通信代码,实验结果为uart回传。
串口通信代码
#include <stdio.h>
#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "esp_spi_flash.h"
#include "string.h"
#include "driver/usb_serial_jtag.h"
void app_main(void)
{
printf("uart test/r/n");
usb_serial_jtag_driver_config_t usb_cdc = {
.rx_buffer_size = 65, //环形buf应大于64
.tx_buffer_size = 65 //环形buf应大于64
};
ESP_ERROR_CHECK(usb_serial_jtag_driver_install(&usb_cdc)); //安装usb_serial驱动
// usb_serial_jtag_driver_uninstall(); //卸载usb_serial驱动
while(1)
{
char buf[1] = {0};
if(usb_serial_jtag_read_bytes(buf, 1, portMAX_DELAY) >0) //阻塞当前任务,直到接收数据
{
usb_serial_jtag_write_bytes(buf, 1, portMAX_DELAY);
}
vTaskDelay(10/portTICK_PERIOD_MS);
}
}
3.1.5. 交互运行
3.1.5.1. 交互式运行环境
为了实现在目标平台上的交互式运行,我们需要提供getchar、putchar接口来重载。 getchar从标准输入字符,putchar从标准输出字符,查看pika平台的代码。
PIKA_WEAK 就是弱函数,弱函数可以应用到几个模块之间的交互接口,在项目中并行开发多个存在交互模块时,本模块代码需要使用到外部模块接口,但其他模块并未开发完成,此处可以使用弱函数解决,编译链接报错问题。
//添加重载函数
char pika_platform_getchar() {
while (1) {
char buff[1] = {0};
if (usb_serial_jtag_read_bytes(buff, 1,portMAX_DELAY) > 0) {
return buff[0];
}
return buff[1];
}
}
int pika_platform_putchar(char ch) {
usb_serial_jtag_write_bytes(&ch, 1, portMAX_DELAY);
return 0;
}
//在主函数中,增加shell代码
//必须使用宏PRIu32,否则putchar会卡死,系统不工作。目前还没找到原因,后续有空再来查查
uint32_t a =5;
printf("Minimum free heap size: %" PRIu32 " bytes\n",a);
PikaObj* pikaMain = pikaScriptInit();
pikaScriptShell(pikaMain);
3.1.5.2. 移植好的shell代码
3.1.6. 文件系统
3.1.6.1. 文件系统适配
文件系统的适配使 PikaPython 能够从文件加载脚本,进行存储、检索和执行操作。 这可能包括对FLASH存储或SD卡等外部存储介质的支持,以及实现或利用现有文件系统 API。 常见文件系统:选择一个常用文件系统,来提供文件系统的适配,如 fatfs、LittleFS等。
3.1.6.2. 原理图 NAND FLASH
3.1.6.3. 新建sd_fatfs.c sd_fatfs.h文件、修改CMAKE
//sd_fatfs.c
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include "driver/gpio.h"
#include "driver/sdspi_host.h"
#include "driver/uart.h"
#include "esp_event.h"
#include "esp_log.h"
#include "esp_system.h"
#include "esp_vfs_fat.h"
#include "freertos/FreeRTOS.h"
#include "freertos/queue.h"
#include "freertos/task.h"
#include "hal/spi_types.h"
#include "sdmmc_cmd.h"
#include "esp_http_client.h"
#include "esp_https_ota.h"
#include "esp_ota_ops.h"
#include "esp_wifi.h"
#include "nvs.h"
#include "nvs_flash.h"
#include "pikaScript.h"
#include "sd_fatfs.h"
static sdmmc_card_t* card;
static bool is_sd_mounted = false;
int sd_fatfs_init(void) {
esp_err_t ret;
const char mount_point[] = MOUNT_POINT;
esp_vfs_fat_sdmmc_mount_config_t mount_config = {
.format_if_mount_failed = true,
.max_files = 5,
.allocation_unit_size = 16 * 1024,
};
// Use settings defined above to initialize SD card and mount FAT
// filesystem. Note: esp_vfs_fat_sdmmc/sdspi_mount is all-in-one convenience
// functions. Please check its source code and implement error recovery when
// developing production applications.
sdmmc_host_t host = SDSPI_HOST_DEFAULT();
host.slot = SPI3_HOST;
spi_bus_config_t bus_cfg = {
.mosi_io_num = SDSPI_MOSI,
.miso_io_num = SDSPI_MISO,
.sclk_io_num = SDSPI_CLK,
.quadwp_io_num = -1,
.quadhd_io_num = -1,
.max_transfer_sz = 4000,
};
ret = spi_bus_initialize(host.slot, &bus_cfg, SDSPI_DEFAULT_DMA);
if (ret != ESP_OK && ret != ESP_ERR_INVALID_STATE) {
printf("Failed to initialize SPI bus.\r\n");
return -1;
}
// This initializes the slot without card detect (CD) and write protect (WP)
// signals. Modify slot_config.gpio_cd and slot_config.gpio_wp if your board
// has these signals.
sdspi_device_config_t slot_config = SDSPI_DEVICE_CONFIG_DEFAULT();
slot_config.gpio_cs = SDSPI_CS;
slot_config.host_id = host.slot;
printf("Mounting filesystem...\r\n");
ret = esp_vfs_fat_sdspi_mount(mount_point, &host, &slot_config,
&mount_config, &card);
if (ret != ESP_OK) {
if (ret == ESP_FAIL) {
printf(
"Failed to mount filesystem. "
"If you want the card to be formatted, set the "
"CONFIG_EXAMPLE_FORMAT_IF_MOUNT_FAILED menuconfig option.\r\n");
} else {
printf(
"Failed to initialize the card (%s). "
"Make sure SD card lines have pull-up resistors in place.\r\n",
esp_err_to_name(ret));
}
return -1;
} else {
printf("Filesystem mounted\r\n");
is_sd_mounted = true;
sdmmc_card_print_info(stdout, card);
}
return 0;
}
//sd_fatfs.h
#ifndef SD_FATFS_H
#define SD_FATFS_H
#define MOUNT_POINT "/sd"
#define SDSPI_CS (GPIO_NUM_47)
#define SDSPI_CLK (GPIO_NUM_21)
#define SDSPI_MISO (GPIO_NUM_14)
#define SDSPI_MOSI (GPIO_NUM_13)
int sd_fatfs_init(void);
#endif
3.1.6.4. 在main.c主函数中,初始化文件和添加操作文件的重载函数
//main.c文件 主函数添加
sd_fatfs_init();
//main.c文件,添加文件重载函数
FILE *pika_platform_fopen(const char *filename, const char *modes)
{
return fopen(filename, modes);
}
int pika_platform_fclose(FILE *fp) { return fclose(fp); }
int pika_platform_fseek(FILE *fp, long offset, int whence)
{
return fseek(fp, offset, whence);
}
long pika_platform_ftell(FILE *fp) { return ftell(fp); }
size_t pika_platform_fread(void *ptr, size_t size, size_t count, FILE *fp)
{
return fread(ptr, size, count, fp);
}
size_t pika_platform_fwrite(const void *ptr, size_t size, size_t count,
FILE *fp)
{
return fwrite(ptr, size, count, fp);
}
3.1.6.5. 在cmake上需要添加编译 SRCS “sd_fatfs.c”
file(GLOB_RECURSE SOURCES *.c)
idf_component_register(SRCS "hello.c"
SRCS "sd_fatfs.c"
INCLUDE_DIRS ".")
idf_build_set_property(
COMPILE_DEFINITIONS "-DPIKA_CONFIG_ENABLE" APPEND)
3.1.7. os模块引入
os 模块提供了非常丰富的方法用来处理文件和目录,举个栗子:
import os
# 路径的拼接
folder_path = os.path.join("file","user")
print(folder_path) # file\user
# 查看sd文件夹里的文件
os.listdir('/sd')
3.1.7.1. 增加os模块
在requestment.txt增加os,增加完还需要运行pikaPackage.exe包来进行下载,然后执行rust-msc-latest-win10.exe,打包进去
这个特别注意下,参考下图,视频os当时是v0.1.1来做的,现在os版本是v0.1.4了(2024.2.27日),编译报错。其实在报错的时候,有错误提示在最后一个报错提示的,需要v1.12.7以上才可以,而我习惯看错误从一个错误开始看起,以为漏了那个宏定义的步骤。各种找问题,后面看到需要升级版本到v1.12.7,编译通过了,在执行os.listdir(’/sd’)的时候,由于内核PikaPlatform.c改了,需要重载pika_platform_listdir才行,我也是哭死了,为什么这么折磨我,后面对比固件代码,跟固件代码版本一致。成功了,从晚上十点折磨到凌晨4点,一口老血喷出。所以以后务必指明版本,我也没想到版本差别这么大。
3.1.7.2. 修改pikapython中的CMAKE
增加os模块编译
因为os模块很多代码使用的是linux环境下,所以我们需要把pikapython也设置为linux环境下,在main文件夹下修改CMAKE
3.1.7.3. 在main文件夹下添加pika_config.h文件
//pika_config.h
#define PIKA_LINUX_COMPATIBLE 1
3.1.7.4. 在py文件引入os
// main.py 更改后,记得执行rust-msc-latest-win10.exe
import os
print('hello pikapython!')
3.1.7.5. 修改esp32配置
支持文件系统的长名字和大小写区分
命令:idf.py menuconfig
S为保存,保存后,idf.py fullclean,重新编译下
3.1.7.6. 代码
3.1.8. 串口烧录脚本
回顾上一章的内容,实现了交互和文件系统,这次从串口发送脚本文件保存,并将这个脚本文件启动,实现串口烧录
3.1.8.1. 串口下载python脚本
串口下载 Python 脚本和交互式运行非常类似,仍然是使用 obj_run 内核 API 进行脚本的运行。和交互式运行不同的是,下载 Python 脚本还需要对python脚本进行 存储。
obj_run 支持运行字符串形式的 Python 脚本,因此无论以哪种方式存储,只要最后给 obj_run 传入 Python 脚本的字符串即可。所以可以的存储方式有:flash 直接存储、文件系统、外部存储器等。
3.1.8.2. 存储python脚本
存储 Python 源码很简单,将串口接收到的 Python 脚本字符串完整写入 Flash 即可。启动时不使用 pikaScriptInit() 函数,而是手动创建 pikaMain 根对象,再使用 obj_run(pikaMain, code) 运行脚本,code 代表的是存储好的 python 源码。
3.1.8.3. 运行脚本
首先用pikastudio软件通过串口发送的.a文件,然后保存会保存到app.pika
读取脚本
PikaObj *root= NULL;
//判断是否文件
FILE *fp = fopen(PIKA_SHELL_SAVE_APP_PATH, "rb");
if(fp!=NULL){
fclose(fp);
printf("[Info] load app from sd card\n");
root = newRootObj("pikaMain", New_PikaMain);
obj_linkLibraryFile(root,PIKA_SHELL_SAVE_APP_PATH);
obj_runModule(root,"main");
} else {
printf("[Info] load app from firmware\n");
root = pikaPythonInit();
}
pikaScriptShell(root);
重启脚本,需要重载函数
void pika_platform_reboot(void){
// esp_restart();
abort();
}
3.1.8.4. 擦除脚本
当写脚本的时候,不小心写了死循环,那么将无法通过串口再次烧录了,这时候需要先擦除,再来烧录
擦除脚本
remove(PIKA_SHELL_SAVE_APP_PATH);
esp_restart();//擦除之后,需要重启
新建一个任务,用来判断是否擦除脚本
// 创建动态任务
xTaskCreate(eriase_task, "Dynamic Task", 2048, (void *)5, 5, &task_handle);
vTaskDelay(3000/portTICK_PERIOD_MS);
/*IO 操作*/
#define BOOT_GPIO_PIN GPIO_NUM_0
#define BOOT gpio_get_level(BOOT_GPIO_PIN)
void key_init(void)
{
gpio_config_t gpio_init_struct;
gpio_init_struct.intr_type = GPIO_INTR_DISABLE; /* 失能引脚中断 */
gpio_init_struct.mode = GPIO_MODE_INPUT; /* 输入模式 */
gpio_init_struct.pull_up_en = GPIO_PULLUP_ENABLE; /* 使能上拉 */
gpio_init_struct.pull_down_en = GPIO_PULLDOWN_DISABLE; /* 失能下拉 */
gpio_init_struct.pin_bit_mask = 1ull << BOOT_GPIO_PIN; /* BOOT 按键引脚 */
gpio_config(&gpio_init_struct); /* 配置使能 */
}
void eriase_task(void *pvParameters) {
while(1){
if(BOOT == 0)
{
vTaskDelay(10/portTICK_PERIOD_MS); /* 去抖动 */
if(BOOT == 0)
{
//擦除
printf("remove");
remove(PIKA_SHELL_SAVE_APP_PATH);
esp_restart();
}
}
vTaskDelay(10/portTICK_PERIOD_MS);
}
}