Commit 87be42b7 authored by 时昊's avatar 时昊

Merge branch 'shihao_esp32' of...

Merge branch 'shihao_esp32' of http://tyw-server.synology.me:12345/rt200t/rt200t_esp32 into shihao_esp32
parent 2429b9a8
FROM espressif/idf
ARG DEBIAN_FRONTEND=nointeractive
ARG CONTAINER_USER=esp
ARG USER_UID=1000
ARG USER_GID=$USER_UID
RUN apt-get update \
&& apt install -y -q \
cmake \
git \
libglib2.0-0 \
libnuma1 \
libpixman-1-0 \
&& rm -rf /var/lib/apt/lists/*
# QEMU
ENV QEMU_REL=esp_develop_8.2.0_20240122
ENV QEMU_SHA256=e7c72ef5705ad1444d391711088c8717fc89f42e9bf6d1487f9c2a326b8cfa83
ENV QEMU_DIST=qemu-xtensa-softmmu-${QEMU_REL}-x86_64-linux-gnu.tar.xz
ENV QEMU_URL=https://github.com/espressif/qemu/releases/download/esp-develop-8.2.0-20240122/${QEMU_DIST}
ENV LC_ALL=C.UTF-8
ENV LANG=C.UTF-8
RUN wget --no-verbose ${QEMU_URL} \
&& echo "${QEMU_SHA256} *${QEMU_DIST}" | sha256sum --check --strict - \
&& tar -xf $QEMU_DIST -C /opt \
&& rm ${QEMU_DIST}
ENV PATH=/opt/qemu/bin:${PATH}
RUN groupadd --gid $USER_GID $CONTAINER_USER \
&& adduser --uid $USER_UID --gid $USER_GID --disabled-password --gecos "" ${CONTAINER_USER} \
&& usermod -a -G root $CONTAINER_USER && usermod -a -G dialout $CONTAINER_USER
RUN chmod -R 775 /opt/esp/python_env/
USER ${CONTAINER_USER}
ENV USER=${CONTAINER_USER}
WORKDIR /home/${CONTAINER_USER}
RUN echo "source /opt/esp/idf/export.sh > /dev/null 2>&1" >> ~/.bashrc
ENTRYPOINT [ "/opt/esp/entrypoint.sh" ]
CMD ["/bin/bash", "-c"]
\ No newline at end of file
// For format details, see https://aka.ms/devcontainer.json. For config options, see the README at:
// https://github.com/microsoft/vscode-dev-containers/tree/v0.183.0/containers/ubuntu
{
"name": "ESP-IDF QEMU",
"build": {
"dockerfile": "Dockerfile"
},
// Add the IDs of extensions you want installed when the container is created
"workspaceMount": "source=${localWorkspaceFolder},target=${localWorkspaceFolder},type=bind",
/* the path of workspace folder to be opened after container is running
*/
"workspaceFolder": "${localWorkspaceFolder}",
"mounts": [
"source=extensionCache,target=/root/.vscode-server/extensions,type=volume"
],
"customizations": {
"vscode": {
"settings": {
"terminal.integrated.defaultProfile.linux": "bash",
"idf.espIdfPath": "/opt/esp/idf",
"idf.customExtraPaths": "",
"idf.pythonBinPath": "/opt/esp/python_env/idf5.3_py3.10_env/bin/python",
"idf.toolsPath": "/opt/esp",
"idf.gitPath": "/usr/bin/git"
},
"extensions": [
"espressif.esp-idf-extension"
],
},
"codespaces": {
"settings": {
"terminal.integrated.defaultProfile.linux": "bash",
"idf.espIdfPath": "/opt/esp/idf",
"idf.customExtraPaths": "",
"idf.pythonBinPath": "/opt/esp/python_env/idf5.3_py3.10_env/bin/python",
"idf.toolsPath": "/opt/esp",
"idf.gitPath": "/usr/bin/git"
},
"extensions": [
"espressif.esp-idf-extension"
],
}
},
"runArgs": ["--privileged"]
}
\ No newline at end of file
......@@ -4,7 +4,7 @@ cmake_minimum_required(VERSION 3.16)
# (Not part of the boilerplate)
# This example uses an extra component for common functions such as Wi-Fi and Ethernet connection.
set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common)
set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common "./source/wifi" )
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(RT200T-2)
......@@ -5,3 +5,4 @@ otadata, data, ota, , 0x2000,
phy_init, data, phy, , 0x1000,
ota_0, app, ota_0, , 0x800K,
ota_1, app, ota_1, , 0x800K,
assert, data, spiffs, , 300K,
\ No newline at end of file
# Embed the server root certificate into the final binary
# Embed the server root certificate into the final binary "simple_ota_example.c"
idf_build_get_property(project_dir PROJECT_DIR)
idf_component_register(SRCS "app_BT_User.c" "bt_app_main.c" "bt_app_hf.c" "bt_app_core.c" "gatts_table_creat_demo.c"
"simple_ota_example.c"
idf_component_register(SRCS "mcudata.c" "app_BT_User.c" "bt_app_main.c" "bt_app_hf.c" "bt_app_core.c" "gatts_table_creat_demo.c"
"Protocol_CRC16.c"
"Protocol_Lib.c"
"Protocol_User.c"
"MCU_Core_Protocol.c"
"app_Ble_User.c"
"main_user.c"
"../source/wifi"
"gattc_demo.c"
INCLUDE_DIRS "."
EMBED_TXTFILES ${project_dir}/server_certs/ca_cert.pem)
......@@ -21,6 +21,8 @@ static ProtocolSetData ProtocolSetData_Cbk;
static Protocol_uint8_t *mDataBufPtr = Protocol_NULL;
static Protocol_uint16_t mDataBufLen = 0;
static Protocol_uint32_t DataBufMaxLen = 0;
BAT32A239_ACK_Structure BAT32A239_ACK;
//#define DEBUG_PRO_DATA 0
/**
* @brief 初始化函数
......@@ -52,7 +54,8 @@ void Protocol_Init(Protocol_uint8_t *pMemSpace, Protocol_uint32_t MemLen, Protoc
return;
}
extern Protocol_uint32_t UpdateBAT32A239Protocol_Parse(const Protocol_uint8_t *pData, Protocol_uint32_t len);
extern uint32_t SwitchMode;
/**
* @brief 串口协议服务函数,包括读取数据,解析数据,如在外部读取数据,可不调用此函数
*
......@@ -72,7 +75,15 @@ void Protocol_Service(void)
{
mDataBufLen += readNum;
// 解析协议
if(SwitchMode==0)//处理升级协议
{
len = Protocol_Parse(mDataBufPtr, mDataBufLen);
}
else//处理应用协议
{
len = UpdateBAT32A239Protocol_Parse(mDataBufPtr, mDataBufLen);
}
if ( (len > 0) && (len < mDataBufLen) )
{
// 将未解析的数据移到头部
......@@ -224,13 +235,13 @@ Protocol_uint32_t Protocol_Parse(const Protocol_uint8_t *pData, Protocol_uint32_
*
* @since 1.0.0
*/
Protocol_uint32_t Protocol_Send(const Protocol_uint16_t cmdID, const Protocol_uint8_t *pData, Protocol_uint8_t len)
{
int i = 0;
Protocol_uint16_t checksum = 0;
Protocol_uint8_t dataBuf [ 256 ];
Protocol_uint32_t frameLen;
if ( len + DATA_PACKAGE_MIN_LEN > 256 )
{
// printf("sendProtocol data is too len !!!\n");
......@@ -241,7 +252,7 @@ Protocol_uint32_t Protocol_Send(const Protocol_uint16_t cmdID, const Protocol_ui
dataBuf [ 1 ] = CMD_HEAD2; // 同步帧头 Sync frame header
dataBuf [ 2 ] = len + 4;
dataBuf [ 3 ] = len; // 命令字节 Command byte
dataBuf [ 3 ] = 0; // 命令字节 Command byte
dataBuf [ 4 ] = ( Protocol_uint8_t )cmdID;
......@@ -254,7 +265,6 @@ Protocol_uint32_t Protocol_Send(const Protocol_uint16_t cmdID, const Protocol_ui
frameLen++;
}
// 校验码 Checksum
checksum = getCheckSum(dataBuf + 2, frameLen - 2);
dataBuf [ frameLen ] = (checksum >> 8) & 0x00FF;
......@@ -262,7 +272,79 @@ Protocol_uint32_t Protocol_Send(const Protocol_uint16_t cmdID, const Protocol_ui
dataBuf [ frameLen ] = checksum & 0x00FF;
frameLen++;
if ( UARTSend_Cbk != Protocol_NULL )
{
return UARTSend_Cbk(dataBuf, frameLen);
}
else
{
return 0;
}
}
Protocol_uint32_t CalcCrc32(Protocol_uint8_t buf[], int Len);
/**
* 根据协议格式进行拼接
*/
/**
* @brief 串口协议数据拼接,如初始化发送函数,调用此函数后,数据已通过串口发送
* @param[in] cmdID 命令字
* @param[in] pData 协议数据内容(不包括协议头、长度、帧序号、命令字、校验和,从数据域算起)
* @param[in] len 数据域长度
*
* @return 已发送的数据长度
*
* @since 1.0.0
*/
Protocol_uint32_t UpdateBAT32A239Protocol_Send(UpdateProtocolStructure SendPd)
{
int i = 0;
Protocol_uint16_t checksum = 0;
Protocol_uint8_t dataBuf [ 256 ];
Protocol_uint16_t checksumXor = 0;
Protocol_uint32_t frameLen = 0;
Protocol_uint32_t DAT_CRC;
if ( SendPd.LEN > 256 )
{
// printf("sendProtocol data is too len !!!\n");
return 0;
}
frameLen = SendPd.LEN + 7;
dataBuf [ 0 ] = 0xAA;
dataBuf [ 1 ] = 0x55; // 同步帧头 Sync frame header
dataBuf [ 2 ] = SendPd.CMDH; //CMDH
dataBuf [ 3 ] = SendPd.CMDL; // CMDL
dataBuf [ 4 ] = frameLen;
dataBuf [ 5 ] = frameLen >> 8; // 命令字节 Command byte
if(SendPd.CMDH == CMD_FLASH_DWNLD)
{
if(SendPd.LEN > 4)
{
memcpy(&dataBuf[6],&SendPd.DAT[0],SendPd.LEN - 4);
DAT_CRC=CalcCrc32(&SendPd.DAT[0], SendPd.LEN - 4 );//计算Address + Data的CRC 32
dataBuf[frameLen-5]=(Protocol_uint8_t)(DAT_CRC);
dataBuf[frameLen-4]=(Protocol_uint8_t)(DAT_CRC>>8);
dataBuf[frameLen-3]=(Protocol_uint8_t)(DAT_CRC>>16);
dataBuf[frameLen-2]=(Protocol_uint8_t)(DAT_CRC>>24);
}
}
if(SendPd.CMDH == CMD_FLASH_ERASE)
{
memcpy(&dataBuf[6],&SendPd.DAT[0],SendPd.LEN);
}
for(i = 0 ;i < (frameLen - 1); i++)
{
checksumXor^=dataBuf[i];
}
dataBuf[frameLen - 1]=(Protocol_uint8_t)checksumXor;
//printf("dataBuf[frameLen - 1] = %2x\n", dataBuf[frameLen - 1]);
//printf("frameLen = %d\n", frameLen);
if ( UARTSend_Cbk != Protocol_NULL )
{
return UARTSend_Cbk(dataBuf, frameLen);
......
......@@ -39,6 +39,61 @@ typedef struct
Protocol_uint8_t Data [ 256 ]; /**< 有效数据内容 DATA0-DATAN*/
} Protocol_Data_t;
// #define UPGRADE_BAT32A239
// #ifdef UPGRADE_BAT32A239
#define CMD_FLASH_ERASE 0x30//擦除 FLASH
#define CMD_FLASH_DWNLD 0x31//下载用户程序到 FLASH
#define CMD_DATA_CRC_CHECK 0x32//CRC 校验下载用户程
#define CMD_SYS_RESET 0x50//系统复位
typedef struct
{
Protocol_uint8_t CMDH; //宏定义所包含的
Protocol_uint8_t CMDL;
Protocol_uint16_t LEN; //不关心发送的端格式
Protocol_uint8_t DAT[160];//补充的数据直接补充好再传到下层
}UpdateProtocolStructure;//上层协议数据结构
typedef struct
{
Protocol_uint8_t CMDH ;
Protocol_uint8_t CMDL ;
Protocol_uint8_t LEN[2];
union
{
Protocol_uint8_t DAT[128];
struct
{
Protocol_uint8_t CR1 :8;
Protocol_uint8_t CR2 :8;
}Erase;
struct
{
Protocol_uint8_t CR1 :8;
Protocol_uint8_t CR2 :8;
}download;
struct
{
Protocol_uint8_t CR1 :8;
Protocol_uint8_t CR2 :8;
}verification;
struct
{
Protocol_uint8_t CR1 :8;
Protocol_uint8_t CR2 :8;
}reset;
struct
{
Protocol_uint8_t CR1 :8;
Protocol_uint8_t CR2 :8;
}appgo;
}dat;
}BAT32A239_ACK_Structure;//下层应答协议
extern BAT32A239_ACK_Structure BAT32A239_ACK;
typedef Protocol_uint8_t (*UARTOpen)(void);
typedef Protocol_uint32_t (*UARTSend)(const Protocol_uint8_t *pData, Protocol_uint32_t u32Len);
typedef Protocol_uint32_t (*UARTRead)(Protocol_uint8_t *pData, Protocol_uint32_t u32Len);
......@@ -63,5 +118,6 @@ void Protocol_Init(Protocol_uint8_t *pMemSpace, Protocol_uint32_t M
void Protocol_Service(void);
Protocol_uint32_t Protocol_Parse(const Protocol_uint8_t *pData, Protocol_uint32_t len);
Protocol_uint32_t Protocol_Send(const Protocol_uint16_t cmdID, const Protocol_uint8_t *pData, Protocol_uint8_t len);
Protocol_uint32_t UpdateBAT32A239Protocol_Send(UpdateProtocolStructure SendPd);
#endif
#include <stdint.h>
#include "Protocol_User.h"
#include "Protocol_Lib.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
......@@ -32,6 +33,7 @@
#include <string.h>
#include <stdbool.h>
#include <stdio.h>
#include "http_server.h"
......@@ -209,6 +211,8 @@ static Protocol_uint32_t Protocol_UartSend(const Protocol_uint8_t *pData, Protoc
return 0;
}
extern void wifiServiceStart(void);
uint32_t SwitchMode=0;
static void Protocol_UartHandle(const Protocol_Data_t *pData)//esp接收底板数据
{
if ( pData->CmdID == 0x20 )//收到底板发送的数据后,才会发送0x12,0x01,0x02的id
......@@ -268,7 +272,9 @@ static void Protocol_UartHandle(const Protocol_Data_t *pData)//esp接收底板
if(Wifi_OTA_Request == 0)
{
Wifi_OTA_Request = 1;
printf("get ota req! \r\n");
printf("收到进入OTA指令 \r\n");
SwitchMode=1;
wifiServiceStart();
}
// }
}
......@@ -398,3 +404,415 @@ void Prot_Send_Msg_Process(void )
}
}
}
//BAT32A239
UpdateProtocolStructure Update_Frame;
//extern const unsigned char _acBAT32A239dat[88016];
Protocol_uint32_t UpgradeStep =0xFF;//初始状态
uint32_t Step_delayTime =0;
uint32_t Flash_Size =0;
uint32_t temp_Size =0;
uint32_t Write_Counter=0;
uint32_t StartAddr = 0;
uint32_t BackupStartAddr = 0;
uint32_t DataTotalLen = 0;
uint32_t BackupDataTotalLen = 0;
void SetUpgradeStart(void)
{
// uint32_t fills;
// G031toBoot();
// vTaskDelay(pdMS_TO_TICKS(100));
// G031tReset();
// vTaskDelay(pdMS_TO_TICKS(200));
// TaskSchOnUpdateNAT32G031();//关闭任务
// fills=temp_Size%16;
// if (fills!=0)
// {
// memset(&_acBAT32A239dat[temp_Size],0xFF,16-fills);
// Flash_Size+=(16-fills);//下载数据需要对齐16字节
// }
UpgradeStep=4;
}
void SetUpgradeFlashSize(uint32_t size,uint32_t len)
{
DataTotalLen = size - 16;
BackupDataTotalLen = DataTotalLen;
temp_Size=0;
StartAddr = len;
BackupStartAddr = StartAddr;
Write_Counter = 0;
}
void Cache_data(unsigned char* p,uint32_t len)
{
// memcpy(&_acBAT32A239dat[temp_Size],p,len);
temp_Size+=len;
}
void SendCmd_EraseBAT32A239_Chip(void)
{
Update_Frame.CMDH = CMD_FLASH_ERASE;
Update_Frame.CMDL = 0x00;
Update_Frame.LEN = 0x08;
Update_Frame.DAT[0] = StartAddr >> 24;
Update_Frame.DAT[1] = StartAddr >> 16;
Update_Frame.DAT[2] = StartAddr >> 8;
Update_Frame.DAT[3] = StartAddr;
Update_Frame.DAT[4] = BackupDataTotalLen >> 24;
Update_Frame.DAT[5] = BackupDataTotalLen >> 16;
Update_Frame.DAT[6] = BackupDataTotalLen >> 8;
Update_Frame.DAT[7] = BackupDataTotalLen;
UpdateBAT32A239Protocol_Send(Update_Frame);
}
uint32_t Write_Size=0;
uint32_t SendCmd_WriteBAT32A239_Flash(void)
{
//uint32_t Offset=0;
if (Flash_Size>Write_Counter)
{
Update_Frame.CMDH = CMD_FLASH_DWNLD;
Update_Frame.CMDL = 0x00;
Update_Frame.LEN = 0;
if ((Flash_Size-Write_Counter)>=128)
{
Update_Frame.LEN= 128+8;//0x94;
Write_Size=128;
}
else
{
Update_Frame.LEN = (Flash_Size - Write_Counter) + 8;//剩余数量
Write_Size = Flash_Size - Write_Counter;
}
memcpy(&Update_Frame.DAT[4],&buf[Write_Counter],Write_Size); //拷贝需要写入的数据到发送结构
//Write_Counter += StartAddr;//转换为下载 FLASH 的实际起始地址
Update_Frame.DAT[0] = (Protocol_uint8_t)(StartAddr >> 24);
Update_Frame.DAT[1] = (Protocol_uint8_t)(StartAddr >> 16);
Update_Frame.DAT[2] = (Protocol_uint8_t)(StartAddr >> 8);
Update_Frame.DAT[3] = (Protocol_uint8_t)(StartAddr >> 0);
UpdateBAT32A239Protocol_Send(Update_Frame);//发送
}
return Write_Counter;
}
/*
下载成功后,长度的变化;
//写入指针增加
*/
void SendCmd_CrcCheckBAT32A239_Flash(void)
{
uint32_t crc=0;
uint32_t start=0x08000000;
uint32_t lenght=Flash_Size;
//crc=CalcCrc32(&_acBAT32A239dat[0],lenght);//减掉CRC和前16字节DAT
Update_Frame.CMDH = CMD_DATA_CRC_CHECK;
Update_Frame.CMDL = 0x00;
Update_Frame.LEN = 0x00;
UpdateBAT32A239Protocol_Send(Update_Frame);
}
void SendCmd_ResetComond(void)
{
Update_Frame.CMDH = CMD_SYS_RESET;
Update_Frame.CMDL = 0x00;
Update_Frame.LEN = 0x00;
UpdateBAT32A239Protocol_Send(Update_Frame);
}
static uint32_t UpgradeBAT32A239_1ms_Cnt;
void Upgrade_BAT32A239_Task(void *arg)
{
while(1)
{
Protocol_Service();
if (UpgradeBAT32A239_1ms_Cnt < 1000)
{
UpgradeBAT32A239_1ms_Cnt++;
}
else
{
UpgradeBAT32A239_1ms_Cnt = 0;
}
if((UpgradeBAT32A239_1ms_Cnt + 2) % 10 == 0)
{
BAT32A239_MCU_Update();
}
Protocol_Send_Service();
vTaskDelay(pdMS_TO_TICKS(1));
}
}
void BAT32A239_MCU_Update(void)
{
double percent = 0.0;
const char *partition_label = "assert";
const esp_partition_t *assert_update_partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, partition_label);
switch (UpgradeStep)
{
case 0 :
SendCmd_EraseBAT32A239_Chip();//发送擦除指令
UpgradeStep=1;
Step_delayTime=0;
ESP_LOGI("MSI","UpgradeStep : %d Erase Chip \n",UpgradeStep);
break;
case 1 :
//ESP_LOGI("MSI","Flash_Size : %ld \n",Flash_Size);
Write_Counter = 0;
if (BAT32A239_ACK.CMDH == CMD_FLASH_ERASE)
{
if (BAT32A239_ACK.dat.Erase.CR1 == 0)//没判断长度,只判断了擦除状态
{
UpgradeStep = 2;
ESP_LOGI("MSI","UpgradeStep : %d Erase Chip finshed\n",UpgradeStep);
ESP_LOGI("MSI","downloading... \n");
SendCmd_WriteBAT32A239_Flash();//下载shou'zhen
}
else
{
UpgradeStep = 0;
ESP_LOGI("MSI","UpgradeStep : %d Erase Chip finshed\n",UpgradeStep);
ESP_LOGI("MSI","Erasing failed, request erasing again\n");
}
}
else
{
Step_delayTime++;
if (Step_delayTime>=5000)
{
ESP_LOGI("MSI","UpgradeStep : %d Erase Chip timeout\n",UpgradeStep);
Step_delayTime = 0;
UpgradeStep = 5; //超时停止
}
}
if(BAT32A239_ACK.CMDH==CMD_FLASH_DWNLD)
{
SendCmd_WriteBAT32A239_Flash();//下载shou'zhen
UpgradeStep = 2;
}
break;
case 2:
//ESP_LOGI("MSI","BAT32A239_ACK.CMDH : %d\n",BAT32A239_ACK.CMDH);
if (BAT32A239_ACK.CMDH==CMD_FLASH_DWNLD)
{
//ESP_LOGI("MSI","xxxxxxx");
if (BAT32A239_ACK.dat.download.CR1==0x01)
{
ESP_LOGI("MSI","Download failed, request to re-download the package");
SendCmd_WriteBAT32A239_Flash();//下载进度
}
if (BAT32A239_ACK.dat.download.CR1==0x00)
{
BAT32A239_ACK.dat.download.CR1=0xFF;
Write_Counter += Write_Size;
StartAddr += Write_Size;
//ESP_LOGI("MSI","Flash_Size : %ld verification OK !\n",Flash_Size);
//ESP_LOGI("MSI","Write_Counter : %ld verification OK !\n",Write_Counter);
if (Write_Counter == Flash_Size)//下载完成
{
UpgradeStep = 4;
Write_Counter = 0;
Write_Size = 0;
// ESP_LOGI("MSI", " %.2f%%", 100.00);
ESP_LOGI("MSI","\n UpgradeStep : %d download finished \n",UpgradeStep);
}
else
{
// percent = 100.0 - (double)(Write_Counter * 100) / (double)Flash_Size;
// ESP_LOGI("MSI", " %.2f%%", percent);
SendCmd_WriteBAT32A239_Flash();//下载进度
}
}
}
break;
case 3:
if (BAT32A239_ACK.CMDH==CMD_DATA_CRC_CHECK)
{
if (BAT32A239_ACK.dat.verification.CR1==0x01)
{
ESP_LOGI("MSI","Err : %2x \n",BAT32A239_ACK.dat.download.CR2);
Step_delayTime = 0;
}
if (BAT32A239_ACK.dat.verification.CR1==0x00)
{
UpgradeStep=5;
ESP_LOGI("MSI","UpgradeStep : %d verification OK !\n",UpgradeStep);
}
}
else
{
if((Step_delayTime % 20) == 0)
{
SendCmd_CrcCheckBAT32A239_Flash();//校验flash
}
Step_delayTime++;
}
//UpgradeStep=9;
break;
case 4:
if(BackupDataTotalLen != 0)
{
if(DataTotalLen == BackupDataTotalLen)
{
UpgradeStep = 0;
}
else
{
UpgradeStep = 1;
}
if(DataTotalLen > MAX_OTA_BUFF)
{
//ESP_LOGI("MSI","~~~~~~~~~~~~~~~~~~~~~~\n");
Flash_Size = MAX_OTA_BUFF;
esp_partition_read(assert_update_partition,StartAddr - BackupStartAddr + 16,buf,Flash_Size);
DataTotalLen -= Flash_Size;
}
else if(DataTotalLen != 0)
{
//ESP_LOGI("MSI","!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
Flash_Size = DataTotalLen;
esp_partition_read(assert_update_partition,StartAddr - BackupStartAddr + 16,buf,Flash_Size);
DataTotalLen = 0;
}
else
{
UpgradeStep = 3;
Step_delayTime = 0;
}
}
break;
default:
UpgradeStep=5;
/*Flash_Size =0;
temp_Size =0;
Write_Counter=0;
StartAddr = 0;
BackupStartAddr = 0;
DataTotalLen = 0;
BackupDataTotalLen = 0;*/
break;
}
}
Protocol_uint32_t CalcCrc32(Protocol_uint8_t buf[], int Len)
{
int i,j;
int n = 0;
Protocol_uint8_t LE32buf[4];
Protocol_uint32_t crc = 0xFFFFFFFF; // Initial value
for (n = 0; n < Len; n+=4)
{
LE32buf[0]=buf[n+3];//[n+0];//
LE32buf[1]=buf[n+2];//[n+1];//
LE32buf[2]=buf[n+1];//[n+2];//
LE32buf[3]=buf[n+0];//[n+3];//
for(j=0;j<4;j++)
{
crc ^= (Protocol_uint32_t)LE32buf[j] << 24;
for (i = 0; i < 8; ++i)
{
if (crc & 0x80000000)
{
crc = (crc << 1) ^ 0x04C11DB7; // 0xEDB88320= reverse 0x04C11DB7
}
else
{
crc = (crc << 1);
}
}
}
}
return crc;
}
Protocol_uint32_t UpdateBAT32A239Protocol_Parse(const Protocol_uint8_t *pData, Protocol_uint32_t len)
{
Protocol_uint8_t remainLen = len; // 剩余数据长度 Remaining data length
Protocol_uint8_t dataLen; // 数据包长度 Packet length
Protocol_uint8_t frameLen=0; // 帧长度 Frame length
Protocol_uint8_t checksumXor=0;
int i = 0;
/**
* 以下部分需要根据协议格式进行相应的修改,解析出每一帧的数据
*/
while ( remainLen >= 7 )
{
// 找到一帧数据的数据头
// Find the data header of a frame of data
while ( (remainLen >= 2) && ((pData [ 0 ] != 0xAA) || (pData [ 1 ] != 0x55)) )
{
pData++;
remainLen--;
continue;
}
dataLen = pData [ 4 ];//实际是[4][5]小端排序,但实际么有那么多直接取低字节
// 0 1 2 3 4 5 6~n 6+n+1 6+n+2 6+n+3
//STA1 + STA2+{< CMD_H + CMD_L + LENL+LENH > + (DAT) + <CR1 + CR2> }+XOR
frameLen = dataLen;//准确的一帧数据长度
// if ( frameLen > remainLen )// 数据内容不全
// {
// #ifdef DEBUG_PRO_DATA
// printf("Incomplete data packet!!!!!!\n");
// #endif
// break;
// }
// checksumXor=pData[0];
/*在 BOOT V1.0 的版本(获取版本信息命令见章节 2.3.2),异或运算不对 CR2
运算,只对 CR2 前面的字节进行运算, 即(STA1 + STA2 + {< CMD_H + CMD_L
+ LEN > + (DAT) + <CR1 >})。
*/
if(remainLen==frameLen)
{
for ( i = 0; i < remainLen-1; i++)
{
checksumXor^=pData[i];
}
// printf("Dataxor =%2x-- pData[remainLen-2] = %2x",checksumXor,pData[remainLen-2] );
}
if (checksumXor!=pData[remainLen-1])//抛弃坏帧
{
// 打印一帧数据,需要时在CommDef.h文件中打开DEBUG_PRO_DATA宏
#ifdef DEBUG_PRO_DATA
for ( i = 0; i < frameLen; ++i )
{
printf("%x ", pData [ i ]);
}printf("\n");
#endif
break;
}
memcpy(&BAT32A239_ACK.CMDH,&pData[2],frameLen-1);
pData += frameLen;
remainLen -= frameLen;
}
return len - remainLen;
}
\ No newline at end of file
......@@ -24,7 +24,108 @@ typedef struct
extern Protocol_User_Ctrl_Struct Prot_User;
void Protocol_User_Ctrl_Init(void );
void BAT32A239_MCU_Update(void);
void Prot_Send_Msg_Process(void );
Protocol_uint32_t CalcCrc32(Protocol_uint8_t buf[], int Len);
extern Protocol_uint32_t UpdateBAT32A239Protocol_Parse(const Protocol_uint8_t *pData, Protocol_uint32_t len);
extern void SendCmd_ResetComond(void);
#ifdef UPGRADE_N32G031
#define CMD_SET_BR 0x01//设置串口波特率
#define CMD_GET_INF 0x10//读取芯片型号索引、BOOT 版本号、芯片 ID
#define CMD_FLASH_ERASE 0x30//擦除 FLASH
#define CMD_FLASH_DWNLD 0x31//下载用户程序到 FLASH
#define CMD_DATA_CRC_CHECK 0x32//CRC 校验下载用户程
#define CMD_OPT_RW 0x40//读取/配置选项字节(包含了读保护等级、FLASH 页写保护、Data0/1 配置等)
#define CMD_SYS_RESET 0x50//系统复位
#define CMD_APP_GO 0x51//跳转到用户区执行程序
typedef struct
{
Protocol_uint8_t CMDH; //宏定义所包含的
Protocol_uint8_t CMDL;
Protocol_uint16_t LEN; //不关心发送的端格式
Protocol_uint8_t PAR[4];//需要处理好段格式
Protocol_uint8_t DAT[160];//补充的数据直接补充好再传到下层
}UpdateProtocolStructure;//上层协议数据结构
typedef struct
{
Protocol_uint8_t CMDH ;
Protocol_uint8_t CMDL ;
Protocol_uint8_t LEN[2];
union
{
Protocol_uint8_t DAT[128];
struct
{
Protocol_uint8_t unused_0 :8;
Protocol_uint8_t BootVer :8;
Protocol_uint8_t BootCmdVer :8;
Protocol_uint8_t UCID [16];
Protocol_uint8_t ChipID_UID [12];
Protocol_uint8_t DBGMCU_IDCODE[4];
Protocol_uint8_t Other [16];
Protocol_uint8_t CR1 :8;
Protocol_uint8_t CR2 :8;
}Chipinf;
struct
{
Protocol_uint8_t CR1 :8;
Protocol_uint8_t CR2 :8;
}Erase;
struct
{
Protocol_uint8_t CR1 :8;
Protocol_uint8_t CR2 :8;
}download;
struct
{
Protocol_uint8_t CR1 :8;
Protocol_uint8_t CR2 :8;
}verification;
struct
{
Protocol_uint8_t CR1 :8;
Protocol_uint8_t CR2 :8;
}reset;
struct
{
Protocol_uint8_t CR1 :8;
Protocol_uint8_t CR2 :8;
}appgo;
struct
{
struct Protocol_Lib
{
Protocol_uint8_t RDP ;
Protocol_uint8_t nRDP ;
Protocol_uint8_t USER ;
Protocol_uint8_t nUSER ;
Protocol_uint8_t Data0;
Protocol_uint8_t nData0;
Protocol_uint8_t Data1;
Protocol_uint8_t nData1;
Protocol_uint8_t WRP0;
Protocol_uint8_t nWRP0;
Protocol_uint8_t WRP1;
Protocol_uint8_t nWRP1;
Protocol_uint8_t RDP2;
Protocol_uint8_t nRDP2;
Protocol_uint8_t Reserved;
Protocol_uint8_t nReserved;
}optionbyte;
Protocol_uint8_t CR1 :8;
Protocol_uint8_t CR2 :8;
}flashOpt;
}dat;
}N32G031_ACK_Structure;//下层应答协议
extern N32G031_ACK_Structure N32G031_ACK;
Protocol_uint32_t UpdateN32G031Protocol_Send(UpdateProtocolStructure SendPd);
Protocol_uint32_t UpdateN32G031Protocol_Parse(const Protocol_uint8_t *pData, Protocol_uint32_t len);
#endif
#endif
......@@ -448,6 +448,8 @@ void Ble_User_Task(void *pvParameter)
vTaskDelete(NULL);
}
TaskHandle_t Ble_User_Task_hdl=NULL;
void Ble_User_Init(void )
{
BleRecSuc_Semaphore = xSemaphoreCreateBinary();
......@@ -474,6 +476,5 @@ void Ble_User_Init(void )
Ble_Clear_Rx_Buffer();
xTaskCreatePinnedToCore(Ble_User_Task, "Ble_User", 4096, NULL, 10, NULL, 0);
xTaskCreatePinnedToCore(Ble_User_Task, "Ble_User", 4096, NULL, 10, Ble_User_Task_hdl, 0);
}
......@@ -19,8 +19,8 @@ static void bt_app_task_handler(void *arg);
static bool bt_app_send_msg(bt_app_msg_t *msg);
static void bt_app_work_dispatched(bt_app_msg_t *msg);
static QueueHandle_t bt_app_task_queue = NULL;
static TaskHandle_t bt_app_task_handle = NULL;
QueueHandle_t bt_app_task_queue = NULL;
TaskHandle_t bt_app_task_handle = NULL;
bool bt_app_work_dispatch(bt_app_cb_t p_cback, uint16_t event, void *p_params, int param_len, bt_app_copy_cb_t p_copy_cback)
{
......
......@@ -104,12 +104,12 @@ static void Uart_Rx_Task(void *arg)
}
free(data);
}
TaskHandle_t Uart_Rx_Taskhdl;
void bsp_Uart_Init(void )
{
init_Uart();
Protocol_KL30_Wakeup_Init();
xTaskCreatePinnedToCore(Uart_Rx_Task, "Ble_User", 4096, NULL, 4, NULL, 1);
xTaskCreatePinnedToCore(Uart_Rx_Task, "Ble_User", 4096, NULL, 4, Uart_Rx_Taskhdl, 1);
}
......@@ -119,16 +119,16 @@ void bsp_Uart_Init(void )
extern void simple_ota_main(void);
void simple_ota_service(void)
{
if(Wifi_OTA_Request == 1)
{
Wifi_OTA_Request = 2;
simple_ota_main();
vTaskDelay(portMAX_DELAY);
}
}
// extern void simple_ota_main(void);
// void simple_ota_service(void)
// {
// if(Wifi_OTA_Request == 1)
// {
// Wifi_OTA_Request = 2;
// simple_ota_main();
// vTaskDelay(portMAX_DELAY);
// }
// }
......
......@@ -73,7 +73,7 @@ void bsp_Uart_Init(void );
int bsp_Ble_Gatts_Send_Indicate(uint8_t len, uint8_t *data);
void simple_ota_service(void);
// void simple_ota_service(void);
extern uint8_t BT_Device_Name[14];
......
......@@ -28,7 +28,7 @@
#include "app_BT_User.h"
#include "bt_app_hf.h"
#include "wifi_service.h"
#define TAG "MAIN_USER"
extern esp_bd_addr_t peer_addr;
......@@ -45,11 +45,16 @@ uint32_t Sys_1ms_Cnt;
uint32_t testcnt;
extern uint32_t SwitchMode;
static void Sys_Run_Tasks(void *arg)
{
uint8_t i = 0;
while(1)
{
if(SwitchMode!=0)
{
break;
}
if(Sys_1ms_Cnt < 499)
{
Sys_1ms_Cnt ++ ;
......@@ -86,7 +91,7 @@ static void Sys_Run_Tasks(void *arg)
if(SYS_RUN_TASK_1000MS)
{
simple_ota_service();
// simple_ota_service();
testcnt++;
if(testcnt >= 10)
......@@ -120,9 +125,29 @@ static void Sys_Run_Tasks(void *arg)
vTaskDelay(1);
}
vTaskDelete(NULL);
}
TaskHandle_t wifi_service_hdl=NULL;
extern uint32_t SwitchMode;
extern void wifiServiceStart(void);
extern void Upgrade_BAT32A239_Task(void *arg);
static void wifi_service_task(void *arg)
{
while (1)
{
// if(SwitchMode == 1)
// {
// //delele_tasks();
// xTaskCreatePinnedToCore(Upgrade_BAT32A239_Task, "Upgrade_BAT32A239_Task", 1024 * 4, NULL, 5, NULL, 1);
// SwitchMode=2;
// }
// wifi_service_timer();
wifi_service();
vTaskDelay(pdMS_TO_TICKS(100));
}
}
TaskHandle_t Sys_Run_Taskshdl=NULL;
void app_main(void)
{
Protocol_User_Ctrl_Init();
......@@ -135,9 +160,16 @@ void app_main(void)
bsp_Uart_Init();
printf("KL30 INIT OVER~~~~~~\r\n");
xTaskCreatePinnedToCore(Sys_Run_Tasks, "Sys_Run_Tasks", 4096, NULL, 3, NULL, 1);
xTaskCreatePinnedToCore(Sys_Run_Tasks, "Sys_Run_Tasks", 4096, NULL, 3, Sys_Run_Taskshdl, 1);
xTaskCreatePinnedToCore(wifi_service_task, "wifi_service_task", 4096, NULL, 5, &wifi_service_hdl, 1);
xTaskCreatePinnedToCore(Upgrade_BAT32A239_Task, "Upgrade_BAT32A239_Task", 1024 * 4, NULL, 5, NULL, 1);
}
void delele_tasks(void)
{
// vTaskSuspend(Sys_Run_Taskshdl);
// vTaskSuspend(Ble_User_Task_hdl);
// bt_app_task_shut_down( );
// vTaskDelay(pdMS_TO_TICKS(100));
}
#ifndef _MAIN_USER_H_
#define _MAIN_USER_H_
extern TaskHandle_t Ble_User_Task_hdl;
extern TaskHandle_t Sys_Run_Taskshdl;
extern TaskHandle_t Uart_Rx_Taskhdl;
extern void bt_app_task_shut_down(void);
extern void delateBleUser_Task(void);
#endif
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -213,11 +213,11 @@ CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y
# CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_NONE is not set
# CONFIG_BOOTLOADER_LOG_LEVEL_NONE is not set
# CONFIG_BOOTLOADER_LOG_LEVEL_ERROR is not set
CONFIG_BOOTLOADER_LOG_LEVEL_WARN=y
# CONFIG_BOOTLOADER_LOG_LEVEL_INFO is not set
# CONFIG_BOOTLOADER_LOG_LEVEL_WARN is not set
CONFIG_BOOTLOADER_LOG_LEVEL_INFO=y
# CONFIG_BOOTLOADER_LOG_LEVEL_DEBUG is not set
# CONFIG_BOOTLOADER_LOG_LEVEL_VERBOSE is not set
CONFIG_BOOTLOADER_LOG_LEVEL=2
CONFIG_BOOTLOADER_LOG_LEVEL=3
#
# Serial Flash Configurations
......@@ -985,7 +985,7 @@ CONFIG_RTC_CLK_CAL_CYCLES=1024
#
# Peripheral Control
#
# CONFIG_PERIPH_CTRL_FUNC_IN_IRAM is not set
CONFIG_PERIPH_CTRL_FUNC_IN_IRAM=y
# end of Peripheral Control
#
......@@ -1298,7 +1298,7 @@ CONFIG_FREERTOS_CORETIMER_0=y
# CONFIG_FREERTOS_CORETIMER_1 is not set
CONFIG_FREERTOS_SYSTICK_USES_CCOUNT=y
# CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH is not set
# CONFIG_FREERTOS_PLACE_SNAPSHOT_FUNS_INTO_FLASH is not set
CONFIG_FREERTOS_PLACE_SNAPSHOT_FUNS_INTO_FLASH=y
# CONFIG_FREERTOS_CHECK_PORT_CRITICAL_COMPLIANCE is not set
CONFIG_FREERTOS_ASSERT_ON_UNTESTED_FUNCTION=y
CONFIG_FREERTOS_ENABLE_TASK_SNAPSHOT=y
......@@ -1899,11 +1899,11 @@ CONFIG_WPA_MBEDTLS_TLS_CLIENT=y
# CONFIG_ESP32_COMPATIBLE_PRE_V3_1_BOOTLOADERS is not set
# CONFIG_LOG_BOOTLOADER_LEVEL_NONE is not set
# CONFIG_LOG_BOOTLOADER_LEVEL_ERROR is not set
CONFIG_LOG_BOOTLOADER_LEVEL_WARN=y
# CONFIG_LOG_BOOTLOADER_LEVEL_INFO is not set
# CONFIG_LOG_BOOTLOADER_LEVEL_WARN is not set
CONFIG_LOG_BOOTLOADER_LEVEL_INFO=y
# CONFIG_LOG_BOOTLOADER_LEVEL_DEBUG is not set
# CONFIG_LOG_BOOTLOADER_LEVEL_VERBOSE is not set
CONFIG_LOG_BOOTLOADER_LEVEL=2
CONFIG_LOG_BOOTLOADER_LEVEL=3
# CONFIG_APP_ROLLBACK_ENABLE is not set
# CONFIG_FLASH_ENCRYPTION_ENABLED is not set
# CONFIG_FLASHMODE_QIO is not set
......
idf_component_register(SRCS "http_server.c" "wifi_service.c" "softap.c"
INCLUDE_DIRS "." "../../main"
PRIV_REQUIRES nvs_flash esp_netif esp_wifi esp_http_server app_update driver
EMBED_FILES "favicon.ico" "ota_page.html")
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1" charset="utf-8">
<title>ESP32</title>
</head>
<body>
<h2>ESP32</h2>
<hr><br>
<button id="ota" type="button" onclick="ota()">ESP32 固件升级</button>
<script>
function ota() {
window.location.href = "http://192.168.4.1/ota";
}
</script>
</body>
</html>
\ No newline at end of file
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1" charset="utf-8">
<title>固件升级</title>
</head>
<body>
<h2>固件升级</h2>
<hr>
<a href="http://192.168.4.1" style="font-size: smaller;">[返回首页]</a><br><br>
<!-- 选择文本按钮 -->
<label for="newFile">加载文件:</label>
<input id="newFile" type="file" accept=".bin" onchange="checkFile()">
<br><br>
<!-- 上传操作 -->
<label for="otaStart">执行操作:</label>
<button id="otaStart" type="button" onclick="otaStart()">开始升级</button>
<button id="reload" type="button" onclick="reload()">刷新界面</button>
<br><br>
<!-- 进度显示 -->
<label for="otaPercent">进度显示:</label>
<input id="otaPercent" type="text" value="0.00%" style="width: 75px;border: none;font-size:large;">
<progress id="otaProgress" value="0" max="100"></progress>
<br><br><hr>
<p id="viewName"></p>
<p id="viewSize"></p>
<p id="viewFlashStart"></p>
<p id="viewFlashResult"></p>
<script>
function reload() {
location.reload();
}
function getFileSize(size) {
if (!size) return "";
var num = 1024.00;
if (size < num) {
return size + "B";
}
if (size < Math.pow(num, 2)) {
return (size / num).toFixed(2) + "KB";
}
if (size < Math.pow(num, 3)) {
return (size / Math.pow(num, 2)).toFixed(2) + "MB";
}
}
function checkFile() {
var newFile = document.getElementById("newFile").files[0];
var newFileName = newFile.name;
var newFileSize = newFile.size;
if (newFileSize > 2 * 1024 * 1024) {
alert('所选文件超出最大限制\n点击确定后将自动刷新页面');
location.reload();
}
else {
document.getElementById("viewName").innerHTML = "文件名称:" + newFileName;
document.getElementById("viewSize").innerHTML = "文件大小:" + getFileSize(newFileSize);
}
}
function otaStart() {
var res = document.getElementById("newFile").files[0];
if (typeof (res) == "undefined") {
alert('未选择文件!');
}
else {
var filepath = document.getElementById("newFile").files[0].name;
var upload_path = "/ota/" + filepath;
document.getElementById("viewFlashStart").innerHTML = "锁定页面,请务必保持WiFi在线,正在上传...";
document.getElementById("newFile").disabled = true;
document.getElementById("otaStart").disabled = true;
var file = document.getElementById("newFile").files[0];
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function () {
if (xhttp.readyState == 4) {
if (xhttp.status == 200) {
document.getElementById("viewFlashResult").innerHTML = "上传成功!";
} else if (xhttp.status == 0) {
document.getElementById("viewFlashResult").innerHTML = "服务器断开!<br><br>请检查服务器是否在线,刷新页面后重新上传...";
} else {
alert(xhttp.status + " Error!\n" + xhttp.responseText);
}
}
};
let progressBar = document.getElementById("otaProgress");
xhttp.upload.onprogress = function (e) {
var percentage = (event.loaded * 100.00) / (event.total * 1.00);
percentage = percentage.toFixed(2);
progressBar.value = Math.round(percentage);
document.getElementById("otaPercent").value = percentage + "%";
}
xhttp.open("POST", upload_path, true);
xhttp.send(file);
}
}
</script>
</body>
</html>
\ No newline at end of file
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <esp_log.h>
#include <nvs_flash.h>
#include <sys/param.h>
#include "esp_netif.h"
#include <esp_wifi.h>
#include <esp_system.h>
#include "nvs_flash.h"
#include "esp_ota_ops.h"
#include "http_server.h"
#include "Protocol_User.h"
static const char *TAG = "http_server";
char buf[MAX_OTA_BUFF]; // 接收服务端传来的文件缓存, 必须使用全局变量, 否则会触发看门狗复位, 原理未知
extern void Cache_data(unsigned char* p,uint32_t len);
extern void SetUpgradeFlashSize(uint32_t size,uint32_t len);
extern void SetUpgradeStart(void);//初始状态
static unsigned char softap_ota_start = 0;
httpd_handle_t http_server = NULL;
static esp_err_t index_html_get_handler(httpd_req_t *req)
{
ESP_LOGI(TAG, "---- 回到起始页");
httpd_resp_set_status(req, "307 Temporary Redirect");
httpd_resp_set_hdr(req, "Location", "/");
httpd_resp_send(req, NULL, 0);
return ESP_OK;
}
static esp_err_t favicon_get_handler(httpd_req_t *req)
{
extern const unsigned char favicon_ico_start[] asm("_binary_favicon_ico_start");
extern const unsigned char favicon_ico_end[] asm("_binary_favicon_ico_end");
const size_t favicon_ico_size = (favicon_ico_end - favicon_ico_start);
ESP_LOGI(TAG, "---- 下载网站图标");
httpd_resp_set_type(req, "image/x-icon");
httpd_resp_send(req, (const char *)favicon_ico_start, favicon_ico_size);
return ESP_OK;
}
static esp_err_t http_resp_dir_html(httpd_req_t *req)
{
extern const unsigned char ota_page_start[] asm("_binary_ota_page_html_start");
extern const unsigned char ota_page_end[] asm("_binary_ota_page_html_end");
const size_t ota_page_size = (ota_page_end - ota_page_start);
ESP_LOGI(TAG, "---- 下载网站起始页");
httpd_resp_set_type(req, "text/HTML");
httpd_resp_send(req, (const char *)ota_page_start, ota_page_size);
return ESP_OK;
}
static esp_err_t download_get_handler(httpd_req_t *req)
{
const char *uri_get = req->uri;
ESP_LOGI(TAG, "---- GET URI: 192.168.4.1%s", req->uri);
if (strcmp(uri_get, "/") == 0)
{
return http_resp_dir_html(req);
}
else if (strcmp(uri_get, "/favicon.ico") == 0)
{
return favicon_get_handler(req);
}
else
{
ESP_LOGI(TAG, "---- 非预设GET, 不处理, 直接回到起始页");
return index_html_get_handler(req);
}
return ESP_OK;
}
static esp_err_t app_post_handler(httpd_req_t *req)
{
int ret = 0;
int recv_block = 0;
int remaining = req->content_len;
int total = remaining;
double percent = 0.0;
ESP_LOGI(TAG, "---- 应用程序更新, 需接收数据长度(bytes): %d", remaining);
esp_ota_handle_t app_update_handle = 0;
const esp_partition_t *app_update_partition = esp_ota_get_next_update_partition(NULL);
esp_err_t err = esp_ota_begin(app_update_partition, OTA_WITH_SEQUENTIAL_WRITES, &app_update_handle);
while (remaining > 0)
{
/* Read the data for the request */
if ((ret = httpd_req_recv(req, buf, MIN(remaining, sizeof(buf)))) <= 0)
{
if (ret == HTTPD_SOCK_ERR_TIMEOUT)
{
/* Retry receiving if timeout occurred */
continue;
}
return ESP_FAIL;
}
err = esp_ota_write(app_update_handle, buf, ret);
if (err != ESP_OK)
{
ESP_LOGI(TAG, "---- 写入数据失败, 错误信息:%s", esp_err_to_name(err));
}
else
{
remaining -= ret;
recv_block++;
if ((recv_block % 20) == 0)
{
percent = 100.0 - (double)(remaining * 100) / (double)total;
ESP_LOGI(TAG, "---- 写入OTA升级数据: %.2f%%", percent);
}
}
// 增加20ms延时, 解决CPU0看门狗超时的问题
vTaskDelay(pdMS_TO_TICKS(20));
}
err = esp_ota_end(app_update_handle);
if (err == ESP_OK)
{
esp_err_t err = esp_ota_set_boot_partition(app_update_partition);
if (err != ESP_OK)
{
ESP_LOGI(TAG, "---- 设备启动分区失败, 错误信息:%s", esp_err_to_name(err));
}
else
{
ESP_LOGI(TAG, "---- 应用程序更新完成, 3秒后自动重启.");
httpd_resp_send_chunk(req, NULL, 0);
// delele_tasks();
// httpd_resp_sendstr(req, "<p>应用程序更新完成,3秒后自动重启.</p>");
vTaskDelay(pdMS_TO_TICKS(3000));
//esp_restart();
SendCmd_ResetComond();
}
}
// End response
// httpd_resp_sendstr(req, "<p>数据上传完成,但应用更新不成功,请重试.</p>");
ESP_LOGI(TAG, "---- 数据接收完成, OTA失败, 1秒后自动重启.");
httpd_resp_send_chunk(req, NULL, 0);
// delele_tasks();
vTaskDelay(pdMS_TO_TICKS(1000));
esp_restart();
return ESP_OK;
}
// static esp_err_t assert_post_handler(httpd_req_t *req)
// {
// int ret, remaining = req->content_len;
// while (remaining > 0)
// {
// /* Read the data for the request */
// if ((ret = httpd_req_recv(req, buf, MIN(remaining, sizeof(buf)))) <= 0)
// {
// if (ret == HTTPD_SOCK_ERR_TIMEOUT)
// {
// /* Retry receiving if timeout occurred */
// continue;
// }
// return ESP_FAIL;
// }
// remaining -= ret;
// // ESP_LOGI(TAG, "=========== RECEIVED DATA ==========");
// // 数据处理代码
// // ESP_LOGI(TAG, "====================================");
// }
// // End response
// httpd_resp_send_chunk(req, NULL, 0);
// return ESP_OK;
// }
// static esp_err_t storage_post_handler(httpd_req_t *req)
// {
// int ret, remaining = req->content_len;
// while (remaining > 0)
// {
// /* Read the data for the request */
// if ((ret = httpd_req_recv(req, buf, MIN(remaining, sizeof(buf)))) <= 0)
// {
// if (ret == HTTPD_SOCK_ERR_TIMEOUT)
// {
// /* Retry receiving if timeout occurred */
// continue;
// }
// return ESP_FAIL;
// }
// remaining -= ret;
// // ESP_LOGI(TAG, "=========== RECEIVED DATA ==========");
// // 数据处理代码
// // ESP_LOGI(TAG, "====================================");
// }
// // End response
// httpd_resp_send_chunk(req, NULL, 0);
// return ESP_OK;
// }
static void MSI_Print_mem16(size_t len,char *buf)
{
for (size_t i = 0; i < len; )
{
ESP_LOGI("MSI","%02xh: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",i,\
buf[i+0],buf[i+1],buf[i+2],buf[i+3],buf[i+4],buf[i+5],buf[i+6],buf[i+7],
buf[i+8],buf[i+9],buf[i+10],buf[i+11],buf[i+12],buf[i+13],buf[i+14],buf[i+15]);
i+=16;
}
}
/*上传文件名是BAT32A239dat.bin的处理函数*/
static esp_err_t nation_post_handler(httpd_req_t *req)
{
int recv_block = 0;
double percent = 0.0;
int ret, remaining = req->content_len;
int total = remaining;
int err_timeout_retry_cnt = 0;
size_t erase_size = 0;
size_t erase_offset = 0;
size_t write_offset = 0;
int Addr = 0;
esp_err_t err = ESP_OK;
const char *partition_label = "assert";
const esp_partition_t *assert_update_partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, partition_label);
// if (Sys_Run_hdl != NULL)
// {
// vTaskDelete(Sys_Run_hdl);
// Sys_Run_hdl = NULL;
// vTaskDelay(pdMS_TO_TICKS(100));
// }
//SetUpgradeFlashSize(remaining); // 设定文件大小
ESP_LOGI(TAG, "---- 国民技术程序文件: 需要接收的数据(byte) = %d", remaining);
while (remaining > 0)
{
/* Read the data for the request */
if ((ret = httpd_req_recv(req, buf, MIN(remaining, sizeof(buf)))) <= 0)
{
if (ret == HTTPD_SOCK_ERR_TIMEOUT)
{
err_timeout_retry_cnt++;
if (err_timeout_retry_cnt >= MAX_RETRY_COUNT)
{
httpd_resp_send_408(req);
httpd_resp_send_chunk(req, NULL, 0);
ESP_LOGE(TAG, "---- 接收数据超时, 退出升级流程, 请保持无线连接稳定后再试.");
return ESP_FAIL;
}
/* else
{
Retry receiving if timeout occurred
continue;
}*/
}
else
{
ESP_LOGI("MSI","total : %d \n",total);
ESP_LOGI("MSI","remaining : %d \n",remaining);
err_timeout_retry_cnt = 0;
}
}
if(total == remaining)//下载长度+地址
{
Addr = 0;
Addr |= buf[8];
Addr <<= 8;
Addr |= buf[9];
Addr <<= 8;
Addr |= buf[10];
Addr <<= 8;
Addr |= buf[11];
SetUpgradeFlashSize(remaining, Addr);
}
while (erase_offset < write_offset + ret)
{
err = esp_partition_erase_range(assert_update_partition, erase_offset, assert_update_partition->erase_size);
if (err == ESP_OK)
{
erase_offset += assert_update_partition->erase_size;
}
else
{
httpd_resp_send_chunk(req, NULL, 0);
//ESP_LOGE(TAG, "---- assert 分区擦除失败(%s), 分区容量 = 0x%x, 偏移地址 = 0x%x, 擦除长度 = 0x%x", esp_err_to_name(err), assert_update_partition->size, erase_offset, assert_update_partition->erase_size);
return ESP_FAIL;
}
}
err = esp_partition_write(assert_update_partition, write_offset, buf, ret);
if (err == ESP_OK)
{
remaining -= ret;
write_offset += ret;
recv_block++;
if ((recv_block % 32) == 0)
{
percent = 100.0 - (double)(remaining * 100) / (double)total;
ESP_LOGI(TAG, "---- 写入数据(%.2f%%), recv_block = %d", percent, recv_block);
}
}
else
{
httpd_resp_send_chunk(req, NULL, 0);
ESP_LOGE(TAG, "---- assert 分区写数据失败(%s)", esp_err_to_name(err));
return ESP_FAIL;
}
// 增加20ms延时, 解决CPU0看门狗超时的问题
vTaskDelay(pdMS_TO_TICKS(20));
}
ESP_LOGI(TAG, "---- write_offset = %d", write_offset);
if (write_offset == total)
{
ESP_LOGI(TAG, "---- assert 分区更新完成, 1秒后自动重启.");
vTaskDelay(pdMS_TO_TICKS(1000));
}
else
{
httpd_resp_send_chunk(req, NULL, 0);
ESP_LOGE(TAG, "---- assert 分区更新数据部分丢失");
return ESP_FAIL;
}
SetUpgradeStart(); // 启动升级
ESP_LOGI(TAG, "---- 国民技术程序文件: 接收完成");
return ESP_OK;
}
void Nat32G031_ReqReset(void)
{
ESP_LOGI(TAG, "---- NAT32G031程序更新完成, 3秒后自动重启.");
// delele_tasks();
// httpd_resp_sendstr(req, "<p>应用程序更新完成,3秒后自动重启.</p>");
vTaskDelay(pdMS_TO_TICKS(3000));
esp_restart();
}
static esp_err_t upload_post_handler(httpd_req_t *req)
{
const char *uri_post = req->uri;
ESP_LOGI(TAG, "---- POST URI: 192.168.4.1%s", req->uri);
if (strcmp(uri_post, "/upload/RT200T-2.bin") == 0)
{
return app_post_handler(req);
}
// else if (strcmp(uri_post, "/upload/mmap_assert.bin") == 0)
// {
// return assert_post_handler(req);
// }
// else if (strcmp(uri_post, "/upload/storage.bin") == 0)
//{
// return storage_post_handler(req);
//}
else if (strcmp(uri_post, "/upload/BAT32G139.bin") == 0)
{
return nation_post_handler(req);
}
else
{
ESP_LOGI(TAG, "---- 非预设POST, 不处理, 直接回到起始页");
return index_html_get_handler(req);
}
return ESP_OK;
}
void set_softap_ota_status(unsigned char status)
{
softap_ota_start = status;
}
unsigned char get_softap_ota_status(void)
{
return softap_ota_start;
}
httpd_handle_t start_webserver(void)
{
httpd_handle_t server = NULL;
httpd_config_t config = HTTPD_DEFAULT_CONFIG();
config.lru_purge_enable = true;
config.uri_match_fn = httpd_uri_match_wildcard;
// Start the httpd server
ESP_LOGI(TAG, "---- 服务器端口号: '%d'", config.server_port);
if (httpd_start(&server, &config) == ESP_OK)
{
// Set URI handlers
ESP_LOGI(TAG, "---- 注册URI管理程序");
// 注册客户端下载行为
httpd_uri_t download_cfg = {
.uri = "/*",
.method = HTTP_GET,
.handler = download_get_handler,
.user_ctx = NULL};
httpd_register_uri_handler(server, &download_cfg);
// 注册客户端上传行为
httpd_uri_t upload_cfg = {
.uri = "/upload/*",
.method = HTTP_POST,
.handler = upload_post_handler,
.user_ctx = NULL};
httpd_register_uri_handler(server, &upload_cfg);
return server;
}
ESP_LOGI(TAG, "---- 服务器启动时发生错误.");
return NULL;
}
esp_err_t stop_webserver(httpd_handle_t server)
{
return httpd_stop(server);
}
/******************************************
*根据某种状态自动开关webserver的监听处理,
*没有任何STA连接AP,自动关闭webserver,
*任意STA连接AP,自动开启webserver.
******************************************/
void connect_handler(void *arg)
{
httpd_handle_t *server = (httpd_handle_t *)arg;
if (*server == NULL)
{
ESP_LOGI(TAG, "---- 开启HTTP服务器");
*server = start_webserver();
}
}
void disconnect_handler(void *arg)
{
httpd_handle_t *server = (httpd_handle_t *)arg;
if (*server)
{
ESP_LOGI(TAG, "---- 关闭HTTP服务器");
if (stop_webserver(*server) == ESP_OK)
{
*server = NULL;
}
else
{
ESP_LOGE(TAG, "Failed to stop http server");
}
}
}
httpd_handle_t http_service(void)
{
static httpd_handle_t server = NULL;
// 首次启动http_server
server = start_webserver();
if (server)
{
ESP_LOGI(TAG, "---- HTTP服务器开启成功.");
}
else
{
ESP_LOGI(TAG, "---- HTTP服务器开启失败.");
}
return server;
}
#ifndef _GTTP_SERVER_H_
#define _GTTP_SERVER_H_
#include "esp_event.h"
#include "esp_http_server.h"
#define HTTP_SERVER_STOP 0
#define HTTP_SERVER_INIT 1
#define HTTP_SERVER_START 2
#define HTTP_SERVER_DEINIT 3
#define MAX_OTA_BUFF 4096u
#define MAX_RETRY_COUNT 5
extern char buf[MAX_OTA_BUFF];
extern httpd_handle_t http_server;
void set_softap_ota_status(unsigned char status);
unsigned char get_softap_ota_status(void);
void connect_handler(void *arg);
void disconnect_handler(void *arg);
httpd_handle_t http_service(void);
extern void delele_tasks(void);
extern void Catch_data(unsigned char *p, uint32_t len);
extern void SetUpgradeFlashSize(uint32_t size,uint32_t len);
extern void SetUpgradeStart(void); // ��ʼ״̬
void Nat32G031_ReqReset(void);
#endif
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1" charset="utf-8">
<title>OTA Page</title>
</head>
<body>
<h2>OTA Page</h2>
<hr>
<!-- 下拉菜单 -->
<label for="selectPartition">目标分区:</label>
<select id="selectPartition" name="selectPartition">
<option selected value="RT200T-2.bin">Application</option>
<option value="BAT32G139.bin">MCU_app</option>
</select>
<br><br>
<!-- 选择文本按钮 -->
<label for="newfile">目标文件:</label>
<input id="newfile" type="file" accept=".bin" onchange="checkFile()">
<br><br>
<!-- 上传操作 -->
<label for="upload">执行操作:</label>
<button id="upload" type="button" onclick="upload()">开始上传</button>
<button id="home" type="button" onclick="homePage()">重置页面</button>
<br><br>
<!-- 进度显示 -->
<label for="uploadPercent">进度显示:</label>
<input id="uploadPercent" type="text" value="0.00%" style="width: 75px;border: none;font-size:large;">
<progress id="uploadProgress" value="0" max="100"></progress>
<hr>
<p id="view_name"></p>
<p id="view_size"></p>
<p id="view_flash_start"></p>
<p id="view_flash_result"></p>
<script>
function homePage() {
location.reload();
}
function getfilesize(size) {
if (!size) return "";
var num = 1024.00;
if (size < num) {
return size + "B";
}
if (size < Math.pow(num, 2)) {
return (size / num).toFixed(2) + "KB";
}
if (size < Math.pow(num, 3)) {
return (size / Math.pow(num, 2)).toFixed(2) + "MB";
}
}
function checkFile() {
var currentPartition = document.getElementById("selectPartition").value;
var newFile = document.getElementById("newfile").files[0];
var newFileName = newFile.name;
var newFileSize = newFile.size;
filepath = newFileName;
if (newFileName != currentPartition) {
alert('所选文件与目标分区不匹配\n点击确定后将自动刷新页面\n');
homePage();
}
if (newFileSize > 16 * 1024 * 1024) {
alert('所选文件超出最大限制\n点击确定后将自动刷新页面');
homePage();
}
else {
document.getElementById("view_name").innerHTML = "文件名称:" + newFileName;
document.getElementById("view_size").innerHTML = "文件大小:" + getfilesize(newFileSize);
}
}
function upload() {
var res = document.getElementById("newfile").files[0];
if (typeof (res) == "undefined") {
alert('未选择文件!');
}
else {
var filepath = document.getElementById("newfile").files[0].name;
var upload_path = "/upload/" + filepath;
document.getElementById("view_flash_start").innerHTML = "锁定页面,请务必保持WiFi在线,正在上传...";
document.getElementById("selectPartition").disabled = true;
document.getElementById("newfile").disabled = true;
document.getElementById("upload").disabled = true;
var file = document.getElementById("newfile").files[0];
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function () {
if (xhttp.readyState == 4) {
if (xhttp.status == 200) {
document.getElementById("view_flash_result").innerHTML = "上传成功!";
} else if (xhttp.status == 0) {
document.getElementById("view_flash_result").innerHTML = "服务器断开!<br><br>请检查服务器是否在线,刷新页面后重新上传...";
} else {
alert(xhttp.status + " Error!\n" + xhttp.responseText);
}
}
};
let progressBar = document.getElementById("uploadProgress");
xhttp.upload.onprogress = function (e) {
var percentage = (event.loaded * 100.00) / (event.total * 1.00);
percentage = percentage.toFixed(2);
progressBar.value = Math.round(percentage);
document.getElementById("uploadPercent").value = percentage + "%";
}
xhttp.open("POST", upload_path, true);
xhttp.send(file);
}
}
</script>
</body>
</html>
\ No newline at end of file
#include <stdio.h>
#include <string.h>
#include "nvs_flash.h"
#include "esp_event.h"
#include "esp_mac.h"
#include "esp_netif.h"
#include "esp_log.h"
#include "softap.h"
#include "wifi_service.h"
static const char *TAG = "softAP";
esp_netif_t *softap_netif = NULL;
wifi_sta_list_t softap_sta_list;
unsigned char softap_sta_connect = STA_CONNECTED_NEVER;
static void softap_event_handler(void *event_handler_arg, esp_event_base_t event_base, int32_t event_id, void *event_data)
{
if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_AP_STACONNECTED)
{
wifi_event_ap_staconnected_t *event = (wifi_event_ap_staconnected_t *)event_data;
ESP_LOGI(TAG, "---- 设备加入网络, MAC地址 :" MACSTR ", 编号(AID) = %d.", MAC2STR(event->mac), event->aid);
softap_sta_connect = STA_CONNECTED_ONCE;
connect_handler(event_handler_arg);
wifi_service_stop_timer_clear();
}
if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_AP_STADISCONNECTED)
{
wifi_event_ap_stadisconnected_t *event = (wifi_event_ap_stadisconnected_t *)event_data;
ESP_LOGI(TAG, "---- 设备退出网络, MAC地址 :" MACSTR ", 编号(AID) = %d.", MAC2STR(event->mac), event->aid);
disconnect_handler(event_handler_arg);
wifi_service_stop_timer_clear();
}
}
void softap_service_start(void)
{
// NVS分区初始化
ESP_LOGI(TAG, "---- nvs分区初始化...");
esp_err_t ret = nvs_flash_init();
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND)
{
ESP_ERROR_CHECK(nvs_flash_erase());
ret = nvs_flash_init();
}
ESP_ERROR_CHECK(ret);
// 创建系统事件循环
ESP_LOGI(TAG, "---- 创建系统事件循环...");
ESP_ERROR_CHECK(esp_event_loop_create_default());
// 将WiFi的所有事件作为实例注册进系统事件循环中
ESP_LOGI(TAG, "---- 注册WiFi事件实例...");
ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, softap_event_handler, &http_server));
// 初始化网卡相关的底层配置
ESP_LOGI(TAG, "---- 网卡初始化...");
ESP_ERROR_CHECK(esp_netif_init());
// 以默认的方式创建一个ap类型的网卡
ESP_LOGI(TAG, "---- 创建AP类型网卡...");
softap_netif = esp_netif_create_default_wifi_ap();
// 初始化WiFi底层配置
ESP_LOGI(TAG, "---- WiFi初始化...");
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
// 将WiFi设置成AP模式
ESP_LOGI(TAG, "---- 配置WiFi为AP模式...");
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_AP));
// 创建AP配置
ESP_LOGI(TAG, "---- 创建AP配置...");
wifi_config_t wifi_config = {
.ap = {
.ssid = ESP_WIFI_SSID,
.ssid_len = strlen(ESP_WIFI_SSID),
.password = ESP_WIFI_PASSWD,
.max_connection = 1,
.authmode = WIFI_AUTH_WPA_WPA2_PSK}};
// 获取当前AP的MAC地址
unsigned char softap_mac[6];
esp_wifi_get_mac(WIFI_IF_AP, softap_mac);
// 将MAC地址后两个字节转为字符串
char softap_temp[5];
sprintf(softap_temp, "%02X%02X", softap_mac[4], softap_mac[5]);
// 将MAC地址拼接到 ESP_WIFI_SSID 后面
char softap_ssid[32] = ESP_WIFI_SSID;
strcat(softap_ssid, softap_temp);
// 重新配置 ssid 和 ssid_len
memcpy(wifi_config.ap.ssid, softap_ssid, sizeof(softap_ssid));
wifi_config.ap.ssid_len = strlen(softap_ssid);
// 配置AP的属性
ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_AP, &wifi_config));
// 开启WiFi
ESP_LOGI(TAG, "---- 开启WiFi, 名称 : %s 密码 : %s", wifi_config.ap.ssid, wifi_config.ap.password);
ESP_ERROR_CHECK(esp_wifi_start());
// 首次开启http_server
ESP_LOGI(TAG, "---- 首次开启HTTP服务器...");
http_server = http_service();
// 启动服务关闭计时器
ESP_LOGI(TAG, "---- 启动服务关闭计时器...");
wifi_service_stop_timer_clear();
}
void softap_service_stop(void)
{
// 关闭http_server
ESP_LOGI(TAG, "---- 关闭HTTP服务器...");
disconnect_handler(&http_server);
// 关闭WiFi
ESP_LOGI(TAG, "---- 关闭WiFi...");
ESP_ERROR_CHECK(esp_wifi_stop());
// WiFi反初始化
ESP_LOGI(TAG, "---- WiFi反初始化...");
ESP_ERROR_CHECK(esp_wifi_deinit());
// 销毁网卡实例
ESP_LOGI(TAG, "---- 销毁网卡实例...");
esp_netif_destroy_default_wifi(softap_netif);
// 网卡反初始化 - 官方未实现的功能
// ESP_LOGI(TAG, "---- 网卡反初始化...");
// ESP_ERROR_CHECK(esp_netif_deinit());
// 注销WiFi事件实例
ESP_LOGI(TAG, "---- 注销WiFi事件实例...");
ESP_ERROR_CHECK(esp_event_handler_unregister(WIFI_EVENT, ESP_EVENT_ANY_ID, softap_event_handler));
// 删除系统事件循环
ESP_LOGI(TAG, "---- 删除系统事件循环...");
ESP_ERROR_CHECK(esp_event_loop_delete_default());
// NVS分区反初始化
ESP_LOGI(TAG, "---- NVS分区反初始化...");
ESP_ERROR_CHECK(nvs_flash_deinit());
ESP_LOGI(TAG, "---- WiFi服务已关闭, 重置WiFi参数");
wifi_service_init();
}
#ifndef _SOFTAP_H_
#define _SOFTAP_H_
#include "esp_wifi.h"
#include "http_server.h"
#define SOFTAP_STOP 0
#define SOFTAP_INIT 1
#define SOFTAP_START 2
#define SOFTAP_DEINIT 3
#define STA_CONNECTED_NEVER 0
#define STA_CONNECTED_ONCE 1
#define ESP_WIFI_SSID "ESP32S3_AP_"
#define ESP_WIFI_PASSWD "12345677"
extern wifi_sta_list_t softap_sta_list;
extern unsigned char softap_sta_connect;
void softap_service_start(void);
void softap_service_stop(void);
#endif
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_log.h"
#include "driver/uart.h"
#include "esp_wifi.h"
#include "wifi_service.h"
#include "main_user.h"
static const char *TAG = "wifi_service";
extern void delele_tasks(void);
/*****************************************************
* 首次启动HTTP服务器后, 如果一直没有STA设备加入
* 就不能触发STA disconnect事件,也就不会自动关闭HTTP服务器
* 所以需要额外判断这种情况, 当30秒关闭的定时器触发2次后直接关闭
******************************************************/
static unsigned char http_server_stop_counter = 0;
static unsigned char softap_service_stop_flag = 0;
static unsigned short wifi_service_stop_timer = 0;
wifi_service_t wifi_service_info;
void wifi_service_init(void)
{
wifi_service_stop_timer = 0;
softap_service_stop_flag = 0;
http_server_stop_counter = 0;
wifi_service_info.status = WIFI_SERVICE_STOP;
wifi_service_info.softap_status = SOFTAP_STOP;
wifi_service_info.http_server_status = HTTP_SERVER_STOP;
wifi_service_info.ota_partition = 0;
}
void wifi_service_timer(void)
{
if (wifi_service_info.status == WIFI_SERVICE_START)
{
if (wifi_service_stop_timer < 300)
{
++wifi_service_stop_timer;
}
// 每30秒尝试关闭WiFi服务
if (wifi_service_stop_timer == 300)
{
wifi_service_info.status = WIFI_SERVICE_DEINIT;
}
}
}
void wifi_service_stop_timer_clear(void)
{
wifi_service_stop_timer = 0;
}
void wifi_service(void)
{
if (wifi_service_info.status == WIFI_SERVICE_INIT) // 收到指令: WiFi服务初始化
{
wifi_service_info.status = WIFI_SERVICE_START;
ESP_LOGI(TAG, "---- 开启WiFi服务...\n");
// Bsp_Can_Sleep_Init();
// uart_driver_delete(UART_NUM_1);
// delele_tasks();
softap_service_start();
}
else
{
if (wifi_service_info.status == WIFI_SERVICE_DEINIT) // 收到指令: WiFi服务反初始化, 先读取当前连接的STA数量
{
esp_err_t ret = esp_wifi_ap_get_sta_list(&softap_sta_list);
if (ret == ESP_OK)
{
if (softap_sta_list.num == 0) // 当前没有STA连接
{
if (softap_sta_connect == STA_CONNECTED_NEVER) // 从未有STA接入过
{
if (http_server_stop_counter == 1)
{
softap_service_stop_flag = 1;
}
else
{
ESP_LOGI(TAG, "首次启动HTTP服务器, 1分钟内不会关闭WiFi");
++http_server_stop_counter; // 服务器开启状态且没有设备接入过, 延后30秒再关闭
}
}
else
{
softap_service_stop_flag = 1; // 关闭WiFi服务
}
}
else
{
ESP_LOGI(TAG, "---- 有STA设备在线, 拒绝关闭WiFi");
}
}
else
{
ESP_LOGI(TAG, "---- 读取当前连接的STA数量失败, 打印错误信息");
esp_err_to_name(ret);
}
if (softap_service_stop_flag == 1)
{
wifi_service_info.status = WIFI_SERVICE_STOP;
ESP_LOGI(TAG, "---- 关闭WiFi服务, 开启CAN总线, 重装LIN driver...");
softap_service_stop();
// Bsp_Can_Wakeup_Init();
// bsp_Uart1_Init();
}
else
{
wifi_service_info.status = WIFI_SERVICE_START;
wifi_service_stop_timer = 0; // 重置HTTP服务器关闭的定时器
}
}
}
}
void wifiServiceStart(void)
{
if(wifi_service_info.status == WIFI_SERVICE_STOP)
{
// 开启WiFi服务
wifi_service_info.status = WIFI_SERVICE_INIT;
}
}
\ No newline at end of file
#ifndef _WIFI_SERVICE_H_
#define _WIFI_SERVICE_H_
#include "softap.h"
#define WIFI_SERVICE_STOP 0
#define WIFI_SERVICE_INIT 1
#define WIFI_SERVICE_START 2
#define WIFI_SERVICE_DEINIT 3
typedef struct
{
unsigned char status;
unsigned char softap_status; // 暂时用不上 2024.05.08
unsigned char http_server_status; // 暂时用不上 2024.05.08
unsigned char ota_partition; // 暂时用不上 2024.05.08
} wifi_service_t;
extern wifi_service_t wifi_service_info;
void wifi_service_init(void);
void wifi_service_timer(void);
void wifi_service_stop_timer_clear(void);
void wifi_service(void);
extern void Bsp_Can_Sleep_Init(void);
extern void Bsp_Can_Wakeup_Init(void);
extern void bsp_Uart1_Init(void);
extern void wifiServiceStart(void);
#endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment