• 猿创征文|中国移动 OneOS 万耦启物开发板支持包(BSP)


    项目源码地址:【例程】OneOS启物开发板板级支持包(BSP)

    1. 序言

    本板级支持包(BSP)是基于OneOS官方源码进行二次开发,对本开发板进行适配,方便使用与学习开发的一个源码项目。主要针对中国移动OneOS 启物开发板<以下简称启物开发板>进行更新优化。
    在这里插入图片描述

    本文档将从BSP目录结构开始,为您讲解整个BSP的结构,与简要的使用示范。
    在这里插入图片描述

    2. BSP目录结构说明

    启物开发板的BPS工程目录基本结构与OneOS基础目录一致,所有的开发板Demo存放于projects目录下,该目录下一同存放例程功能说明。Demo会在未来进行新增、维护。
    在这里插入图片描述
    关于OneOS 的层级目录关系与主要介绍,可以移步OneOS官网开发文档页面进行详细阅读参考,地址连接为:https://os.iot.10086.cn/doc/。
    Demo 的工程目录内容与OneOS官方一致,应用于源码文件存放于 application文件夹下,开发板相关源码存放于board 文件夹下,通过OneOS-Cube进行工程设置,关于如何使用OneOs-Cube也可以在OneOS官网开发文档页面找到对应描述。

    3.例程简介

    这里我们简要说明相关的例程结构与大致作用:

    Demo名称简要说明
    oo_Customer_Sample_Project用户工程
    01_UserButton_Key_Demo用户按键部分-标准IO按键例程
    02_Peripheral_BUZZER_Demo外设部分-蜂鸣器例程
    03_Peripheral_RGB_PWM_Demo外设部分-PWM驱动RGB例程
    04_Peripheral_AHT20_Demo外设部分-AHT20例程
    05_Peripheral_ESP8266_Demo外设部分-ESP8266例程

    每个Demo都有详尽的例程说明注释,在使用Demo进行调试前,请务必进行阅读:

    // *************************** 例程说明 ***************************
    // 
    // 测试需要准备  一块
    // 推荐 MDK 版本为 MDK5.28a
    // 
    // 调试下载需要准备 <逐飞科技 CMSIS-DAP 调试下载器> 或  一个
    // 或者使用 <标准 Jlink> 进行下载调试连接亦可
    // 
    // 确认连接无误 上电 可使用调试下载器供电 但推荐使用 USB供电 可通过CH340的Type-C进行供电isp下载hex
    // 烧录本例程后 如果使用的是 <逐飞科技 CMSIS-DAP 调试下载器> 或 
    // 可以直接在串口助手中打开对应串口
    // 如果使用的并不是 <逐飞科技 CMSIS-DAP 调试下载器> 或 下载bin
    // 请接上 CH340 标识的Type-C接口到电脑USB 再打开串口调试助手打开对应串口
    // 
    // 本工程为用户示例工程 仅开启基础功能
    // 
    // 打开新的工程或者工程移动了位置务必执行以下操作
    // 第一步 关闭上面所有打开的文件
    // 第二步 project->clean  等待下方进度条走完
    // 
    // 2021-08-12	SEEKFREE
    // 
    // *************************** 例程说明 ***************************
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    根据不同的Demo,说明内容会有所不一样,相关的提示信息不在这里进行赘述。源码
    中有详尽的对应注释,供参考学习使用。

    4. 实验验证

    本实验一共有六个实验,

    4.1 用户工程

    • 核心代码
    /**
     ***********************************************************************************************************************
     * Copyright (c) 2020, China Mobile Communications Group Co.,Ltd.
     *
     * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with 
     * the License. You may obtain a copy of the License at
     *
     *     http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
     * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
     * specific language governing permissions and limitations under the License.
     *
     * @file        main.c
     *
     * @brief       User application entry
     *
     * @revision
     * Date         Author          Notes
     * 2020-02-20   OneOS Team      First Version
     ***********************************************************************************************************************
     */
    
    #include 
    #include 
    
    // *************************** 例程说明 ***************************
    // 
    // 测试需要准备  一块
    // 推荐 MDK 版本为 MDK5.28a
    // 
    // 调试下载需要准备 <逐飞科技 CMSIS-DAP 调试下载器> 或  一个
    // 或者使用 <标准 Jlink> 进行下载调试连接亦可
    // 
    // 确认连接无误 上电 可使用调试下载器供电 但推荐使用 USB供电 可通过CH340的Type-C进行供电
    // 烧录本例程后 如果使用的是 <逐飞科技 CMSIS-DAP 调试下载器> 或 
    // 可以直接在串口助手中打开对应串口
    // 如果使用的并不是 <逐飞科技 CMSIS-DAP 调试下载器> 或 
    // 请接上 CH340 标识的Type-C接口到电脑USB 再打开串口调试助手打开对应串口
    // 
    // 本工程为用户示例工程 仅开启基础功能
    // 
    // 打开新的工程或者工程移动了位置务必执行以下操作
    // 第一步 关闭上面所有打开的文件
    // 第二步 project->clean  等待下方进度条走完
    // 
    // 2021-08-12	SEEKFREE
    // 
    // *************************** 例程说明 ***************************
    
    static void user_task(void *parameter)
    {
    	os_int32_t time_count = 1;
    
    	os_task_msleep(1000);
    	os_kprintf("\r\nWhat's up?\r\n");
        while (1)
        {
    		os_kprintf("%dh %dm %ds was wasted.\r\n", time_count/3600, time_count/60%60, time_count%60);
    		time_count++;
    		os_task_msleep(1000);
        }
    }
    
    int main(void)
    {
        os_task_t *task;
    
        task = os_task_create("user", user_task, NULL, 1024, 3);
        OS_ASSERT(task);
        os_task_startup(task);
    
        return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 代码分析
      创建一个task线程,调用user_task函数,然后开始计时打印显示
    • 调试效果
    21:01:23.796 -> [0] W/STARTUP: OneOS kernel start, version: Kernel-V2.0.1-20210118 [_k_startup][251]
    21:01:23.802 -> 
    21:01:23.802 -> 
    21:01:23.804 -> sh>
    21:01:24.795 -> What's up?
    21:01:24.795 -> 0h 0m 1s was wasted.
    21:01:25.796 -> 0h 0m 2s was wasted.
    21:01:26.796 -> 0h 0m 3s was wasted.
    21:01:27.797 -> 0h 0m 4s was wasted.
    21:01:28.796 -> 0h 0m 5s was wasted.
    21:01:29.795 -> 0h 0m 6s was wasted.
    21:01:30.797 -> 0h 0m 7s was wasted.
    21:01:31.797 -> 0h 0m 8s was wasted.
    21:01:32.796 -> 0h 0m 9s was wasted.
    21:01:33.796 -> 0h 0m 10s was wasted.
    21:01:35.019 -> 0h 0m 11s was wasted.
    21:01:35.797 -> 0h 0m 12s was wasted.
    21:01:37.702 -> 0h 0m 13s was wasted.
    21:01:37.796 -> 0h 0m 14s was wasted.
    21:01:38.796 -> 0h 0m 15s was wasted.
    21:01:39.796 -> 0h 0m 16s was wasted.
    21:01:40.796 -> 0h 0m 17s was wasted.
    21:01:41.796 -> 0h 0m 18s was wasted.
    21:01:42.796 -> 0h 0m 19s was wasted.
    21:01:43.796 -> 0h 0m 20s was wasted.
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    4.2 用户按键部分-标准IO按键例程

    • 核心代码
    /**
     ***********************************************************************************************************************
     * Copyright (c) 2020, China Mobile Communications Group Co.,Ltd.
     *
     * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with 
     * the License. You may obtain a copy of the License at
     *
     *     http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
     * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
     * specific language governing permissions and limitations under the License.
     *
     * @file        main.c
     *
     * @brief       User application entry
     *
     * @revision
     * Date         Author          Notes
     * 2020-02-20   OneOS Team      First Version
     ***********************************************************************************************************************
     */
    
    #include 
    #include 
    
    // *************************** 例程说明 ***************************
    // 
    // 测试需要准备  一块
    // 推荐 MDK 版本为 MDK5.28a
    // 
    // 调试下载需要准备 <逐飞科技 CMSIS-DAP 调试下载器> 或  一个
    // 或者使用 <标准 Jlink> 进行下载调试连接亦可
    // 
    // 确认连接无误 上电 可使用调试下载器供电 但推荐使用 USB供电 可通过CH340的Type-C进行供电
    // 烧录本例程后 如果使用的是 <逐飞科技 CMSIS-DAP 调试下载器> 或 
    // 可以直接在串口助手中打开对应串口
    // 如果使用的并不是 <逐飞科技 CMSIS-DAP 调试下载器> 或 
    // 请接上 CH340 标识的Type-C接口到电脑USB 再打开串口调试助手打开对应串口
    // 
    // 按下主板上对应按键后 程序会通过 shell 输出信息
    // 
    // 本例程示范将 S1初始化为普通IO按键 S2/S3初始化为中断输入按键
    // 按下S1会输出按键计数复位信息
    // 按下S2会输出按键计数增加信息
    // 按下S3会输出按键计数减少信息
    // 
    // 打开新的工程或者工程移动了位置务必执行以下操作
    // 第一步 关闭上面所有打开的文件
    // 第二步 project->clean  等待下方进度条走完
    // 
    // 2021-08-12	SEEKFREE
    // 
    // *************************** 例程说明 ***************************
    
    void key2_handler (void *args)																// 按键 S2 的回调处理函数
    {
    	*((os_uint32_t *)args) += 1;															// 按键 S3 触发中断回调 将传参的指针指向的 key_count 加一
    }
    
    void key3_handler (void *args)																// 按键 S3 的回调处理函数
    {
    	*((os_uint32_t *)args) -= 1;															// 按键 S3 触发中断回调 将传参的指针指向的 key_count 减一
    }
    
    static void user_task(void *parameter)
    {
        os_uint32_t key_count = 0;
        os_uint32_t key_count_last = 0;
    	os_uint8_t key_state = 0;
    
    	os_pin_mode(key_table[0].pin, key_table[0].mode);										// 将按键初始化为 普通IO 输入模式 参数详见 bsp/board.c
    	os_pin_attach_irq(key_table[1].pin, key_table[1].irq_mode, key2_handler, &key_count);	// 将按键初始化为 中断输入IO 下降沿触发 参数详见 bsp/board.c 关联回调函数 key2_handler 传参 key_count 的地址
    	os_pin_attach_irq(key_table[2].pin, key_table[2].irq_mode, key3_handler, &key_count);	// 将按键初始化为 中断输入IO 下降沿触发 参数详见 bsp/board.c 关联回调函数 key3_handler 传参 key_count 的地址
    	os_pin_irq_enable(key_table[1].pin, ENABLE);											// 使能按键的中断
    	os_pin_irq_enable(key_table[2].pin, ENABLE);											// 使能按键的中断
    	key_state = os_pin_read(key_table[0].pin);												// 获取默认的 S1 按键状态
    
    	os_task_msleep(1000);
    	os_kprintf("\r\nkey test is running.\r\n");
        while (1)
        {
    		if(os_pin_read(key_table[0].pin) != key_state)										// 按键 S1 状态发生变化
    		{
    			key_count = 0;																	// 清空 key_count 计数
    			os_kprintf("key_count was reset.\r\n");											// 通过 shell 输出计数复位提示信息
    			os_task_msleep(500);															// 延时 主要是防止反复触发消抖
    		}
    		key_state = os_pin_read(key_table[0].pin);											// 更新按键 S1 状态
    
    		if(key_count_last != key_count)														// 计数状态变更
    		{
    			key_count_last = key_count;														// 更新计数状态
    			os_kprintf("key_count is %d.\r\n", key_count);									// 输出当前按键计数状态
    		}
    		os_task_msleep(10);
        }
    }
    
    int main(void)
    {
        os_task_t *task;
    
        task = os_task_create("user", user_task, NULL, 1024, 3);
        OS_ASSERT(task);
        os_task_startup(task);
    
        return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 代码分析
      本例程示范将 S1初始化为普通IO按键 S2/S3初始化为中断输入按键,按下S1会输出按键计数复位信息, 按下S2会输出按键计数增加信息,按下S3会输出按键计数减少信息
    • 调试效果
    21:03:53.587 -> [0] W/STARTUP: OneOS kernel start, version: Kernel-V2.0.1-20210118 [_k_startup][251]
    21:03:53.593 -> 
    21:03:53.593 -> 
    21:03:53.595 -> sh>
    21:03:54.588 -> key test is running.
    21:03:56.947 -> key_count was reset.
    21:03:58.057 -> key_count is 1.
    21:04:00.517 -> key_count is 2.
    21:04:00.657 -> key_count is 5.
    21:04:00.827 -> key_count is 6.
    21:04:00.947 -> key_count is 7.
    21:04:01.128 -> key_count is 8.
    21:04:01.798 -> key_count is 7.
    21:04:02.138 -> key_count is 6.
    21:04:02.437 -> key_count is 5.
    21:04:02.738 -> key_count is 4.
    21:04:02.927 -> key_count is 2.
    21:04:03.318 -> key_count is 1.
    21:04:03.857 -> key_count is -3.
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    4.3 外设部分-蜂鸣器例程

    • 核心代码
    /**
     ***********************************************************************************************************************
     * Copyright (c) 2020, China Mobile Communications Group Co.,Ltd.
     *
     * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with 
     * the License. You may obtain a copy of the License at
     *
     *     http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
     * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
     * specific language governing permissions and limitations under the License.
     *
     * @file        main.c
     *
     * @brief       User application entry
     *
     * @revision
     * Date         Author          Notes
     * 2020-02-20   OneOS Team      First Version
     ***********************************************************************************************************************
     */
    
    #include 
    #include 
    
    // *************************** 例程说明 ***************************
    // 
    // 测试需要准备  一块
    // 推荐 MDK 版本为 MDK5.28a
    // 
    // 调试下载需要准备 <逐飞科技 CMSIS-DAP 调试下载器> 或  一个
    // 或者使用 <标准 Jlink> 进行下载调试连接亦可
    // 
    // 确认连接无误 上电 可使用调试下载器供电 但推荐使用 USB供电 可通过CH340的Type-C进行供电
    // 烧录本例程后 如果使用的是 <逐飞科技 CMSIS-DAP 调试下载器> 或 
    // 可以直接在串口助手中打开对应串口
    // 如果使用的并不是 <逐飞科技 CMSIS-DAP 调试下载器> 或 
    // 请接上 CH340 标识的Type-C接口到电脑USB 再打开串口调试助手打开对应串口
    // 
    // 本例程示范将 B1初始化为IO控制蜂鸣器
    // 跟随时间蜂鸣器间隔会变短
    // 最终长鸣后重新开始循环
    // 会有信息通过 shell 输出
    // 
    // 打开新的工程或者工程移动了位置务必执行以下操作
    // 第一步 关闭上面所有打开的文件
    // 第二步 project->clean  等待下方进度条走完
    // 
    // 2021-08-12	SEEKFREE
    // 
    // *************************** 例程说明 ***************************
    
    static void user_task(void *parameter)
    {
    	os_uint16_t count = 950;
    
    	os_task_msleep(1000);
        os_pin_mode(beep_table[0].pin, PIN_MODE_OUTPUT);
    
        while (1)
        {
    		os_pin_write(beep_table[0].pin, beep_table[0].active_level);
    		os_task_msleep(50);
    		os_pin_write(beep_table[0].pin, !beep_table[0].active_level);
    		os_task_msleep(count);
    		os_kprintf("count: %d\r\n",count);
    
    		count -= 10;
    		if(count == 0)
    		{
    			os_kprintf("\r\nBOOM!");
    			os_pin_write(beep_table[0].pin, beep_table[0].active_level);
    			os_task_msleep(1000);
    			os_pin_write(beep_table[0].pin, !beep_table[0].active_level);
    			os_task_msleep(1000);
    			count = 950;
    		}
        }
    }
    
    int main(void)
    {
        os_task_t *task;
    
        task = os_task_create("user", user_task, NULL, 1024, 3);
        OS_ASSERT(task);
        os_task_startup(task);
    
        return 0;
    }
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 代码分析
      本例程示范将 B1初始化为IO控制蜂鸣器, 跟随时间蜂鸣器间隔会变短,最终长鸣后重新开始循环,打印延时时间间隔。
    • 调试效果
    21:11:35.211 -> [0] W/STARTUP: OneOS kernel start, version: Kernel-V2.0.1-20210118 [_k_startup][251]
    21:11:35.216 -> 
    21:11:35.216 -> 
    21:11:35.219 -> sh>count: 950
    21:11:38.201 -> count: 940
    21:11:39.179 -> count: 930
    21:11:40.150 -> count: 920
    21:11:41.110 -> count: 910
    21:11:42.061 -> count: 900
    21:11:42.999 -> count: 890
    21:11:43.930 -> count: 880
    21:11:44.850 -> count: 870
    21:11:45.760 -> count: 860
    21:11:46.659 -> count: 850
    21:11:47.550 -> count: 840
    21:11:48.430 -> count: 830
    21:11:49.300 -> count: 820
    21:11:50.160 -> count: 810
    21:11:51.010 -> count: 800
    21:11:51.850 -> count: 790
    21:11:52.680 -> count: 780
    21:11:53.500 -> count: 770
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    4.4 外设部分-PWM驱动RGB例程

    • 核心代码
    /**
     ***********************************************************************************************************************
     * Copyright (c) 2020, China Mobile Communications Group Co.,Ltd.
     *
     * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with 
     * the License. You may obtain a copy of the License at
     *
     *     http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
     * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
     * specific language governing permissions and limitations under the License.
     *
     * @file        main.c
     *
     * @brief       User application entry
     *
     * @revision
     * Date         Author          Notes
     * 2020-02-20   OneOS Team      First Version
     ***********************************************************************************************************************
     */
    
    #include 
    #include 
    
    // *************************** 例程说明 ***************************
    // 
    // 测试需要准备  一块
    // 推荐 MDK 版本为 MDK5.28a
    // 
    // 调试下载需要准备 <逐飞科技 CMSIS-DAP 调试下载器> 或  一个
    // 或者使用 <标准 Jlink> 进行下载调试连接亦可
    // 
    // 确认连接无误 上电 可使用调试下载器供电 但推荐使用 USB供电 可通过CH340的Type-C进行供电
    // 烧录本例程后 如果使用的是 <逐飞科技 CMSIS-DAP 调试下载器> 或 
    // 可以直接在串口助手中打开对应串口
    // 如果使用的并不是 <逐飞科技 CMSIS-DAP 调试下载器> 或 
    // 请接上 CH340 标识的Type-C接口到电脑USB 再打开串口调试助手打开对应串口
    // 
    // 本例程示范将 A1-A3初始化为IO控制RGB灯珠
    // 跟随时间RGB灯珠换色间隔会变短
    // 最终常亮白光后重新开始循环
    // 会有信息通过 shell 输出
    // 
    // 打开新的工程或者工程移动了位置务必执行以下操作
    // 第一步 关闭上面所有打开的文件
    // 第二步 project->clean  等待下方进度条走完
    // 
    // 2021-08-12	SEEKFREE
    // 
    // *************************** 例程说明 ***************************
    
    static void user_task(void *parameter)
    {
        int i = 0;
    	os_uint16_t count = 1000;
    
        for (i = 0; i < led_table_size; i++)
        {
            os_pin_mode(led_table[i].pin, PIN_MODE_OUTPUT);
            os_pin_write(led_table[i].pin, led_table[i].active_level);
        }
    	os_task_msleep(1000);
    
        while (1)
        {
            for (i = 0; i < led_table_size; i++)
            {
                os_pin_write(led_table[i].pin, !led_table[i].active_level);
                os_task_msleep(count);
                os_pin_write(led_table[i].pin, led_table[i].active_level);
            }
    		os_kprintf("count: %d\r\n",count);
    		count -= 50;
    		if(count == 0)
    		{
    			os_kprintf("\r\nFlash!");
    			for (i = 0; i < led_table_size; i++)
    			{
    				os_pin_write(led_table[i].pin, !led_table[i].active_level);
    			}
    			os_task_msleep(1000);
    			for (i = 0; i < led_table_size; i++)
    			{
    				os_pin_write(led_table[i].pin, led_table[i].active_level);
    			}
    			os_task_msleep(1000);
    			count = 1000;
    		}
        }
    }
    
    int main(void)
    {
        os_task_t *task;
    
        task = os_task_create("user", user_task, NULL, 1024, 3);
        OS_ASSERT(task);
        os_task_startup(task);
    
        return 0;
    }
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 代码分析
      本例程示范将 A1-A3初始化为IO控制RGB灯珠, 打印打开LED时间,跟随时间RGB灯珠换色间隔会变短,最终常亮白光后重新开始循环。
    • 调试效果
    21:21:39.775 -> [0] W/STARTUP: OneOS kernel start, version: Kernel-V2.0.1-20210118 [_k_startup][251]
    21:21:39.780 -> 
    21:21:39.780 -> 
    21:21:39.783 -> sh>count: 1000
    21:21:46.623 -> count: 950
    21:21:49.324 -> count: 900
    21:21:51.874 -> count: 850
    21:21:54.274 -> count: 800
    21:21:56.524 -> count: 750
    21:21:58.624 -> count: 700
    21:22:00.574 -> count: 650
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    4.5 外设部分-AHT20例程

    • 核心代码
    /**
     ***********************************************************************************************************************
     * Copyright (c) 2020, China Mobile Communications Group Co.,Ltd.
     *
     * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with 
     * the License. You may obtain a copy of the License at
     *
     *     http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
     * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
     * specific language governing permissions and limitations under the License.
     *
     * @file        main.c
     *
     * @brief       User application entry
     *
     * @revision
     * Date         Author          Notes
     * 2020-02-20   OneOS Team      First Version
     ***********************************************************************************************************************
     */
    
    #include 
    #include 
    #include 
    
    // *************************** 例程说明 ***************************
    // 
    // 测试需要准备  一块
    // 推荐 MDK 版本为 MDK5.28a
    // 
    // 调试下载需要准备 <逐飞科技 CMSIS-DAP 调试下载器> 或  一个
    // 或者使用 <标准 Jlink> 进行下载调试连接亦可
    // 
    // 确认连接无误 上电 可使用调试下载器供电 但推荐使用 USB供电 可通过CH340的Type-C进行供电
    // 烧录本例程后 如果使用的是 <逐飞科技 CMSIS-DAP 调试下载器> 或 
    // 可以直接在串口助手中打开对应串口
    // 如果使用的并不是 <逐飞科技 CMSIS-DAP 调试下载器> 或 
    // 请接上 CH340 标识的Type-C接口到电脑USB 再打开串口调试助手打开对应串口
    // 
    // 本例程示范将 开发板上AHT20传感器通过软件IIC1总线初始化
    // 每间隔一秒输出一次当前温湿度信息
    // 相关信息通过 shell 输出
    // 
    // 打开新的工程或者工程移动了位置务必执行以下操作
    // 第一步 关闭上面所有打开的文件
    // 第二步 project->clean  等待下方进度条走完
    // 
    // 2021-08-12	SEEKFREE
    // 
    // *************************** 例程说明 ***************************
    
    static void user_task(void *parameter)
    {
        struct os_sensor_data sensor_data;																				// 新建一个数据存放结构体
    
    	os_task_msleep(1000);
    	os_kprintf("\r\nAHT20 test running.\r\n");
    
    	// 为什么 AHT20 需要两个设备 这是因为驱动文件中将其拆分成了两个部分 分别是湿度与温度 注册成了两个设备
        os_device_t *sensor_humi = os_device_find("humi_aht20");														// 通过设备名找到 humi_aht20
        OS_ASSERT(sensor_humi != NULL);																					// 如果没有该设备则报错
        os_device_open(sensor_humi);																					// 找到设备就打开设备
    	
        os_device_t *sensor_temp = os_device_find("temp_aht20");														// 通过设备名找到 temp_aht20
        OS_ASSERT(sensor_temp != NULL);																					// 如果没有该设备则报错
        os_device_open(sensor_temp);																					// 找到设备就打开设备
    
    	while(1)
    	{
            os_device_read_nonblock(sensor_humi, 0, &sensor_data, sizeof(struct os_sensor_data));						// 通过设备读取数据
            os_kprintf("sensor humi (%d.%03d)%\r\n", sensor_data.data.humi / 1000, sensor_data.data.humi % 1000);		// 将数据通过 shell 输出
    
            os_device_read_nonblock(sensor_temp, 0, &sensor_data, sizeof(struct os_sensor_data));						// 通过设备读取数据
            os_kprintf("sensor temp (%d.%03d)℃\r\n", sensor_data.data.temp / 1000, sensor_data.data.temp % 1000);		// 将数据通过 shell 输出
    
    		os_task_msleep(1000);
    	}
    }
    
    int main(void)
    {
        os_task_t *task;
    
        task = os_task_create("user", user_task, NULL, 1024, 3);
        OS_ASSERT(task);
        os_task_startup(task);
    
        return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 代码分析
      本例程示范将 开发板上AHT20传感器通过软件IIC1总线初始化, 每间隔一秒输出一次当前温湿度信息
    • 调试效果
    21:12:03.928 -> [0] W/STARTUP: OneOS kernel start, version: Kernel-V2.0.1-20210118 [_k_startup][251]
    21:12:03.933 -> 
    21:12:03.933 -> [0] I/sensor.sensirion.aht20: aht20:[soft_i2c1][0x38] [aht20_init][111]
    21:12:03.942 -> [71] I/sensor: os_sensor init success [os_hw_sensor_register][296]
    21:12:04.646 -> [99] I/sensor.sensirion.aht20: aht20 temp init success [os_hw_aht20_temp_init][260]
    21:12:04.926 -> [100] I/sensor.sensirion.aht20: aht20:[soft_i2c1][0x38] [aht20_init][111]
    21:12:04.936 -> [170] I/sensor: os_sensor init success [os_hw_sensor_register][296]
    21:12:05.637 -> [198] I/sensor.sensirion.aht20: aht20 baro init success [os_hw_aht20_humi_init][371]
    21:12:05.916 -> 
    21:12:05.918 -> 
    21:12:05.918 -> sh>
    21:12:06.919 -> AHT20 test running.
    21:12:07.193 -> sensor humi (50.042)%
    21:12:07.468 -> sensor temp (26.072)¡æ
    21:12:08.741 -> sensor humi (49.559)%
    21:12:09.016 -> sensor temp (26.084)¡æ
    21:12:10.281 -> sensor humi (49.169)%
    21:12:10.556 -> sensor temp (26.106)¡æ
    21:12:11.820 -> sensor humi (48.857)%
    21:12:12.096 -> sensor temp (26.112)¡æ
    21:12:13.361 -> sensor humi (48.557)%
    21:12:13.635 -> sensor temp (26.094)¡æ
    21:12:14.901 -> sensor humi (48.214)%
    21:12:15.176 -> sensor temp (26.067)¡æ
    21:12:16.441 -> sensor humi (47.876)%
    21:12:16.715 -> sensor temp (26.070)¡æ
    21:12:17.981 -> sensor humi (47.640)%
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    4.6 外设部分-ESP8266例程

    • 核心代码
    /**
     ***********************************************************************************************************************
     * Copyright (c) 2020, China Mobile Communications Group Co.,Ltd.
     *
     * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with 
     * the License. You may obtain a copy of the License at
     *
     *     http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
     * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
     * specific language governing permissions and limitations under the License.
     *
     * @file        main.c
     *
     * @brief       User application entry
     *
     * @revision
     * Date         Author          Notes
     * 2020-02-20   OneOS Team      First Version
     ***********************************************************************************************************************
     */
    
    #include 
    #include 
    
    #include "mo_common.h"
    #include "esp8266.h"
    
    // *************************** 例程说明 ***************************
    // 
    // 测试需要准备  一块
    // 推荐 MDK 版本为 MDK5.28a
    // 
    // 调试下载需要准备 <逐飞科技 CMSIS-DAP 调试下载器> 或  一个
    // 或者使用 <标准 Jlink> 进行下载调试连接亦可
    // 
    // 确认连接无误 上电 可使用调试下载器供电 但推荐使用 USB供电 可通过CH340的Type-C进行供电
    // 烧录本例程后 如果使用的是 <逐飞科技 CMSIS-DAP 调试下载器> 或 
    // 可以直接在串口助手中打开对应串口
    // 如果使用的并不是 <逐飞科技 CMSIS-DAP 调试下载器> 或 
    // 请接上 CH340 标识的Type-C接口到电脑USB 再打开串口调试助手打开对应串口
    // 
    // 本例程示范将 开发板上ESP8266WIFI模块通过Molink组件初始化
    // 输出自身IP地址 进行Ping测试 
    // 然后构建 TCP 连接 并且对远端地址进行收发数据测试
    // 相关信息通过 shell 输出
    // 
    // 需要先行设置 
    // OneOS-Cube->Components->Network->Molink->Enable IoT Modules->WiFi Modules Support->ESP8266->ESP8266 Config
    // ESP8266 Connect AP SSID 为测试环境的 WiFi 名称/SSID
    // ESP8266 Connect AP Password 为测试环境的 WiFi 密码/Password
    // 
    // 本例程需要一个可以使用网络调试功能的调试助手
    // 可以使用 sscom 端口设置为 TCP_Server 并更根据地址更改下方 REMOTE_IP
    // 端口默认设置为 8080 端口
    // 设置完成后点击侦听准备好测试
    // 
    // 确认准备完成后烧录程序开始运行测试
    // 
    // 打开新的工程或者工程移动了位置务必执行以下操作
    // 第一步 关闭上面所有打开的文件
    // 第二步 project->clean  等待下方进度条走完
    // 
    // 2021-08-12	SEEKFREE
    // 
    // *************************** 例程说明 ***************************
    
    #define PING_IP				"192.168.1.110"											// PING 测试的对象地址 这里可以设置为网关 根据测试自行修改
    #define REMOTE_IP			"192.168.2.16"											// 远端通信地址 这里设置为测试时使用的的电脑的IP
    #define REMOTE_PORT			8080													// 通信端口
    
    static void user_task(void *parameter)
    {
    	os_err_t molink_result = OS_ERROR;												// 执行状态变量
    
    	mo_object_t *molink_modle = mo_get_by_name(ESP8266_NAME);						// 获取 ESP8266 对象
    	OS_ASSERT(molink_modle != OS_NULL);												// 确认对象实例正常
    
    	char molink_data_buffer[16];													// 新建一个缓冲区用来存放 IP 地址
    	molink_result = mo_get_ipaddr(molink_modle, molink_data_buffer);				// 获取自身的 IP 地址
    	if(molink_result != OS_EOK)														// 判断获取是否成功
    	{
    		LOG_W("mo_get_ipaddr", "get ipaddr faild.");								// 获取地址失败 输出错误信息
    	}
    	else
    	{
    		LOG_I("mo_get_ipaddr", "IP:%s.", molink_data_buffer);						// 获取地址成功 输出 IP 地址信息
    	}
    
    	ping_resp_t ping_test_t;														// 新建 ping 测试结构体
    	molink_result = mo_ping(molink_modle, PING_IP, 64, 10, &ping_test_t);			// ping 测试
    	if(molink_result != OS_EOK)														// 判断是否测试成功
    	{
    		LOG_W("mo_ping", "ping faild.");											// ping 测试失败 输出错误信息
    	}
    	else
    	{
    		LOG_I("mo_ping", "PING IP:%s | LEN:%d | TIME OUT:%d | TIME RESPONSE:%d.", 	// ping 测试成功 输出 ping 结果信息
    			inet_ntoa(ping_test_t.ip_addr.addr),									// 将 IP 从数字模式转换为字符串
    			ping_test_t.data_len,													// 显示 ping 测试的数据长度
    			ping_test_t.ttl,														// 显示超时时长
    			ping_test_t.time);														// 显示延迟时间
    	}
    
    	mo_netconn_t *test_netconn = mo_netconn_create(molink_modle, NETCONN_TYPE_TCP);	// 新建构建 netceonn 的对象实例 方式为 TCP
    	if(test_netconn == OS_NULL)														// 判断是否新建实例成功
    	{
    		LOG_W("mo_netconn_create", "netconn create faild.");						// 新建实例出错 输出错误信息
    	}
    
        ip_addr_t server_addr = {0};													// 新建一个 IP 地址的缓冲区
        inet_aton(REMOTE_IP, &server_addr);												// 将远端 IP 地址转换为数字形式
    	molink_result = mo_netconn_connect(molink_modle, test_netconn, server_addr, REMOTE_PORT);	// 对该地址建立连接
    	if(molink_result != OS_EOK)														// 判断是否连接建立成功
    	{
    		LOG_W("mo_netconn_connect", "netconn connect faild.");						// 建立连接错误 输出错误信息
    	}
    	else
    	{
    		LOG_I("mo_netconn_connect", "remote IP:%s.", REMOTE_IP);					// 建立连接成功 输出远端 IP
    	}
    
        os_size_t sent_size = mo_netconn_send(molink_modle, test_netconn, "Hello", 5);	// 对远端发送数据
    	if(sent_size != 5)																// 判断发送数据长度跟
    	{
    		LOG_W("mo_netconn_send", "netconn send faild.");
    	}
    	else
    	{
    		LOG_I("mo_netconn_send", "send success.");
    	}
    
        void *data_ptr = OS_NULL;
        os_size_t data_size = 0;
        while (1)
        {
    		molink_result = mo_netconn_recv(molink_modle, test_netconn, &data_ptr, &data_size, OS_WAIT_FOREVER);
    		if(molink_result != OS_EOK)
    		{
    			LOG_W("mo_netconn_recv", "netconn recv faild.");
    		}
    		else
    		{
    			LOG_I("mo_netconn_recv",
    				"Module %s, netconn %d, receive data_len: %d, message: %s.",
    				molink_modle->name,
    				test_netconn->connect_id,
    				data_size,
    				data_ptr
    			);
    			sent_size = mo_netconn_send(molink_modle, test_netconn, data_ptr, data_size);
    			if(sent_size != data_size)
    			{
    				LOG_W("mo_netconn_send", "netconn send faild.");
    			}
    			else
    			{
    				LOG_I("mo_netconn_send", "send success.");
    			}
    		}
        }
    }
    
    int main(void)
    {
        os_task_t *task;
    
        task = os_task_create("user", user_task, NULL, 1024*8, 3);
        OS_ASSERT(task);
        os_task_startup(task);
    
        return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 代码分析
      // 本例程示范将 开发板上ESP8266WIFI模块通过Molink组件初始化
      // 输出自身IP地址 进行Ping测试
      // 然后构建 TCP 连接 并且对远端地址进行收发数据测试
      // 相关信息通过 shell 输出
      //
      // 需要先行设置
      // OneOS-Cube->Components->Network->Molink->Enable IoT Modules->WiFi Modules Support->ESP8266->ESP8266 Config
      // ESP8266 Connect AP SSID 为测试环境的 WiFi 名称/SSID
      // ESP8266 Connect AP Password 为测试环境的 WiFi 密码/Password
      //
      // 本例程需要一个可以使用网络调试功能的调试助手
      // 可以使用 sscom 端口设置为 TCP_Server 并更根据地址更改下方 REMOTE_IP
      // 端口默认设置为 8080 端口
      // 设置完成后点击侦听准备好测试
    • 调试效果
      我的wifi正常连接,但是tcp无法接入
      在这里插入图片描述
    22:02:01.548 -> [0] W/STARTUP: OneOS kernel start, version: Kernel-V2.0.1-20210118 [_k_startup][251]
    22:02:01.553 -> 
    22:02:01.553 -> [302] I/esp8266.wifi: ESP8266 WIFI disconnected. [urc_connect_func][333]
    22:02:04.575 -> [548] I/esp8266.wifi: ESP8266 WIFI connected. [urc_connect_func][328]
    22:02:07.039 -> [802] I/esp8266: Auto create esp8266 module object success! [esp8266_auto_create][302]
    22:02:09.574 -> 
    22:02:09.576 -> sh>[803] I/mo_get_ipaddr: IP:192.168.1.110. [user_task][88]
    22:02:09.590 -> [895] E/at.parser: execute command (AT+PING="192.168.1.110") failed, parser->resp_status:2 [at_parser_exec_cmd_valist][248]
    22:02:10.517 -> [897] W/mo_ping: ping faild. [user_task][95]
    22:02:10.521 -> [1220] E/at.parser: execute command (AT+CIPSTART=0,"TCP","192.168.2.16",8080,60) failed, parser->resp_status:2 [at_parser_exec_cmd_valist][248]
    22:02:13.767 -> [1222] E/esp8266.netconn: Module esp8266 connect to 192.168.2.16:8080 failed! [esp8266_netconn_connect][274]
    22:02:13.779 -> [1223] W/mo_netconn_connect: netconn connect faild. [user_task][117]
    22:02:13.783 -> [1223] E/molink.netconn: Module esp8266 netconn 0 does not connect to server, send failed! [mo_netconn_send][336]
    22:02:13.795 -> [1224] W/mo_netconn_send: netconn send faild. [user_task][127]
    22:02:13.804 -> 
    22:02:13.804 -> [1225] W/esp8266.netconn: Module esp8266 receive close urc data of connect 0 [urc_close_func][479]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    bug收集

    参照:【OneOS万耦启物】4.复位与解锁

  • 相关阅读:
    微信小程序使用echarts组件实现饼状统计图功能
    c++-基本计算器的灵活可扩展实现
    [论文笔记] ICLR 2022 | 减少跨语言表示差异,字节跳动AI Lab通过流形混合增强跨语言迁移
    rce(无回显)
    1600*C. Remove Adjacent(贪心&字符串)
    猿创征文|Apache ShenYu网关插件介绍
    130道基础OJ编程题之: 39 ~ 46 道
    OblivSketch: Oblivious Network Measurement as a Cloud Service
    vscode git 拉取报错 在签出前,请清理存储库工作树
    关于bug的分类和定金,终于有人讲明白了
  • 原文地址:https://blog.csdn.net/vor234/article/details/126631278