1. 1. 简易桌面闹钟
    1. 1.1. 实物
    2. 1.2. 整体结构
    3. 1.3. OLED示意图
      1. 1.3.1. 简易模式
    4. 1.4. 多功能模式
    5. 1.5. SysTick、SVC、PendSV
      1. 1.5.0.1. SysTick_Handler - 系统时钟
      2. 1.5.0.2. SVC_Handler - 系统启动器
      3. 1.5.0.3. PendSV_Handler - 任务切换器
  • 2. 新添内容
    1. 2.1. one-wire协议
    2. 2.2. delay
    3. 2.3. 裁剪FreeRTOS
    4. 2.4. FreeRTOS
      1. 2.4.1. 通信路径表
    5. 2.5. 运行效果
    6. 2.6. 总结
  • 在这份项目里,Bootloader使用之前Bootloader学习笔记里做的样例。

    可以说是为了这碗醋,包了这碗饺子

    简易桌面闹钟

    FreeRTOS移植:超详细的FreeRTOS移植全教程——基于stm32_freertos移植教程-CSDN博客

    时钟方面需要改用FreeRTOS的SysTick,否则系统会卡死

    实物

    整体结构

    OLED示意图

    此处OTA的值存储在AT24C02的0xF0-0XF3字节处(AT24C02总共256字节)

    简易模式

    • PA2进入多功能模式
    • PA0调整城市显示
    • PC13调整OTA状态
    • PB10可以重启设备
    • 支持震动自动切换多功能模式

    多功能模式

    • PA0进入简易模式

    • 温湿度数据1s刷新一次

    • 加速度0.5s刷新一次

    • 10s无操作自动进入简易模式

    SysTick、SVC、PendSV

    SysTick_Handler - 系统时钟

    • 就像心跳,定期检查是否需要切换任务

    • 频率固定,系统运行期间持续工作

    • 负责时间管理和调度触发

    SVC_Handler - 系统启动器

    • 就像点火器,只负责启动第一个任务

    • 只调用一次,启动后就不工作了

    • 从特权模式切换到用户模式

    PendSV_Handler - 任务切换器

    • 就像交通指挥员,负责安排哪个任务先运行

    • 需要切换时才工作,优先级最低

    • 在用户模式下进行任务切换

    Q:为什么使用PendSV_Handler来切换任务?

    Pend → 可挂起的

    SV → 系统服务

    • 中断优先级最低;不影响其他中断
    • 只能软件触发,可控;CPU不会意外触发它
    • 硬件自动保存部分上下文;减少软件负担
    特性 SysTick_Handler SVC_Handler PendSV_Handler
    全称 System Tick Handler Supervisor Call Handler Pending Service Handler
    中文名 系统滴答中断 超级调用中断 挂起服务中断
    触发方式 硬件定时器 软件调用SVC指令 软件触发PendSV

    新添内容

    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
    // 从AT24C02最后一页读取OTA_flag(4字节)
    uint32_t AT24C02_ReadOTAFlag(void)
    {
    uint8_t addr = 0xF0; // 最后一页开始地址
    uint32_t flag = 0;
    uint8_t *pflag = (uint8_t *)&flag;

    // 读取4字节的OTA_flag
    for(int i = 0; i < 4; i++)
    {
    uint8_t data = 0;
    AT24C02_ReadData(addr + i, &data, 1);
    if(data == 0xFF) // 读取失败
    {
    return 0; // 返回0表示读取失败
    }
    pflag[i] = data;
    }

    return flag;
    }
    // Bootloader跳转逻辑控制
    void Bootloader_Jump(void)
    {
    // 读取并打印OTA_flag
    uint32_t OTA_flag = AT24C02_ReadOTAFlag();//处在AT24C02的最后一页
    uprintf("OTA_flag: %d \r\n", OTA_flag);

    // 如果OTA_flag == 1,直接跳转APP
    if(OTA_flag == 1) {
    uprintf("Direct jump to APP\r\n");
    LOAD_A(FLASH_A_SADDR);
    return;
    }

    // 继续原有Bootloader逻辑
    if(Bootloader_Enter(20) == 0)
    {
    if(OTA_flag == OTA_SET_FLAG)
    {
    uprintf("OTA update \r\n");
    BootState |= UPDATA_A_FLAG;
    Updata_A.W25Q64_BlockNM = 0;
    }
    else
    {
    uprintf("Jump to Area A \r\n");
    LOAD_A(FLASH_A_SADDR);
    }
    }
    uprintf("Enter Bootloader command line \r\n");
    Bootloader_Info();
    }

    one-wire协议

    One Wire(单线)总线协议,它只需要一根数据线就能实现双向通信,大大简化了硬件连接。

    • 上拉电阻: 通常4.7kΩ,确保总线空闲时为高电平

    • 开漏输出支持线与逻辑

    【通信协议】单总线协议详解——以DHT11为例_单总线通信协议-CSDN博客

    delay

    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
    static uint8_t fac_us = 0;  // us延时倍乘数
    static uint16_t fac_ms = 0; // ms延时倍乘数,在RTOS下,代表每个节拍的ms数

    /**
    * @brief 时钟初始化 - 参考例程版本
    */
    void Delay_init(void)
    {
    uint32_t reload;
    SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK); // 选择外部时钟 HCLK
    fac_us = SystemCoreClock / 1000000; // 不论是否使用OS,fac_us都需要使用
    reload = SystemCoreClock / 1000000; // 每秒钟的计数次数 单位为M
    reload *= 1000000 / configTICK_RATE_HZ; // 根据configTICK_RATE_HZ设定溢出时间
    // reload为24位寄存器,最大值:16777216,在72M下,约合0.233s左右
    fac_ms = 1000 / configTICK_RATE_HZ; // 代表OS可以延时的最少单位

    SysTick->CTRL |= SysTick_CTRL_TICKINT_Msk; // 开启SYSTICK中断
    SysTick->LOAD = reload; // 每1/configTICK_RATE_HZ秒中断一次
    SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk; // 开启SYSTICK
    }

    /**
    * @brief 延时微妙
    * @param us 延时0~65536微秒
    */
    void Delay_us(uint32_t us)
    {
    uint32_t ticks;
    uint32_t told, tnow, tcnt = 0;
    uint32_t reload = SysTick->LOAD; // LOAD的值
    ticks = us * fac_us; // 需要的节拍数
    told = SysTick->VAL; // 刚进入时的计数器值
    while (1)
    {
    tnow = SysTick->VAL;
    if (tnow != told)
    {
    if (tnow < told)
    tcnt += told - tnow; // 这里注意一下SYSTICK是一个递减的计数器就可以了.
    else
    tcnt += reload - tnow + told;
    told = tnow;
    if (tcnt >= ticks)
    break; // 时间超过/等于要延迟的时间,则退出.
    }
    };
    }

    /**
    * @brief 延时毫秒
    * @param ms 延时0~65536毫秒
    */
    void Delay_ms(uint32_t ms)
    {
    if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) // 系统已经运行
    {
    if (ms >= fac_ms) // 延时的时间大于OS的最少时间周期
    {
    vTaskDelay(ms / fac_ms); // FreeRTOS延时
    }
    ms %= fac_ms; // OS已经无法提供这么小的延时了,采用普通方式延时
    }
    Delay_us((uint32_t)(ms * 1000)); // 普通方式延时
    }

    void Delay_s(uint32_t s)
    {
    Delay_ms(s * 1000);
    }

    /**
    * @brief 延时ms,不会引起任务调度
    * @param ms 要延时的ms数
    */
    void Delay_xms(uint16_t ms)
    {
    uint32_t i;
    for (i = 0; i < ms; i++)
    Delay_us(1000);
    }

    裁剪FreeRTOS

    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
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    300
    301
    302
    303
    304
    305
    306
    307
    308
    309
    310
    311
    312
    313
    314
    315
    316
    317
    318
    319
    320
    321
    322
    323
    324
    325
    326
    327
    328
    329
    330
    331
    332
    333
    334
    335
    336
    337
    338
    339
    340
    341
    342
    343
    344
    345
    346
    347
    348
    349
    350
    351
    352
    353
    354
    355
    356
    357
    358
    359
    360
    361
    362
    363
    364
    365
    366
    367
    368
    369
    370
    371
    372
    373
    374
    375
    376
    377
    378
    379
    380
    381
    382
    383
    384
    385
    386
    387
    388
    389
    390
    391
    392
    393
    394
    395
    396
    397
    398
    399
    400
    401
    402
    403
    404
    405
    406
    407
    408
    409
    410
    411
    412
    413
    414
    415
    416
    417
    418
    419
    420
    421
    422
    423
    424
    425
    426
    427
    428
    429
    430
    431
    432
    433
    #ifndef FREERTOS_CONFIG_H
    #define FREERTOS_CONFIG_H

    #include "stm32f10x.h"

    // 针对不同的编译器,调用不同的stdint.h文件
    #if defined(__ICCARM__) || defined(__CC_ARM) || defined(__GNUC__)
    #include <stdint.h>
    extern uint32_t SystemCoreClock;
    #endif

    // 断言配置 - 用于调试,当条件为假时停止程序
    #define configASSERT(x) \
    if ((x) == 0) \
    { \
    taskDISABLE_INTERRUPTS(); \
    while (1) \
    ; \
    }

    /************************************************************************
    * FreeRTOS基础配置选项
    *********************************************************************/

    /**
    * 调度器类型选择
    * 1: 抢占式调度器 - 高优先级任务可以抢占低优先级任务
    * 0: 协作式调度器 - 任务必须主动释放CPU才能切换
    *
    * 抢占式:就像急诊病人可以插队,高优先级任务立即执行
    * 协作式:就像排队,必须等前面的人办完事才能轮到下一个
    */
    #define configUSE_PREEMPTION 1

    /**
    * 时间片调度
    * 1: 启用时间片 - 同优先级任务轮流执行
    * 0: 禁用时间片 - 同优先级任务需要主动让出CPU
    */
    #define configUSE_TIME_SLICING 1

    /**
    * 任务选择优化
    * 1: 使用硬件优化 - 更快找到最高优先级任务
    * 0: 使用软件查找 - 兼容性更好但速度较慢
    */
    #define configUSE_PORT_OPTIMISED_TASK_SELECTION 1

    /**
    * 无滴答空闲模式
    * 1: 启用 - 空闲时停止系统滴答,省电
    * 0: 禁用 - 始终保持系统滴答运行
    */
    #define configUSE_TICKLESS_IDLE 0

    /**
    * CPU时钟频率
    * 写入实际的CPU主频,用于计算延时时间
    * 例如:72MHz = 72000000
    */
    #define configCPU_CLOCK_HZ (SystemCoreClock)

    /**
    * 系统滴答频率
    * 每秒中断次数,决定任务调度的精度
    * 1000 = 1ms一次中断,精度较高
    * 100 = 10ms一次中断,精度较低但省电
    */
    #define configTICK_RATE_HZ ((TickType_t)1000)

    /**
    * 最大优先级数量
    * 优先级范围:0 ~ (configMAX_PRIORITIES-1)
    * 数字越小优先级越高,0为最高优先级
    * 建议:根据实际任务数量设置,不要设置过大
    */
    #define configMAX_PRIORITIES (16)

    /**
    * 空闲任务栈大小
    * 空闲任务用于系统空闲时的处理
    * 单位:字(4字节)
    */
    #define configMINIMAL_STACK_SIZE ((unsigned short)64)

    /**
    * 任务名称最大长度
    * 用于调试时显示任务名称
    * 建议:8-16个字符
    */
    #define configMAX_TASK_NAME_LEN (12)

    /**
    * 滴答计数器数据类型
    * 1: 16位 - 最大65535个滴答(约65秒)
    * 0: 32位 - 最大4294967295个滴答(约49天)
    */
    #define configUSE_16_BIT_TICKS 0

    /**
    * 空闲任务让出CPU
    * 1: 启用 - 空闲时让出CPU给同优先级任务
    * 0: 禁用 - 空闲任务一直运行
    */
    #define configIDLE_SHOULD_YIELD 1

    /**
    * 队列集功能
    * 1: 启用 - 可以等待多个队列
    * 0: 禁用 - 只能等待单个队列
    */
    #define configUSE_QUEUE_SETS 0

    /**
    * 任务通知功能
    * 1: 启用 - 轻量级任务间通信
    * 0: 禁用 - 只能使用队列和信号量
    */
    #define configUSE_TASK_NOTIFICATIONS 1

    /**
    * 互斥量功能
    * 1: 启用 - 用于保护共享资源
    * 0: 禁用 - 无法使用互斥量
    */
    #define configUSE_MUTEXES 1

    /**
    * 递归互斥量功能
    * 1: 启用 - 同一任务可以多次获取同一个互斥量
    * 0: 禁用 - 只能获取一次
    */
    #define configUSE_RECURSIVE_MUTEXES 1

    /**
    * 计数信号量功能
    * 1: 启用 - 用于资源计数
    * 0: 禁用 - 无法使用计数信号量
    */
    #define configUSE_COUNTING_SEMAPHORES 1

    /**
    * 事件组功能
    * 1: 启用 - 用于多任务同步
    * 0: 禁用 - 无法使用事件组
    */
    #define configUSE_EVENT_GROUPS 1

    /**
    * 队列注册表大小
    * 用于调试时跟踪队列和信号量
    * 建议:根据实际使用的队列数量设置
    */
    #define configQUEUE_REGISTRY_SIZE 6

    /**
    * 任务标签功能
    * 1: 启用 - 可以为任务设置标签
    * 0: 禁用 - 无法使用任务标签
    */
    #define configUSE_APPLICATION_TASK_TAG 0

    /*****************************************************************
    FreeRTOS内存管理配置选项
    *****************************************************************/

    /**
    * 动态内存分配
    * 1: 启用 - 可以使用xTaskCreate等动态创建函数
    * 0: 禁用 - 只能使用静态创建函数
    */
    #define configSUPPORT_DYNAMIC_ALLOCATION 1

    /**
    * 静态内存分配
    * 1: 启用 - 可以使用xTaskCreateStatic等静态创建函数
    * 0: 禁用 - 只能使用动态创建函数
    */
    #define configSUPPORT_STATIC_ALLOCATION 0

    /**
    * 堆内存大小
    * 用于动态内存分配,包括任务栈、队列等
    * 单位:字节
    * 建议:根据实际内存使用情况设置
    */
    #define configTOTAL_HEAP_SIZE ((size_t)(14 * 1024))

    /***************************************************************
    FreeRTOS钩子函数配置选项
    **************************************************************/

    /**
    * 空闲钩子函数
    * 1: 启用 - 空闲时调用用户定义的函数
    * 0: 禁用 - 不调用钩子函数
    */
    #define configUSE_IDLE_HOOK 0

    /**
    * 滴答钩子函数
    * 1: 启用 - 每次系统滴答时调用用户定义的函数
    * 0: 禁用 - 不调用钩子函数
    */
    #define configUSE_TICK_HOOK 0

    /**
    * 内存分配失败钩子函数
    * 1: 启用 - 内存分配失败时调用用户定义的函数
    * 0: 禁用 - 不调用钩子函数
    */
    #define configUSE_MALLOC_FAILED_HOOK 0

    /**
    * 栈溢出检查
    * 0: 禁用 - 不检查栈溢出
    * 1: 方法1 - 检查栈顶是否被覆盖
    * 2: 方法2 - 检查栈底是否被覆盖(更严格)
    */
    #define configCHECK_FOR_STACK_OVERFLOW 0

    /********************************************************************
    FreeRTOS运行时间和任务状态收集配置选项
    **********************************************************************/

    /**
    * 运行时间统计
    * 1: 启用 - 可以统计任务运行时间
    * 0: 禁用 - 不统计运行时间
    */
    #define configGENERATE_RUN_TIME_STATS 0

    /**
    * 可视化跟踪调试
    * 1: 启用 - 支持FreeRTOS+Trace等调试工具
    * 0: 禁用 - 不支持跟踪调试
    */
    #define configUSE_TRACE_FACILITY 1

    /**
    * 统计格式化函数
    * 1: 启用 - 提供格式化统计信息的函数
    * 0: 禁用 - 不提供格式化函数
    */
    #define configUSE_STATS_FORMATTING_FUNCTIONS 1

    /********************************************************************
    FreeRTOS协程配置选项
    *********************************************************************/

    /**
    * 协程功能
    * 1: 启用 - 可以使用协程(轻量级任务)
    * 0: 禁用 - 无法使用协程
    * 注意:启用后必须添加croutine.c文件
    */
    #define configUSE_CO_ROUTINES 0

    /**
    * 协程优先级数量
    * 协程的优先级范围:0 ~ (configMAX_CO_ROUTINE_PRIORITIES-1)
    */
    #define configMAX_CO_ROUTINE_PRIORITIES (2)

    /***********************************************************************
    FreeRTOS软件定时器配置选项
    **********************************************************************/

    /**
    * 软件定时器功能
    * 1: 启用 - 可以使用软件定时器
    * 0: 禁用 - 无法使用软件定时器
    */
    #define configUSE_TIMERS 1

    /**
    * 软件定时器任务优先级
    * 建议:设置为较高优先级,确保定时器及时处理
    */
    #define configTIMER_TASK_PRIORITY (configMAX_PRIORITIES - 1)

    /**
    * 软件定时器队列长度
    * 用于存储定时器命令的队列大小
    */
    #define configTIMER_QUEUE_LENGTH 5

    /**
    * 软件定时器任务栈大小
    * 软件定时器服务任务的栈大小
    */
    #define configTIMER_TASK_STACK_DEPTH (configMINIMAL_STACK_SIZE)

    /************************************************************
    FreeRTOS可选函数配置选项
    ************************************************************/

    /**
    * 任务调度器状态查询函数
    * 1: 启用 - 可以使用xTaskGetSchedulerState()
    * 0: 禁用 - 无法查询调度器状态
    */
    #define INCLUDE_xTaskGetSchedulerState 1

    /**
    * 任务优先级设置函数
    * 1: 启用 - 可以使用vTaskPrioritySet()
    * 0: 禁用 - 无法动态修改任务优先级
    */
    #define INCLUDE_vTaskPrioritySet 1

    /**
    * 任务优先级获取函数
    * 1: 启用 - 可以使用uxTaskPriorityGet()
    * 0: 禁用 - 无法获取任务优先级
    */
    #define INCLUDE_uxTaskPriorityGet 1

    /**
    * 任务删除函数
    * 1: 启用 - 可以使用vTaskDelete()
    * 0: 禁用 - 无法删除任务
    */
    #define INCLUDE_vTaskDelete 1

    /**
    * 任务清理资源函数
    * 1: 启用 - 可以使用vTaskCleanUpResources()
    * 0: 禁用 - 无法清理任务资源
    */
    #define INCLUDE_vTaskCleanUpResources 1

    /**
    * 任务挂起函数
    * 1: 启用 - 可以使用vTaskSuspend()
    * 0: 禁用 - 无法挂起任务
    */
    #define INCLUDE_vTaskSuspend 1

    /**
    * 任务延时直到指定时间函数
    * 1: 启用 - 可以使用vTaskDelayUntil()
    * 0: 禁用 - 无法使用绝对延时
    */
    #define INCLUDE_vTaskDelayUntil 1

    /**
    * 任务延时函数
    * 1: 启用 - 可以使用vTaskDelay()
    * 0: 禁用 - 无法使用相对延时
    */
    #define INCLUDE_vTaskDelay 1

    /**
    * 任务状态获取函数
    * 1: 启用 - 可以使用eTaskGetState()
    * 0: 禁用 - 无法获取任务状态
    */
    #define INCLUDE_eTaskGetState 1

    /**
    * 定时器挂起函数调用
    * 1: 启用 - 可以使用xTimerPendFunctionCall()
    * 0: 禁用 - 无法使用定时器挂起函数调用
    */
    #define INCLUDE_xTimerPendFunctionCall 0

    /**
    * 任务栈高水位标记函数
    * 1: 启用 - 可以使用uxTaskGetStackHighWaterMark()
    * 0: 禁用 - 无法检查栈使用情况
    */
    #define INCLUDE_uxTaskGetStackHighWaterMark 1

    /******************************************************************
    FreeRTOS中断配置选项
    ******************************************************************/

    /**
    * 中断优先级位数
    * STM32F103使用4位优先级
    */
    #ifdef __NVIC_PRIO_BITS
    #define configPRIO_BITS __NVIC_PRIO_BITS
    #else
    #define configPRIO_BITS 4
    #endif

    /**
    * 中断最低优先级
    * 数值越大优先级越低
    * 15 = 最低优先级
    */
    #define configLIBRARY_LOWEST_INTERRUPT_PRIORITY 15

    /**
    * 系统可管理的最高中断优先级
    * 数值越小优先级越高
    * 1 = 较高优先级,可以被FreeRTOS管理
    * 0 = 最高优先级,不能被FreeRTOS管理
    */
    #define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 1

    /**
    * 内核中断优先级
    * 用于FreeRTOS内核的中断优先级
    */
    #define configKERNEL_INTERRUPT_PRIORITY (configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS)) /* 240 */

    /**
    * 系统调用最高中断优先级
    * 可以被FreeRTOS管理的中断最高优先级
    */
    #define configMAX_SYSCALL_INTERRUPT_PRIORITY (configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS))

    /****************************************************************
    FreeRTOS中断服务函数配置选项
    ****************************************************************/

    /**
    * PendSV中断处理函数映射
    * 用于任务切换的中断处理函数
    */
    #define xPortPendSVHandler PendSV_Handler

    /**
    * SVC中断处理函数映射
    * 用于启动第一个任务的中断处理函数
    */
    #define vPortSVCHandler SVC_Handler

    #endif /* FREERTOS_CONFIG_H */

    FreeRTOS

    FreeRTOS高优先级优先,具有优先级反转机制,注意config里的总优先级不能低于4

    Ucos和RT-Thread是低优先级优先

    通信路径表

    运行效果

    Xmodem工具使用xcom(这东西老是丢包,下载操作还有BUG,丢包了再下载进去的是错的,以后再修改吧)

    在简易模式和多功能模式均可以调整OTA_flag;若为0,可以进行OTA更新,若为1,则自动进入系统

    本实验通过【5】向外部FLASH的第1块下载简易模式(MODE=0),第2块下载简易+多功能模式(MODE=1)

    后续借助【7】重启、PB10重启和【6】下载外部FLASH等功能,对第1块和第2块外部Flash片区内容进行实验测试,均符合预期效果。

    【1】擦除和【2】下载,测得没有问题;【3】和【4】也是测试通过。

    总结

    整体代码太冗长了,这里就只把核心部分贴上去了。

    还有,记得调整两个0x5000,不然程序是运行不了的。