沁恒蓝牙芯片CH582:蓝牙OTA升级技术详解与应用探索

2024-03-10 22:20

本文主要是介绍沁恒蓝牙芯片CH582:蓝牙OTA升级技术详解与应用探索,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

  • 一、前言
    • 1.WCH 蓝牙空中升级(BLE OTA)概述
    • 2. WCH BLE SDK DFU 工作原理(方式一)
  • 二、移植程序
    • 1.找到BackUpgrade_OTA例程
    • 2.添加文件到工程
      • 2.1 添加文件
      • 2.2 如何添加
    • 3.修改APP工程
      • 3.1 修改peripheral_main.c文件
      • 3.2 修改peripheral.c文件
    • 4.修改Link.Ld文件
  • 三、OTA升级
    • 1.合并文件
    • 2.下载bin文件
    • 3.APP升级程序
      • 3.1 OTA升级工具
      • 3.2 搜索蓝牙,连接
      • 3.3 选择升级的固件
      • 3.4 升级过程
      • 3.5 升级完成
      • 3.6 升级结果
  • 四、总结


一、前言

1.WCH 蓝牙空中升级(BLE OTA)概述

DFU(Device Firmware Update)设备固件升级,OTA(Over The Air)是实现 DFU 的一种方式,OTA 的全称应该是 OTA DFU,即通过空中无线方式实现设备固件升级。OTA 也可以称为 FOTA,即 Firmware OTA。WCH BLE 系列芯片除了可以通过无线方式(OTA)-方式一/二 DFU 进行升级,也可以通过有线方式-方式三 DFU 进行升级,比如通过内置 BOOT(UART/USB)来升级设备固件。

不管采用 OTA 方式还是有线通信方式,DFU 包括后台式(background)和非后台式两种模式。后台式 DFU-类似方式一 DFU,又称静默式 DFU(Silent DFU),即新固件下载属于应用程序功能的一部分,在新固件下载过程中,应用可以正常使用,下载完成后,系统完成执行新固件的操作,至此整个升级过程结束(比如EVT/BLE/BackupUpgrade_XXX 例子)。非后台式 DFU-方式二 DFU,在升级的时候整个升级过程中 APP 正常功能都无法使用。系统需要先从应用模式跳入到 BootLoader/IAP 模式,由 BootLoader/IAP 进行新固件下载工作,直接覆盖老固件,至升级结束
(比如EVT\EXAM\BLE\OnlyUpdateApp_XXX 例子)。

在这里插入图片描述

2. WCH BLE SDK DFU 工作原理(方式一)

方式一上电优先运行 IAP 程序,之后跳转 APP 执行用户程序。APP 文件为独立完整的功能文件,运行时可以通过无线方式接收完整的 OTA 备份升级文件,然后软复位进入 IAP 程序,IAP 会将备份区的 OTA 升级文件拷贝到 APP应用程序区,最后跳转回升级后的 APP 应用程序运行新的固件。升级固件带 LIB 编译(LIB 约 90K)。

注意:备份升级方式,适用于 flash 资源充裕的应用,优点是 APP+LIB 都可以升级,缺点是 flash 需要对半分使用。

方式一 DFU 包含 3 个文件 JumpIAP + APP + IAP(APP 是用户功能代码,也是实现产品功能和升级功能的主体,对应 BackupUpgrade_OTA 产生的 hex 文件;IAP 是编程升级 APP 的代码,对应 BackupUpgrade_IAP 产生的 hex 文件;JumpIAP 为跳转 IAP 代码,
对应BackupUpgrade_JumpIAP 产生的 hex 文件)。
在这里插入图片描述

选择对应的文件,点击合并,产生一个 BIN 文件,然后使用 ISP 工具下载即可。


二、移植程序

1.找到BackUpgrade_OTA例程

根据上面原理的介绍,如果我们要在我们的APP程序上进行OTA升级,我们需要根据BackUpgrade_OTA例程来修改我们的程序。

BackUpgrade_OTA例程在如下目录里。

  1. 在这里插入图片描述
  2. 在这里插入图片描述
  3. 在这里插入图片描述

2.添加文件到工程

2.1 添加文件

添加ota.h,OTAprogile.c和OTAprogile.h文件到自己的APP工程中
在这里插入图片描述

2.2 如何添加

在需要添加的位置右键添加,选择已存在文件。
在这里插入图片描述

3.修改APP工程

3.1 修改peripheral_main.c文件

添加头文件

#include "OTA.h"
#include "OTAprofile.h"

添加代码

/* 记录当前的Image */
unsigned char CurrImageFlag = 0xff;/* 用于APP判断文件有效性 */
const uint32_t Address = 0xFFFFFFFF;__attribute__((aligned(4))) uint32_t Image_Flag __attribute__((section(".ImageFlag"))) = (uint32_t)&Address;/* 注意:关于程序升级后flash的操作必须先执行,不开启任何中断,防止操作中断和失败 */
/********************************************************************** @fn      ReadImageFlag** @brief   读取当前的程序的Image标志,DataFlash如果为空,就默认是ImageA** @return  none*/
void ReadImageFlag(void)
{OTADataFlashInfo_t p_image_flash;EEPROM_READ(OTA_DATAFLASH_ADD, &p_image_flash, 4);CurrImageFlag = p_image_flash.ImageFlag;/* 程序第一次执行,或者没有更新过,以后更新后在擦除DataFlash */if((CurrImageFlag != IMAGE_A_FLAG) && (CurrImageFlag != IMAGE_B_FLAG)){CurrImageFlag = IMAGE_A_FLAG;}
}//在main主函数里面添加以下函数
int main(void)
{ReadImageFlag();
}

3.2 修改peripheral.c文件

添加头文件

#include "OTA.h"
#include "OTAprofile.h"

添加代码

  1. 蓝牙参数
//一些蓝牙相关参数,这里就不一一介绍了
// How often to perform periodic event   多长时间执行一次周期事件
#define SBP_PERIODIC_EVT_PERIOD              1000//1600// What is the advertising interval when device is discoverable (units of 625us, 80=50ms) 设备被发现时的广告间隔是多少(单位为625us, 80=50ms)
#define DEFAULT_ADVERTISING_INTERVAL         80// Limited discoverable mode advertises for 30.72s, and then stops  限制可发现模式的广告时间为30.72秒,然后停止
// General discoverable mode advertises indefinitely   一般可发现模式无限广告
#define DEFAULT_DISCOVERABLE_MODE            GAP_ADTYPE_FLAGS_GENERAL// Minimum connection interval (units of 1.25ms, 6=7.5ms)最小连接间隔(以1.25ms为单位,6=7.5ms)
#define DEFAULT_DESIRED_MIN_CONN_INTERVAL    12// Maximum connection interval (units of 1.25ms, 100=125ms)最大连接间隔(以1.25ms为单位,100=125ms)
#define DEFAULT_DESIRED_MAX_CONN_INTERVAL    100//100// How often to perform read rssi event  多久执行一次读取rssi事件
#define SBP_READ_RSSI_EVT_PERIOD             32//3200 Parameter update delay  参数更新延迟
//#define SBP_PARAM_UPDATE_DELAY               6400
//
 PHY update delay  PHY更新延迟
//#define SBP_PHY_UPDATE_DELAY                 2400// Slave latency to use parameter update   从延迟使用参数更新
#define DEFAULT_DESIRED_SLAVE_LATENCY        5// Supervision timeout value (units of 10ms, 100=1s)  监督超时值(单位10ms, 100=1s)
#define DEFAULT_DESIRED_CONN_TIMEOUT         1000//100// Whether to enable automatic parameter update request when a connection is formed
#define DEFAULT_ENABLE_UPDATE_REQUEST        TRUE// Company Identifier: WCH
#define WCH_COMPANY_ID                       0x07D7#define INVALID_CONNHANDLE                   0xFFFF
  1. OTA相关参数和函数
// OTA IAP VARIABLES
/* OTA通讯的帧 */
OTA_IAP_CMD_t iap_rec_data;/* OTA解析结果 */
uint32_t OpParaDataLen = 0;
uint32_t OpAdd = 0;/* flash的数据临时存储 */
__attribute__((aligned(8))) uint8_t block_buf[16];/* Image跳转函数地址定义 */
typedef int (*pImageTaskFn)(void);
pImageTaskFn user_image_tasks;/* Flash 擦除过程 */
uint32_t EraseAdd = 0;      // 擦除地址
uint32_t EraseBlockNum = 0; // 需要擦除的块数
uint32_t EraseBlockCnt = 0; // 擦除的块计数/* FLASH 校验过程 */
uint8_t VerifyStatus = 0;void OTA_IAPReadDataComplete(unsigned char index);
void OTA_IAPWriteData(unsigned char index, unsigned char *p_data, unsigned char w_len);
void Rec_OTA_IAP_DataDeal(void);
void OTA_IAP_SendCMDDealSta(uint8_t deal_status);// Simple GATT Profile Callbacks
static OTAProfileCBs_t Peripheral_OTA_IAPProfileCBs = {OTA_IAPReadDataComplete, // Charactersitic value change callbackOTA_IAPWriteData};
  1. 在void Peripheral_Init()函数中修改如下
// GAP_SetParamValue(TGAP_ADV_SCAN_REQ_NOTIFY, ENABLE);OTAProfile_AddService(GATT_ALL_SERVICES);//OTA Profile初始化OTAProfile_RegisterAppCBs(&Peripheral_OTA_IAPProfileCBs);//OTA Profile读写回调函数注册
  1. 在uint16_t Peripheral_ProcessEvent(uint8_t task_id, uint16_t events)函数中添加如下代码
   if (events & SBP_PARAM_UPDATE_EVT2){// Send connect param update request发送连接参数更新请求GAPRole_PeripheralConnParamUpdateReq(peripheralConnList.connHandle,DEFAULT_DESIRED_MIN_CONN_INTERVAL,20,0,DEFAULT_DESIRED_CONN_TIMEOUT,Peripheral_TaskID);return (events ^ SBP_PARAM_UPDATE_EVT2);}if (events & OTA_FLASH_ERASE_EVT){uint8_t status;PRINT("ERASE:%08x num:%d\r\n", (int)(EraseAdd + EraseBlockCnt * FLASH_BLOCK_SIZE), (int)EraseBlockCnt);status = FLASH_ROM_ERASE(EraseAdd + EraseBlockCnt * FLASH_BLOCK_SIZE, FLASH_BLOCK_SIZE);/* 擦除失败 */if (status != SUCCESS){OTA_IAP_SendCMDDealSta(status);return (events ^ OTA_FLASH_ERASE_EVT);}EraseBlockCnt++;/* 擦除结束 */if (EraseBlockCnt >= EraseBlockNum){PRINT("ERASE Complete\r\n");OTA_IAP_SendCMDDealSta(status);return (events ^ OTA_FLASH_ERASE_EVT);}return (events);}
  1. 在Peripheral.h文件中新增定义如下
#define OTA_FLASH_ERASE_EVT     0x0040  //OTA Flash
#define SBP_PARAM_UPDATE_EVT2   0x0080
  1. 在Peripheral.c文件中新增如下函数
/********************************************************************** @fn      OTA_IAP_SendData** @brief   OTA IAP发送数据,使用时限制20字节以内** @param   p_send_data - 发送数据的指针* @param   send_len    - 发送数据的长度** @return  none*/
void OTA_IAP_SendData(uint8_t *p_send_data, uint8_t send_len)
{OTAProfile_SendData(OTAPROFILE_CHAR, p_send_data, send_len);
}/********************************************************************** @fn      OTA_IAP_SendCMDDealSta** @brief   OTA IAP执行的状态返回** @param   deal_status - 返回的状态** @return  none*/
void OTA_IAP_SendCMDDealSta(uint8_t deal_status)
{uint8_t send_buf[2];send_buf[0] = deal_status;send_buf[1] = 0;OTA_IAP_SendData(send_buf, 2);
}/********************************************************************** @fn      OTA_IAP_CMDErrDeal** @brief   OTA IAP异常命令码处理** @return  none*/
void OTA_IAP_CMDErrDeal(void)
{OTA_IAP_SendCMDDealSta(0xfe);
}/********************************************************************** @fn      SwitchImageFlag** @brief   切换dataflash里的ImageFlag** @param   new_flag    - 切换的ImageFlag** @return  none*/
void SwitchImageFlag(uint8_t new_flag)
{uint16_t i;uint32_t ver_flag;/* 读取第一块 */EEPROM_READ(OTA_DATAFLASH_ADD, (uint32_t *)&block_buf[0], 4);/* 擦除第一块 */EEPROM_ERASE(OTA_DATAFLASH_ADD, EEPROM_PAGE_SIZE);/* 更新Image信息 */block_buf[0] = new_flag;/* 编程DataFlash */EEPROM_WRITE(OTA_DATAFLASH_ADD, (uint32_t *)&block_buf[0], 4);
}/********************************************************************** @fn      DisableAllIRQ** @brief   关闭所有的中断** @return  none*/
void DisableAllIRQ(void)
{SYS_DisableAllIrq(NULL);
}/********************************************************************** @fn      Rec_OTA_IAP_DataDeal** @brief   接收到OTA数据包处理** @return  none*/
void Rec_OTA_IAP_DataDeal(void)
{switch (iap_rec_data.other.buf[0]){/* 编程 */case CMD_IAP_PROM:{uint32_t i;uint8_t status;OpParaDataLen = iap_rec_data.program.len;OpAdd = (uint32_t)(iap_rec_data.program.addr[0]);OpAdd |= ((uint32_t)(iap_rec_data.program.addr[1]) << 8);OpAdd = OpAdd * 16;OpAdd += IMAGE_A_SIZE;PRINT("IAP_PROM: %08x len:%d \r\n", (int)OpAdd, (int)OpParaDataLen);/* 当前是ImageA,直接编程 */status = FLASH_ROM_WRITE(OpAdd, iap_rec_data.program.buf, (uint16_t)OpParaDataLen);if (status)PRINT("IAP_PROM err \r\n");OTA_IAP_SendCMDDealSta(status);break;}/* 擦除 -- 蓝牙擦除由主机控制 */case CMD_IAP_ERASE:{OpAdd = (uint32_t)(iap_rec_data.erase.addr[0]);OpAdd |= ((uint32_t)(iap_rec_data.erase.addr[1]) << 8);OpAdd = OpAdd * 16;OpAdd += IMAGE_A_SIZE;EraseBlockNum = (uint32_t)(iap_rec_data.erase.block_num[0]);EraseBlockNum |= ((uint32_t)(iap_rec_data.erase.block_num[1]) << 8);EraseAdd = OpAdd;EraseBlockCnt = 0;/* 检验就放在擦除里清0 */VerifyStatus = 0;PRINT("IAP_ERASE start:%08x num:%d\r\n", (int)OpAdd, (int)EraseBlockNum);if (EraseAdd < IMAGE_B_START_ADD || (EraseAdd + (EraseBlockNum - 1) * FLASH_BLOCK_SIZE) > IMAGE_IAP_START_ADD){OTA_IAP_SendCMDDealSta(0xFF);}else{/* 启动擦除 */tmos_set_event(Peripheral_TaskID, OTA_FLASH_ERASE_EVT);}break;}/* 校验 */case CMD_IAP_VERIFY:{uint32_t i;uint8_t status = 0;OpParaDataLen = iap_rec_data.verify.len;OpAdd = (uint32_t)(iap_rec_data.verify.addr[0]);OpAdd |= ((uint32_t)(iap_rec_data.verify.addr[1]) << 8);OpAdd = OpAdd * 16;OpAdd += IMAGE_A_SIZE;PRINT("IAP_VERIFY: %08x len:%d \r\n", (int)OpAdd, (int)OpParaDataLen);/* 当前是ImageA,直接读取ImageB校验 */status = FLASH_ROM_VERIFY(OpAdd, iap_rec_data.verify.buf, OpParaDataLen);if (status){PRINT("IAP_VERIFY err \r\n");}VerifyStatus |= status;OTA_IAP_SendCMDDealSta(VerifyStatus);break;}/* 编程结束 */case CMD_IAP_END:{PRINT("IAP_END \r\n");/* 当前的是ImageA *//* 关闭当前所有使用中断,或者方便一点直接全部关闭 */DisableAllIRQ();/* 修改DataFlash,切换至ImageIAP */SwitchImageFlag(IMAGE_IAP_FLAG);/* 等待打印完成 ,复位*/mDelaymS(10);SYS_ResetExecute();break;}case CMD_IAP_INFO:{uint8_t send_buf[20];PRINT("IAP_INFO \r\n");/* IMAGE FLAG */send_buf[0] = IMAGE_B_FLAG;/* IMAGE_SIZE */send_buf[1] = (uint8_t)(IMAGE_SIZE & 0xff);send_buf[2] = (uint8_t)((IMAGE_SIZE >> 8) & 0xff);send_buf[3] = (uint8_t)((IMAGE_SIZE >> 16) & 0xff);send_buf[4] = (uint8_t)((IMAGE_SIZE >> 24) & 0xff);/* BLOCK SIZE */send_buf[5] = (uint8_t)(FLASH_BLOCK_SIZE & 0xff);send_buf[6] = (uint8_t)((FLASH_BLOCK_SIZE >> 8) & 0xff);send_buf[7] = CHIP_ID & 0xFF;send_buf[8] = (CHIP_ID << 8) & 0xFF;/* 有需要再增加 *//* 发送信息 */OTA_IAP_SendData(send_buf, 20);break;}default:{OTA_IAP_CMDErrDeal();break;}}
}/********************************************************************** @fn      OTA_IAPReadDataComplete** @brief   OTA 数据读取完成处理** @param   index   - OTA 通道序号** @return  none*/
void OTA_IAPReadDataComplete(unsigned char index)
{PRINT("OTA Send Comp \r\n");
}/********************************************************************** @fn      OTA_IAPWriteData** @brief   OTA 通道数据接收完成处理** @param   index   - OTA 通道序号* @param   p_data  - 写入的数据* @param   w_len   - 写入的长度** @return  none*/
void OTA_IAPWriteData(unsigned char index, unsigned char *p_data, unsigned char w_len)
{unsigned char rec_len;unsigned char *rec_data;rec_len = w_len;rec_data = p_data;tmos_memcpy((unsigned char *)&iap_rec_data, rec_data, rec_len);Rec_OTA_IAP_DataDeal();
}

4.修改Link.Ld文件

在这里插入图片描述

//原本
MEMORY
{FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 448KRAM (xrw) : ORIGIN = 0x20000000, LENGTH = 32K
}
//修改后
MEMORY
{FLASH (rx) : ORIGIN = 0x00001000, LENGTH = 216KRAM (xrw) : ORIGIN = 0x20000000, LENGTH = 32K
}

三、OTA升级

1.合并文件

将BackupUpgrade_IAP 产生的 hex 文件和BackupUpgrade_JumpIAP 产生的 hex 文件还有刚才自己编写的APP程序的hex 文件进行合并为bin文件。
软件可以去沁恒官网下载:沁恒微电子

在这里插入图片描述

2.下载bin文件

在这里插入图片描述

3.APP升级程序

3.1 OTA升级工具

具体可以在官网下载:沁恒微电子
在这里插入图片描述

3.2 搜索蓝牙,连接

在这里插入图片描述

3.3 选择升级的固件

就是刚才APP程序产生的HEX文件

在这里插入图片描述
在这里插入图片描述

3.4 升级过程

在这里插入图片描述

3.5 升级完成

在这里插入图片描述

3.6 升级结果

RGB灯珠由颜色切换,变成了固定一个颜色点亮。

在这里插入图片描述


四、总结

今天主要讲了CH582蓝牙OTA的操作,感兴趣的可以去试试。

感谢你的观看!

在这里插入图片描述

这篇关于沁恒蓝牙芯片CH582:蓝牙OTA升级技术详解与应用探索的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/795699

相关文章

Spring Security基于数据库验证流程详解

Spring Security 校验流程图 相关解释说明(认真看哦) AbstractAuthenticationProcessingFilter 抽象类 /*** 调用 #requiresAuthentication(HttpServletRequest, HttpServletResponse) 决定是否需要进行验证操作。* 如果需要验证,则会调用 #attemptAuthentica

中文分词jieba库的使用与实景应用(一)

知识星球:https://articles.zsxq.com/id_fxvgc803qmr2.html 目录 一.定义: 精确模式(默认模式): 全模式: 搜索引擎模式: paddle 模式(基于深度学习的分词模式): 二 自定义词典 三.文本解析   调整词出现的频率 四. 关键词提取 A. 基于TF-IDF算法的关键词提取 B. 基于TextRank算法的关键词提取

水位雨量在线监测系统概述及应用介绍

在当今社会,随着科技的飞速发展,各种智能监测系统已成为保障公共安全、促进资源管理和环境保护的重要工具。其中,水位雨量在线监测系统作为自然灾害预警、水资源管理及水利工程运行的关键技术,其重要性不言而喻。 一、水位雨量在线监测系统的基本原理 水位雨量在线监测系统主要由数据采集单元、数据传输网络、数据处理中心及用户终端四大部分构成,形成了一个完整的闭环系统。 数据采集单元:这是系统的“眼睛”,

深入探索协同过滤:从原理到推荐模块案例

文章目录 前言一、协同过滤1. 基于用户的协同过滤(UserCF)2. 基于物品的协同过滤(ItemCF)3. 相似度计算方法 二、相似度计算方法1. 欧氏距离2. 皮尔逊相关系数3. 杰卡德相似系数4. 余弦相似度 三、推荐模块案例1.基于文章的协同过滤推荐功能2.基于用户的协同过滤推荐功能 前言     在信息过载的时代,推荐系统成为连接用户与内容的桥梁。本文聚焦于

csu 1446 Problem J Modified LCS (扩展欧几里得算法的简单应用)

这是一道扩展欧几里得算法的简单应用题,这题是在湖南多校训练赛中队友ac的一道题,在比赛之后请教了队友,然后自己把它a掉 这也是自己独自做扩展欧几里得算法的题目 题意:把题意转变下就变成了:求d1*x - d2*y = f2 - f1的解,很明显用exgcd来解 下面介绍一下exgcd的一些知识点:求ax + by = c的解 一、首先求ax + by = gcd(a,b)的解 这个

hdu1394(线段树点更新的应用)

题意:求一个序列经过一定的操作得到的序列的最小逆序数 这题会用到逆序数的一个性质,在0到n-1这些数字组成的乱序排列,将第一个数字A移到最后一位,得到的逆序数为res-a+(n-a-1) 知道上面的知识点后,可以用暴力来解 代码如下: #include<iostream>#include<algorithm>#include<cstring>#include<stack>#in

OpenHarmony鸿蒙开发( Beta5.0)无感配网详解

1、简介 无感配网是指在设备联网过程中无需输入热点相关账号信息,即可快速实现设备配网,是一种兼顾高效性、可靠性和安全性的配网方式。 2、配网原理 2.1 通信原理 手机和智能设备之间的信息传递,利用特有的NAN协议实现。利用手机和智能设备之间的WiFi 感知订阅、发布能力,实现了数字管家应用和设备之间的发现。在完成设备间的认证和响应后,即可发送相关配网数据。同时还支持与常规Sof

【专题】2024飞行汽车技术全景报告合集PDF分享(附原数据表)

原文链接: https://tecdat.cn/?p=37628 6月16日,小鹏汇天旅航者X2在北京大兴国际机场临空经济区完成首飞,这也是小鹏汇天的产品在京津冀地区进行的首次飞行。小鹏汇天方面还表示,公司准备量产,并计划今年四季度开启预售小鹏汇天分体式飞行汽车,探索分体式飞行汽车城际通勤。阅读原文,获取专题报告合集全文,解锁文末271份飞行汽车相关行业研究报告。 据悉,业内人士对飞行汽车行业

zoj3820(树的直径的应用)

题意:在一颗树上找两个点,使得所有点到选择与其更近的一个点的距离的最大值最小。 思路:如果是选择一个点的话,那么点就是直径的中点。现在考虑两个点的情况,先求树的直径,再把直径最中间的边去掉,再求剩下的两个子树中直径的中点。 代码如下: #include <stdio.h>#include <string.h>#include <algorithm>#include <map>#

【区块链 + 人才服务】可信教育区块链治理系统 | FISCO BCOS应用案例

伴随着区块链技术的不断完善,其在教育信息化中的应用也在持续发展。利用区块链数据共识、不可篡改的特性, 将与教育相关的数据要素在区块链上进行存证确权,在确保数据可信的前提下,促进教育的公平、透明、开放,为教育教学质量提升赋能,实现教育数据的安全共享、高等教育体系的智慧治理。 可信教育区块链治理系统的顶层治理架构由教育部、高校、企业、学生等多方角色共同参与建设、维护,支撑教育资源共享、教学质量评估、