状态机-c/c++代码实现

1.五元组信息
(1)初始状态

初始化状态(表示升级处于空闲状态,等待用户下发升级命令)

(2)状态集合:

初始化状态(表示升级处于空闲状态,等待用户下发升级命令)、

准备状态(收到升级命令。进一步的准备处理,校验升级包、读取分区信息等)、

擦除状态(升级准备成功完成,可以开始升级擦除flash)、

写入状态(成功擦除flash,可以开始把升级包内容写入flash中)、

完成状态(写入flash完成,可以进行主备分区切换)、

失败状态(创建配置文件失败、更新版本信息失败、升级包校验不通过、分区信息读取失败、擦除flash失 败、写flash失败、分区切换失败)、

成功状态 (主备分区成功切换,整个升级流程完成)

(3)输入字母表(输入事件)

用户下达升级命令

校验升级包内容

擦除flash设备

升级包写入flash设备

主备分区切换

(4)转移函数

创建系统配置文件失败、读取分区信息失败,则由初始化状态转为失败状态

成功接受到用户升级命令,则由初始化状态转为准备状态

升级包校验失败,则由准备状态转为失败状态

升级包校验成功,则由准备状态转为擦除状态

擦除flash设备失败,则由擦除状态转为失败状态

擦除flash设备成功,则由擦除状态转为写入状态

写入flash设备失败,则由写入状态转为失败状态

写入flash设备成功,则由写入状态转为完成状态

主备分区切换成功,则由完成状态转为成功状态

(5)终止状态集合

失败状态(记录上报升级失败原因)

成功状态(重启,新固件生效)

2.完整代码实现

test.cpp

/*******************************************************************************
 * Copyright (C), 2020-2023, hkzy Co., Ltd.:
 * FileName     :
 * Author       : 王梓涵
 * Description  :
 * Others       :
 * Function List:
 * LastEditTime : 2024-03-08 15:02:46
 * FilePath     : \fsm\.vscode\fsm_test\fsm_test.cpp
******************************************************************************/
#include <iostream>
#include <vector>
#include <malloc.h>
#include <stdio.h>
#include <algorithm>
#include <string>
#include <thread>
#include <chrono>
#include <stdio.h>

#include "test.h"

using namespace std;

static size_t length = 1;

/* 文件隔离 or xml */
//static void set_upgrade_state(int status);/* 数据保存文件中 */
//static void get_upgrade_state(int status);/* 文件中获取数据 */
//
//static void set_upgrade_progress(int progress);/* 数据保存文件中 */
//static void get_upgrade_progress(int progress);/* 文件中获取数据 */
//
//static void set_upgrade_file_name(char* file_name);/* 数据保存文件中 */
//static void get_upgrade_file_name(char* file_name);/* 文件中获取数据 */

//static int get_upgrade_state(int state) //获取状态,包括正常和异常状态
//{
//    //获取当前状态操作
//    state = get_data_json(UPGRADE_FILE_PATH, state); //例如:文件中获取 or xml中获取
//    return state;
//}

/**************************升级状态枚举*******************************/
//typedef enum {
//    UPDATE_INIT,    // 升级初始化状态  
//    UPDATE_PREPARATION, // 升级准备状态
//    UPDATE_ERASING,     // 擦除状态
//    UPDATE_WRITING,     // 写入状态
//    UPDATE_CONPELET     // 完成状态
//    UPDATE_SUCCESS,     // 成功完成
//    UPDATE_FAIL,		// 失败状态
//} upgrade_state_list_e;



/****************************升级状态机 结构体*******************************/
typedef struct {
    upgrade_state_e up_state;                /**< 状态记录       */
    fw_upgrade_init init_interface;          /**< 初始化接口     */
    read_upgrade_state read_state;           /**< 读取当前升级状态*/
    upgrade_sys_part_e sys_part;             /**< 系统分区       */
    upgrade_fw_type_e fw_type_e;             /**< 升级固件类型   */
    bool verificationPassed;                 /**< 升级包校验     */
    const char* dev_name;                    /**< 设备flash路径  */
    int upgrade_pogress;                     /**< 升级进度       */
    const char* upgrade_file_name;           /**< 升级包路径名称 */
} io_upgrade_dev_st;

/*************************升级状态机 结构体************************************/

/*****************************************************************
* 创建系统配置文件操作
******************************************************************/
int create_file(std::string file_name)
{
    int tmp;
    printf("请输入1创建成功,其他为创建失败:");
    scanf_s("%d", &tmp, sizeof(tmp), &length);
    if (tmp == 1)
    {
        printf("已创建文件:%s", file_name.c_str());
        return 1;
    }
    else
    {
        printf("error!!!");
        return 0;
    }
}
/*****************************************************************
* 更新版本信息
******************************************************************/
void update_fw_version(std::vector<int> bmc_version_num)
{
    std::cout << "当前固件版本:";
    for (int elem : bmc_version_num) {
        std::cout << elem << ".0";
    }
    std::cout << std::endl;
}

/*****************************************************************
* 固件初始化
******************************************************************/
static void up_init(void)  //初始状态
{
    std::vector<int> bmc_version_num = { FW_VERSION_MAIN, FW_VERSION_SUB }; //固件版本信息
    update_fw_version(bmc_version_num);//更新版本信息(同时把版本信息写入文件中)
    //...........
}

/*****************************************************************
* (文件中或者xml中)获取状态信息
******************************************************************/
static int get_upgrade_state(int state)
{
    //printf("\n读取到的状态为:state = %d", state);
    return state;
}

/*****************************************************************
* 状态机结构体定义
******************************************************************/
static io_upgrade_dev_st dev_ice =
{
    .init_interface = up_init,
    .read_state = get_upgrade_state,
};


/*****************************************************************
* 配置文件是否创建成功
******************************************************************/
int file_exit(std::string file_name)
{
    if (create_file(file_name))
    {
        printf("配置文件存在\n");
        return 0;
    }
    else
    {
        printf("配置文件创建失败\n");
    }
}

/*****************************************************************
* 延时函数
******************************************************************/
static void delay(int seconds)  //延时
{
    std::this_thread::sleep_for(std::chrono::seconds(seconds));
    //printf("延时时间:%d\n", seconds);
    return;
}

/*****************************************************************
* 文件中写入数据
******************************************************************/
void set_data_config(io_upgrade_dev_st* device, std::string file_name)
{
    if (!file_name.empty())
    {
        printf("成功向配置文件中写入数据:%s\n", file_name.c_str());
    }
}
/*****************************************************************
* 读取系统分区信息
******************************************************************/
void read_sys_partment(io_upgrade_dev_st* device)
{
    upgrade_sys_part_e part;
    printf("读取当前运行的分区0为主分区,1为备份分区:");
    scanf_s("%d", &part, sizeof(part), &length);
    device->sys_part = part;
    if (device->sys_part = MAIN_PARAT)
    {
        printf("选择主分区\n");
    }
    else
    {
        printf("选择备份分区\n");
    }
}

/*****************************************************************
* 擦除操作
******************************************************************/
int erase_action(io_upgrade_dev_st* device)
{
    printf("upgrade_file 擦除操作 \n");
    if (device->upgrade_file_name != NULL)
    {
        printf("擦除flash成功\n");
        return 1;
    }
    else
    {
        printf("擦除flash失败\n");
        return 0;
    }
}
int write_action(io_upgrade_dev_st* device)
{
    if (device->upgrade_file_name != NULL)
    {
        printf("写flash成功\n");
        return 1;
    }
    else
    {
        printf("写flash失败\n");
        return 0;
    }
}

/*****************************************************************
* 校验操作
******************************************************************/
bool verify(io_upgrade_dev_st* device, std::string key)
{
    printf("校验通过\n");
    return true;
}

/**********************************************************
*状态改变函数
**********************************************************/
void io_upgrade_change_state(io_upgrade_dev_st* device, upgrade_state_e newstate)
{
    device->up_state = newstate;
    switch (device->up_state)
    {
    case UPDATE_INIT:
        printf("当前状态:启动升级状态\n");
        break;
    case UPDATE_IDLE:
        printf("当前状态:空闲状态\n");
        break;
    case UPDATE_PREPARATION:
        printf("准备状态!\n");
        break;
    case UPDATE_ERASING:
        printf("擦除状态!!\n");
        break;
    case UPDATE_WRITING:
        printf("写状态!!\n");
        break;
    case UPDATE_CONPELET:
        printf("完成状态!!\n");
        break;
    case UPDATE_SUCCESS:
        printf("成功状态!!\n");
        break;
    default:
        printf("error\n");
        break;
    }
    //set_upgrade_state(device->up_state); //状态存入文件中 or 存到xml
    printf("状态存入文件!\n");
}

/**********************************************************
*flash设备选择
**********************************************************/
static void Choose_Dev_Address(io_upgrade_dev_st* device, upgrade_flash_name_e falsh_name)
{
    switch (falsh_name)
    {
    case FLASH_CONFIG:
        device->dev_name = "/dev/mtd4";
        printf("选择/dev/mtd4\n");
        break;
    case FLASH_RO:
        if (device->sys_part == MAIN_PARAT)
        {
            device->dev_name = "/dev/mtd5";  //注:此处字符串应使用宏定义
            printf("选择/dev/mtd5\n");
        }
        else if (device->sys_part == SUB_PART)
        {
            device->dev_name = "/dev/mtd7";
            printf("选择/dev/mtd7\n");
        }
        break;
    case FLASH_RW:
        if (device->sys_part == MAIN_PARAT)
        {
            device->dev_name = "/dev/mtd6";  //注:此处字符串应使用宏定义
            printf("选择/dev/mtd6\n");
        }
        else if (device->sys_part == SUB_PART)
        {
            device->dev_name = "/dev/mtd8";
            printf("选择/dev/mtd8\n");
        }
        break;
    default:
        device->dev_name = NULL;
        printf("choose flash error!");
        break;
    }
}

/**********************************************************
*读取当前系统运行分区
**********************************************************/
int io_upgrade_read_part(io_upgrade_dev_st* device)
{
    Choose_Dev_Address(device, FLASH_CONFIG); // 系统配置文件设备地址
    read_sys_partment(device); //读取分区操作
    if (device->sys_part == MAIN_PARAT || device->sys_part == SUB_PART)
    {
        set_data_config(device, "/home/sys_start.config"); //分区信息写入配置文件
        return 1;
    }
    else
    {
        printf("读取当前系统运行分区失败\n");
        io_upgrade_change_state(device, RET_UP_PARTMENT);
        return 0;
    }
}

/**********************************************************
* 初始化升级功能
**********************************************************/
void io_upgrade_init(io_upgrade_dev_st* device)
{
    if ((device != NULL) && (device->init_interface != NULL))
    {
        /* 初始化 */
        device->init_interface();
        if (!file_exit("/home/sys_start.config") && io_upgrade_read_part(device)) //字符串使用宏定义
        {
            printf("升级初始化成功!\n");
            io_upgrade_change_state(device, UPDATE_INIT);
        }
        else
        {
            printf("创建系统配置文件失败 or 读取分区信息失败!");
            io_upgrade_change_state(device, RET_UP_CONFIG); //状态设置为错误状态
        }
    }
}

/**********************************************************
*切换系统分区
**********************************************************/
void io_upgrade_change_part(io_upgrade_dev_st* device, upgrade_sys_part_e part)
{
    device->sys_part = part;
    printf("主备分区切换\n");
    set_data_config(device, "/home/sys_start.config"); //宏定义
    Choose_Dev_Address(device, FLASH_CONFIG); //设置config 设备地址
    if (write_action(device))
    {
        io_upgrade_change_state(device, UPDATE_SUCCESS); //成功 
    }
    else
    {
        io_upgrade_change_state(device, RET_UP_SW_PART); //失败 
    }
}

/**********************************************************
*解析升级包内容选择升级固件类型
**********************************************************/
void io_upgrade_fw_choose(io_upgrade_dev_st* device)
{
    upgrade_fw_type_e type;
    printf("输入升级的固件类型,选择升级通道1为bmc,2为cpld:");
    scanf_s("%d", &type, sizeof(type), &length);
    device->fw_type_e = type;//解析升级包操作
    device->upgrade_file_name = "/tmp/image-bmc";//解析升级包操作
    //get_upgrade_file_name(device->upgrade_file_name);
    // type = //解析升级包操作
    // switch (type)
    // {
    // case 1:
    //     device->fw_type_e = EXU_BMC;
    //     break;
    // case 2:
    //     device->fw_type_e = EXU_CPLD;
    //     break;
    // case 3:
    // //................
    //     break; 
    // default:
    //     break;
    // }
    //io_upgrade_change_state(device, UPDATE_PREPARATION); //切换为升级准备状态
}

/**********************************************************
*校验升级包内容
**********************************************************/
void io_upgrade_verify_package(io_upgrade_dev_st* device)
{
    device->upgrade_file_name = "";
    /* 校验通过为true 没有则为false */
    device->verificationPassed = verify(device, "publickey");//校验操作
    if (device->verificationPassed == true)
    {
        printf("升级包校验通过!\n");
        io_upgrade_change_state(device, UPDATE_ERASING);
    }
    else
    {
        printf("升级包校验失败!\n");
        io_upgrade_change_state(device, RET_UP_VERIFY_ERR);
    }

}

/**********************************************************
*升级擦除操作
**********************************************************/
int io_upgrade_erase(io_upgrade_dev_st* device)
{
    switch (device->fw_type_e)
    {
    case EXU_BMC:
        Choose_Dev_Address(device, FLASH_RO); //设置ro 设备地址
        if (erase_action(device))
        {
            io_upgrade_change_state(device, UPDATE_WRITING);//设为写入状态
        }
        else
        {
            io_upgrade_change_state(device, RET_UP_ERASE_ERR); //失败
        }
        break;
    case EXU_CPLD:
        /* 升级cpld操作 */
        break;
    default:
        break;
    }
    return 0;
}

/**********************************************************
*异常状态处理
**********************************************************/
void io_upgrade_handle_wrong_state(io_upgrade_dev_st* device)
{
    switch (device->up_state)
    {
    case RET_UP_CONFIG:
        //异常处理1
        printf("系统配置文件错误");  //异常原因日志记录
        break;
    case RET_UP_PARTMENT:
        //异常处理2
        printf("读取分区信息错误");
        break;
    case RET_UP_FILE:
        //异常处理3
        printf("升级文件不存在");
        break;
    case RET_UP_READ_FLASH:
        //异常处理4
        printf("读取系统flash失败");
        break;
    case RET_UP_GET_SOURCE:
        //异常处理5
        printf("获取源文件失败");
        break;
    case RET_UP_VERIFY_ERR:
        //异常处理6
        printf("升级文件校验失败");
        break;
        //................
    default:
        break;
    }
}

/**********************************************************
*升级进度改变
**********************************************************/
void io_upgrade_change_progress(io_upgrade_dev_st* device, int upgrade_pogress)
{
    if (upgrade_pogress >= 0 && upgrade_pogress <= 100)
    {
        device->upgrade_pogress = upgrade_pogress;
        printf("当前升级进度:%d\n", device->upgrade_pogress);
        //set_upgrade_progress(device->upgrade_pogress); //写入文件中
    }
    else
    {
        printf("进度设置失败");
    }
}

/**********************************************************
*升级写入操作
**********************************************************/
int io_upgrade_write(io_upgrade_dev_st* device)
{
    switch (device->fw_type_e)
    {
    case EXU_BMC:
        Choose_Dev_Address(device, FLASH_RO); //设置ro 设备地址
        if (write_action(device))
        {
            io_upgrade_change_state(device, UPDATE_CONPELET);//设为完成状态
        }
        else
        {
            io_upgrade_change_state(device, RET_UP_WRITE_ERR); //失败
        }
        break;
    case EXU_CPLD:
        /* 升级cpld操作 */
        break;
    default:
        break;
    }
    return 0;
}

/**********************************************************
*状态机运行
**********************************************************/
void io_upgrade_loop(io_upgrade_dev_st* device)
{
    int current_state = 0;
    if ((device == NULL))
    {
        return;
    }
    device->read_state(current_state);
    while (1)
    {
        switch (device->up_state)
        {
        case UPDATE_INIT:
            //接收升级命令后
            io_upgrade_change_state(device, UPDATE_PREPARATION);//成功收到命令后转为准备状态
            io_upgrade_change_progress(&dev_ice, 20);
            printf("UPDATE_INIT\n");
            break;
        case UPDATE_PREPARATION:
            io_upgrade_fw_choose(&dev_ice);
            io_upgrade_verify_package(device); //校验
            io_upgrade_change_progress(&dev_ice, 30);
            printf("UPDATE_PREPARATION\n");
            break;
        case UPDATE_ERASING:
            io_upgrade_erase(device);//擦除
            io_upgrade_change_progress(&dev_ice, 55);
            printf("UPDATE_ERASING\n");
            break;
        case UPDATE_WRITING:
            io_upgrade_write(device);//写入
            io_upgrade_change_progress(&dev_ice, 80);
            printf("UPDATE_WRITING\n");
            break;
        case UPDATE_CONPELET:
            if (device->sys_part == MAIN_PARAT)
            {
                io_upgrade_change_part(device, SUB_PART); //主切备
            }
            else
            {
                io_upgrade_change_part(device, MAIN_PARAT); //备切主
            }
            io_upgrade_change_progress(&dev_ice, 90);
            printf("UPDATE_CONPELET\n");
            break;
        case UPDATE_SUCCESS:
            io_upgrade_change_progress(&dev_ice, 100);
            printf("升级成功! UPDATE_SUCCESS\n");
            return;
        default:
            io_upgrade_handle_wrong_state(device); //异常处理,日志上报
            return;
        }
        delay(2); //2s读一次状态
    }

}
/*主函数*/
void main(int argc, char* argv[])
{

    dev_ice.dev_name = (char*)malloc(12 * sizeof(char));
    dev_ice.upgrade_file_name = (char*)malloc(64 * sizeof(char));
    dev_ice.dev_name = 0;
    dev_ice.upgrade_file_name = 0;
    io_upgrade_init(&dev_ice);
    io_upgrade_change_progress(&dev_ice, 10);
    io_upgrade_loop(&dev_ice);
    //int i = 6;
    /*while (i)
    {
        io_upgrade_loop(&dev_ice);
        delay(2);
        i--;
    }*/
}

test.h

#pragma once
#define FW_VERSION_MAIN  1     // Firmware_Revision
#define FW_VERSION_SUB   1

typedef unsigned char guint8;
typedef unsigned short guint16;
typedef unsigned int guint32;
typedef unsigned long long guint64;
typedef signed char gint8;
typedef signed short gint16;
typedef signed int gint32;
typedef signed long long gint64;

typedef void (*fw_upgrade_init)(void);
typedef int (*read_upgrade_state)(int);

typedef enum {
    UPDATE_INIT,          // 升级初始化状态
    UPDATE_SATRT,         // 启动升级功能
    UPDATE_IDLE,          // 升级空闲状态
    UPDATE_PREPARATION,   // 升级准备状态
    UPDATE_ERASING,       // 擦除程序状态
    UPDATE_WRITING,       // 写程序状态
    UPDATE_CONPELET,      // 升级完成
    UPDATE_SUCCESS,       // 升级成功
    RET_UP_CONFIG,        // 系统配置文件错误
    RET_UP_PARTMENT,      // 读取分区信息错误
    RET_UP_FILE,          // 升级文件不存在
    RET_UP_READ_FLASH,    // 读取系统flash失败
    RET_UP_GET_SOURCE,    // 获取源文件失败
    RET_UP_VERIFY_ERR,    // 升级文件校验失败
    RET_UP_ERASE_ERR,     // 擦除分区文件失败
    RET_UP_WRITE_ERR,     // 写文件失败
    RET_UP_SW_PART,       // 分区切换失败
    RET_UP_NPU_NO,        // NPU载板不在位
}upgrade_state_e;

typedef enum {
    NONE_TYPE,
    EXU_BMC,
    EXU_CPLD,
    NPU_CPLD,
    NPU_MCU,
}upgrade_fw_type_e;          //升级固件类型

typedef enum {
    MAIN_PARAT,
    SUB_PART,
    //......
} upgrade_sys_part_e;        //系统分区

typedef enum {
    FLASH_CONFIG,
    FLASH_RO,
    FLASH_RW,
} upgrade_flash_name_e;    //flash设备地址

  • 10
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值