#!/usr/bin/python3 # -*- coding: utf-8 -*- import openpyxl import os import time import re import sys import getopt STORAGE_DICS = [ ["PARAM_STORE_ADDR", "C1", "存储区域基地址", "D1",], ["PARAM_STORE_NAME", "C2", "存储区域命名", "D2",], ["PARAM_STORE_UNIT", "C3", "存储区域擦写单元", "D3",], ["PARAM_DATA_UNIT", "C4", "存储区域单分区大小", "D4",], ["PARAM_NUM", "C5", "参数个数", "D5",], ["PARAM_RAM", "C6", "是否需要RAM参数对象", "D6",], ["PARAM_STORAGE_TYPE","C7", "存储器类型", "D7",], ["PARAM_FILE_PATH", "C8", "参数文件路径", "D8",], ] class ParamItem(object): ''' 从excel表格中读取到的参数信息体 index:参数索引 DI:参数唯一编码 str_name:参数名称(汉字) name:参数标识符 store_type:参数存储类型 size:参数数据域大小 default_val:参数默认值 local_type:参数本地使用类型 ratio:缩放倍率 min:参数范围-最小值 max:参数范围-最大值 flag:参数标记 check_func:参数修改前的有效性检查函数 updata_func:参数更新后的回调函数 infomation:当前参数注释 offset:当前参数的内存对象偏移 offset_str:当前参数的存储偏移 size_string:参数的数据域大小宏定义 ''' def __init__(self, row): ''' 将excel中的一行数据转换为参数信息体 ''' self.index = row[0].value self.DI = row[1].value self.str_name = row[2].value self.name = row[3].value self.store_type = row[4].value self.size = row[5].value self.default_value = row[6].value self.local_type = row[7].value self.ratio = row[8].value self.min = row[9].value self.max = row[10].value self.flag = row[11].value self.check_func = row[12].value self.updata_func = row[13].value self.infomation = row[14].value self.offset = "" self.offset_str = "" self.size_string = "" def __str__(self): return "%s,\t%s,\t%s,\t%s,\t%s,\t%s,\t%s,\t%s,\t%s,\t%s,\t%s,\t%s,\t%s,\t%s,\t%s"%( self.index, self.DI, self.str_name, self.name, self.store_type, self.size, self.default_value, self.local_type, self.ratio, self.min, self.max, self.flag, self.check_func, self.updata_func, self.infomation) class StorageConfig(object): ''' 读取excel中的所有sheet,将sheet中的数据转换为参数信息结构体 ''' def __init__(self): self.workbook = openpyxl.load_workbook("tools/param_input.xlsx", data_only=True) self.config_set = {} self.param_index = "" for sheet_name in self.workbook.sheetnames: self.config_set[sheet_name] = {} self.config_set[sheet_name]["name"] = sheet_name sheet = self.workbook[sheet_name] self.config_set[sheet_name]["param_storage_addr"] = {sheet["C1"].value:sheet["D1"].value} self.config_set[sheet_name]["param_storage_name"] = {sheet["C2"].value:sheet["D2"].value} self.config_set[sheet_name]["param_storage_unit"] = {sheet["C3"].value:sheet["D3"].value} self.config_set[sheet_name]["param_data_unit"] = {sheet["C4"].value:sheet["D4"].value} self.config_set[sheet_name]["param_num"] = {sheet["C5"].value:sheet["D5"].value} self.config_set[sheet_name]["param_ram"] = {sheet["C6"].value:sheet["D6"].value} self.config_set[sheet_name]["storage_type"] = {sheet["C7"].value:sheet["D7"].value} self.config_set[sheet_name]["file_path_prefix"] = {sheet["C8"].value:sheet["D8"].value} cell_table = sheet["A11":"O%d"%(11+self.config_set[sheet_name]['param_num']["参数个数"])] self.config_set[sheet_name]["param_info_list"] = [] offset = 0 for row_cel in cell_table[1:]: param = ParamItem(row_cel) offset = offset + int(param.size) + 7 #PARAM_INFO_SIZE param.offset = "%s_PARAM_%s_OFFSET"%(sheet_name.upper(), param.name.upper()) param.size_string = "%s_PARAM_%s_SIZE"%(sheet_name.upper(), param.name.upper()) self.config_set[sheet_name]["param_info_list"].append([param,offset]) def data_check(self): for sheet in self.workbook: for item in STORAGE_DICS: if sheet[item[1]].value != item[2]: print(item,sheet[item[1]].value, item[2], "bad file") def __generate_definations(self): '''生成defination.h''' file_name_formate = "param_%s_defination.h" file_title_formate = '''/* * ===================================================================================== * * Filename: param_%s_defination.h * * Description: * * Version: 1.0 * Created: %s * Revision: none * Compiler: gcc * * Author: Autogenerated * Organization: Topscomm * * ===================================================================================== */ #ifndef __PARAM_%s_DEFINATION_H__ #define __PARAM_%s_DEFINATION_H__ #include #include #define %s_PARAM_NUM (%s) ''' file_end_formate = ''' #endif /* ----- #ifndef __PARAM_%s_DEFINATION_H__ ----- */ ''' for key, value in self.config_set.items(): file_name = file_name_formate % key.lower(); ret_str = "" ret_str = ret_str + file_title_formate%(key.lower(), time.strftime("%d/%m/%Y %H:%M:%S"), key.upper(),key.upper(),key.upper(),value["param_num"]["参数个数"]) format_str = "#define {:<50} {}\n" max_line_len = 0 for size_item in value["param_info_list"]: curr_line = key.upper()+"_PARAM_"+size_item[0].name.upper()+"_SIZE" if len(curr_line) > max_line_len : max_line_len = len(curr_line) if size_item[0].store_type == "PARAM_ARRAY": ret_str = ret_str + format_str.format(curr_line, '('+str(size_item[0].size)+')') if size_item[0].store_type == "PARAM_FLOAT": ret_str = ret_str + format_str.format(curr_line, '(sizeof(float))') if size_item[0].store_type == "PARAM_UINT8": ret_str = ret_str + format_str.format(curr_line, '(sizeof(uint8_t))') if size_item[0].store_type == "PARAM_INT8": ret_str = ret_str + format_str.format(curr_line, '(sizeof(int8_t))') if size_item[0].store_type == "PARAM_UINT16": ret_str = ret_str + format_str.format(curr_line, '(sizeof(uint16_t))') if size_item[0].store_type == "PARAM_INT16": ret_str = ret_str + format_str.format(curr_line, '(sizeof(int16_t))') if size_item[0].store_type == "PARAM_UINT32": ret_str = ret_str + format_str.format(curr_line, '(sizeof(uint32_t))') if size_item[0].store_type == "PARAM_INT32": ret_str = ret_str + format_str.format(curr_line, '(sizeof(int32_t))') if size_item[0].store_type == "PARAM_UINT64": ret_str = ret_str + format_str.format(curr_line, '(sizeof(uint64_t))') if size_item[0].store_type == "PARAM_INT64": ret_str = ret_str + format_str.format(curr_line, '(sizeof(int64_t))') if size_item[0].store_type == "PARAM_DOUBLE": ret_str = ret_str + format_str.format(curr_line, '(sizeof(double))') size_item[0].size_string = "%s_PARAM_%s_SIZE"%(key.upper(), size_item[0].name.upper()) ret_str = ret_str + "\n\n" format_str = " {:<%s}/* {} */\n"%(2*max_line_len) ret_str = ret_str + """typedef struct\n{\n""" for size_item in value["param_info_list"]: if size_item[0].store_type == "PARAM_ARRAY": ret_str = ret_str + format_str.format ("uint8_t "+size_item[0].name+"["+size_item[0].size_string+"];", size_item[0].str_name) if size_item[0].store_type == "PARAM_FLOAT": ret_str = ret_str + format_str.format ("float "+size_item[0].name+";", size_item[0].str_name) if size_item[0].store_type == "PARAM_UINT8": ret_str = ret_str + format_str.format ("uint8_t "+size_item[0].name+";", size_item[0].str_name) if size_item[0].store_type == "PARAM_INT8": ret_str = ret_str + format_str.format ("int8_t "+size_item[0].name+";", size_item[0].str_name) if size_item[0].store_type == "PARAM_UINT16": ret_str = ret_str + format_str.format ("uint16_t "+size_item[0].name+";", size_item[0].str_name) if size_item[0].store_type == "PARAM_INT16": ret_str = ret_str + format_str.format ("int16_t "+size_item[0].name+";", size_item[0].str_name) if size_item[0].store_type == "PARAM_UINT32": ret_str = ret_str + format_str.format ("uint32_t "+size_item[0].name+";", size_item[0].str_name) if size_item[0].store_type == "PARAM_INT32": ret_str = ret_str + format_str.format ("int32_t "+size_item[0].name+";", size_item[0].str_name) if size_item[0].store_type == "PARAM_UINT64": ret_str = ret_str + format_str.format ("uint64_t "+size_item[0].name+";", size_item[0].str_name) if size_item[0].store_type == "PARAM_INT64": ret_str = ret_str + format_str.format ("int64_t "+size_item[0].name+";", size_item[0].str_name) if size_item[0].store_type == "PARAM_DOUBLE": ret_str = ret_str + format_str.format ("double "+size_item[0].name+";", size_item[0].str_name) ret_str = ret_str + "} %s_param_t;\n\n"%key.lower() ret_str = ret_str + file_end_formate%(key.upper()) with open("%s/"%self.file_path+file_name, 'w', encoding="utf-8") as f: f.write(ret_str) def __generate_internal_definations(self): '''生成.h''' file_name_formate = "param_%s.h" file_title_formate = '''/* * ===================================================================================== * * Filename: param_%s.h * * Description: * * Version: 1.0 * Created: %s * Revision: none * Compiler: gcc * * Author: Autogenerated * Organization: Topscomm * * ===================================================================================== */ #ifndef __PARAM_%s_H__ #define __PARAM_%s_H__ #include #include "./param_config.h" #include "../param_functional/param_block.h" #include "./param_%s_defination.h" #define %s_PARAM_STORE_ADDR (%s) ''' file_end_formate = ''' #if ENABLE_PARAM_IN_RAM #if ENABLE_PARAM_PRESET typedef struct { %s_param_t preset_table; } update_%s_param_t; #endif #endif extern param_info_table_t %s_PARAM_INFO; #endif /* ----- #ifndef __PARAM_%s_H__ ----- */ ''' for key, value in self.config_set.items(): file_name = file_name_formate%key.lower() ret_str = "" ret_str = ret_str + file_title_formate%(key.lower(), time.strftime("%d/%m/%Y %H:%M:%S"), key.upper(),key.upper(),key.lower(),key.upper(), value["param_storage_addr"]["存储区域基地址"]) format_str = "#define {:<%s} {}\n" index = 0 last_str = "" max_line_len = 0 for size_item in value["param_info_list"]: if max_line_len <= len("%s_PARAM_%s_SIZE"%(key.upper(), size_item[0].name.upper())): max_len_len = len("%s_PARAM_%s_SIZE"%(key.upper(), size_item[0].name.upper())) format_str = format_str%(max_len_len + 5) for size_item in value["param_info_list"]: size_item[0].size_string = "%s_PARAM_%s_SIZE"%(key.upper(), size_item[0].name.upper()) if index == 0: ret_str = ret_str + format_str.format(key.upper()+"_PARAM_"+size_item[0].name.upper()+"_OFFSET", '0') else: ret_str = ret_str + format_str.format(key.upper()+"_PARAM_"+size_item[0].name.upper()+"_OFFSET", last_str) index = index + 1 last_str = ('({:<%s} + {:<%s} + PARAM_INFO_SIZE)' %(2*max_line_len, 3*max_line_len)).format(key.upper()+"_PARAM_"+size_item[0].name.upper()+"_OFFSET", key.upper()+"_PARAM_"+size_item[0].name.upper()+"_SIZE") ret_str = ret_str + "\n" ret_str = ret_str + '''#define %s_PARAM_STORAGE_SIZE\t\t%s\n\n''' % (key.upper(), last_str) ret_str = ret_str + file_end_formate%(key.lower(), key.lower(), key.upper(),key.upper()) with open("%s/"%self.file_path+file_name, 'w', encoding="utf-8") as f: f.write(ret_str) def __generate_infomatin(self): '''生成.c''' file_name_formate = "param_%s.c" file_title_formate = '''/* * ===================================================================================== * * Filename: param_%s.c * * Description: * * Version: 1.0 * Created: %s * Revision: none * Compiler: gcc * * Author: Autogenerated * Organization: Topscomm * * ===================================================================================== */ #include #include "plm_type_def.h" #include "../param_export.h" #include "./param_%s.h" #if ENABLE_PARAM_IN_RAM #if ENABLE_PARAM_PRESET update_%s_param_t g_update_%s_param_info; /*预存参数数据缓冲区 */ #endif %s_param_t g_%s_param_in_ram; /*参数ram缓冲区*/ uint16_t g_check_%s_param_crc[%s_PARAM_NUM]; /*用于记录参数的校验crc结果*/ #endif PARAM_CHANGE_FLAG_E g_%s_param_change_flag[%s_PARAM_NUM]; /*用于记录参数的修改标记*/ const %s_param_t %s_PARAM_DEFAULT_VALUE_TABLE = { ''' file_end_formate = ''' param_info_table_t %s_PARAM_INFO = { #if ENABLE_PARAM_MUTEX .ptr_mutex = &g_param_resouce.param_mutex, #endif .ptr_category_name = %s_REGION_NAME, .ptr_default_value_table = (void*)&%s_PARAM_DEFAULT_VALUE_TABLE, //默认参数值 .ptr_index_table = (void*)%s_PARAM_INDEX_TABLE, //参数索引表 .param_num = %s_PARAM_NUM, //参数个数 .param_data_size = %s_PARAM_STORAGE_SIZE, //数据长度 .param_base_addr = %s_PARAM_STORE_ADDR, //参数存储页地址 #if ENABLE_PARAM_IN_RAM #if ENABLE_PARAM_PRESET .ptr_preset_dataset = (void*)&g_update_%s_param_info.preset_table,//预设参数表 #endif .ptr_param_in_ram = (void*)&g_%s_param_in_ram, //参数ram缓冲区 .ptr_crc_in_ram = g_check_%s_param_crc, //参数crc校验值 #endif .ptr_change_flag = g_%s_param_change_flag, //参数变更标记 .backup_offset = %s, //备份之间的偏移 .idx_min = %s, //参数索引最小值 .idx_max = %s, //参数索引最大值 .ptr_exchange_unit = &g_param_resouce.ptr_param_unit_buff, //参数写入缓冲区 .exchange_size = %s, //按页写入的缓冲区的大小 }; ''' for key, value in self.config_set.items(): file_name = file_name_formate%key.lower() ret_str = "" ret_str = ret_str + file_title_formate%(key.lower(), time.strftime("%d/%m/%Y %H:%M:%S"), key.lower(), key.lower(), key.lower(), key.lower(), key.lower(), key.lower(), key.upper(), key.lower(), key.upper(), key.lower(), key.upper()) format_str = " .{:<20} = {:<40} //{}\n" for size_item in value["param_info_list"]: if size_item[0].store_type == "PARAM_ARRAY": ret_str = ret_str + format_str.format(size_item[0].name, "{"+str(size_item[0].default_value)+"},", size_item[0].str_name) else: ret_str = ret_str + format_str.format(size_item[0].name, str(size_item[0].default_value)+",", size_item[0].str_name) ret_str = ret_str + "};\n\n\n" ret_str = ret_str + "const param_info_t %s_PARAM_INDEX_TABLE[%s_PARAM_NUM] =\n{\n"%(key.upper(),key.upper()) format_str = "{:<40} {:<30} {:<30} {:<30} {:<40} {:<50} {:<20} {:<20} {:<20} {:<30} {:<30} {:<40}\n" for size_item in value["param_info_list"]: ret_str = ret_str + format_str.format(" {.idx=PARA_IDX_%s"%size_item[0].name.upper()+",", ".identity="+str(size_item[0].DI)+",", ".store_type="+size_item[0].store_type+",", ".local_type="+str(size_item[0].local_type)+",", ".size="+size_item[0].size_string+",", ".offset="+"offsetof(%s_param_t, %s)"%(key.lower(),size_item[0].name)+",", ".ratio="+str(size_item[0].ratio)+",", ".min="+str(size_item[0].min)+",", ".max="+str(size_item[0].max)+",", ".check_func="+size_item[0].check_func+",", ".update_func="+size_item[0].updata_func+",},", "//"+size_item[0].str_name) ret_str = ret_str + "};\n\n\n" file_end = file_end_formate % (key.upper(), key.upper(),key.upper(),key.upper(),key.upper(),key.upper(),key.upper(),key.lower(),key.lower(),key.lower(),key.lower(), value["param_data_unit"]["存储区域单分区大小"], "PARA_IDX_%s"%value["param_info_list"][0][0].name.upper(), "PARA_IDX_%s"%value["param_info_list"][value['param_num']["参数个数"]-1][0].name.upper(), value["param_storage_unit"]["存储区域擦写单元"]) ret_str = ret_str + file_end with open("%s/"%self.file_path+file_name, 'w', encoding="utf-8") as f: f.write(ret_str) def __generate_export(self): '''生成interface.h的部分内容''' file_title_formate = '''/* * ===================================================================================== * * Filename: param_defination.h * * Description: * * Version: 1.0 * Created: %s * Revision: none * Compiler: gcc * * Author: Autogenerated * Organization: Topscomm * * ===================================================================================== */ #ifndef __PARAM_DEFINATION_H__ #define __PARAM_DEFINATION_H__ #include /* ##### LOCAL INCLUDES #################################################### */ ''' file_title_formate = file_title_formate%(time.strftime("%d/%m/%Y %H:%M:%S")) for t_item in self.config_set.items(): file_title_formate = file_title_formate + '#include {:<55} {}\n'.format('"param_defination/param_%s_defination.h"'%t_item[0].lower(), "/* %s参数个数及参数数据域大小 */" % t_item[0]) file_title_formate = file_title_formate + "\n/* ##### EXPORTED MACROS ######################################################## */\n" ret_str = file_title_formate for key, value in self.config_set.items(): ret_str = ret_str + "#define {:<25} {:<30} /* {}存储区域名 */\n".format(key.upper()+"_REGION_NAME", value['param_storage_name']['存储区域命名'], key.upper()) category_format = ''' /* ##### EXPORTED DATA TYPES #################################################### */ typedef enum { %s PARAM_CATEGORY_MAX, /*参数表个数*/ }PARAM_CATEGORY_E; /* ---------- end of enum PARAM_CATEGORY_E ---------- */ ''' cat_str = "" for key, value in self.config_set.items(): cat_str = cat_str + "{:<25} /*{}*/\n ".format(key.upper() + "_PARAM,",key) ret_str = ret_str + category_format%cat_str index_format = ''' typedef enum { %s PARA_IDX_MAX, /*参数索引总个数*/ }PARAM_IDX_E; /* ---------- end of enum PARAM_IDX_E ---------- */ ''' index_str = "" for key, value in self.config_set.items(): index_str = index_str + "\n /* %s */\n "%key for size_item in value["param_info_list"]: index_str = index_str + "{:<45} //{}\n ".format("PARA_IDX_"+size_item[0].name.upper()+",", size_item[0].str_name) file_end = ''' #endif /* ----- #ifndef __PARAM_DEFINATION_H__ ----- */ ''' ret_str = ret_str + index_format%index_str + file_end with open("%s/param_defination.h"%self.file_path, 'w', encoding="utf-8") as f: f.write(ret_str) def __generate_storage(self): '''生成param_storage_config.c的部分内容''' file_title_formate = '''/* * ===================================================================================== * * Filename: param_storage_config.c * * Description: * * Version: 1.0 * Created: %s * Revision: none * Compiler: gcc * * Author: Autogenerated * Organization: Topscomm * * ===================================================================================== */ #include "../param_storage/norflash_operation.h" #include "../param_storage/eeprom_operation.h" #include "../param_storage/file_system_operation.h" #include "../param_storage/param_storage.h" #if FILE_SYSTEM_EXIST const char g_param_file_path_prefix[FILE_NAME_MAX_LEN]="%s"; /*存放参数文件的路径前缀*/ #define FILE_MAX_LEN (%s) /*文件最大长度*/ #endif /* ##### VARIABLES - LOCAL TO THIS SOURCE FILE ################################ */ static const storage_info_t all_storage_info_table[PARAM_CATEGORY_MAX] = { ''' item_format=''' /* %s */ { .ptr_name = %s_REGION_NAME, .region = %s_PARAM, #if FILE_SYSTEM_EXIST .max_addr = 0+FILE_MAX_LEN - 1, .min_addr = 0, #else .max_addr = %s, .min_addr = %s, #endif .storage_read = %s_read, .storage_write = %s_write, .storage_clean = %s_clean, }, ''' for t_item in self.config_set.items(): file_title_formate = file_title_formate%(time.strftime("%d/%m/%Y %H:%M:%S"),t_item[1]['file_path_prefix']['参数文件路径'],str(t_item[1]['param_data_unit']['存储区域单分区大小'])+ "*3") break for t_item in self.config_set.items(): file_title_formate = file_title_formate + item_format % (t_item[0].upper(),t_item[0].upper(), t_item[0].upper(), str(t_item[1]['param_storage_addr']['存储区域基地址']) + "+" + str(t_item[1]['param_data_unit']['存储区域单分区大小'])+ "*3 - 1", t_item[1]['param_storage_addr']['存储区域基地址'], t_item[1]['storage_type']['存储器类型'], t_item[1]['storage_type']['存储器类型'], t_item[1]['storage_type']['存储器类型']) file_end = ''' }; /* ##### FUNCTION DEFINITIONS - EXPORTED FUNCTIONS ############################ */ /* * === FUNCTION ====================================================================== * Name: param_storage_get_info_table * Description: 获取所有存储区域的汇总表,用于对存储区域进行检索 * ===================================================================================== */ const storage_info_t* param_storage_get_info_table() { return &all_storage_info_table[0]; } /* ----- end of function param_storage_get_info_table ----- */ ''' ret_str = "" ret_str = file_title_formate + file_end with open("%s/param_storage_config.c"%self.file_path, 'w', encoding="utf-8") as f: f.write(ret_str) def generate_code_files(self, path): ''' 实际执行excel转代码,生成.c、.h、defination.h、param_export.h、 ''' self.file_path = path self.__generate_definations() self.__generate_internal_definations() self.__generate_infomatin() self.__generate_export() self.__generate_storage() def gen_param_info(content): items = {} match = re.search(r"offset=offsetof\(.*\)", content) if match != None: group_list = match.group().split("=") items[group_list[0]] = group_list[1].split(", ")[1].strip(')') else: items["offset"] = "" content = content.replace(".offset=offsetof(", "") for item in content.split(","): match = re.search(r"\..*=.*", item) if match != None: key_value = match.group().strip("}").strip(".").split('=') items[key_value[0]] = key_value[1] return items class ParamCategory(object): ''' 用于存储从代码文件中读出的信息 cat_name:业务参数类型名称 base_addr:参数存储的基地址 data_size:参数数据存储的总大小(暂未使用) param_num:当前类型中,参数的个数 backup_offset:备份之间的偏移 param_name_list:标识符列表 param_name_str_list:参数名称列表(汉字) default_value:默认参数字典 index_table:默认索引表 exchange_size:存储区域擦写单元 ''' def __init__(self, cat_name): ''' 初始化代码文件信息,仅传入参数类型名,构造空的参数信息体 ''' self.cat_name = cat_name.upper() self.base_addr = "" self.data_size = 0 self.param_num = 0 self.backup_offset = "" self.param_name_list=[] self.param_name_str_list=[] self.default_value={} self.index_table=[] self.storage_name='' self.exchange_size = "" def __str__(self): ''' 将对象转换为可打印的字符串 ''' ret = "" ret = ret + "cat_name:\t" + self.cat_name + "\n" ret = ret + "storage_name:\t" + self.storage_name + "\n" ret = ret + "base_addr:\t"+ self.base_addr + "\n" ret = ret + "data_size:\t"+ str(self.data_size) + "\n" ret = ret + "param_num:\t"+ str(self.param_num) + "\n" ret = ret + "backup_offset:\t"+ self.backup_offset + "\n" ret = ret + "param_name_list"+ str(self.param_name_list) + "\n" ret = ret + "param_name_str_list"+ str(self.param_name_str_list) + "\n" ret = ret + "default_value"+ str(self.default_value) + "\n" ret = ret + "index_table"+ str(self.index_table) + "\n" ret = ret + "exchange_size:\t"+ self.exchange_size + "\n" return ret class CodeGeneration(object): ''' 将代码文件还原为excel文件 ''' categary_pattern = r'param_[a-z]*\.c' def __find_param_category(self, path): ''' 找到path目录下可被逆向解析的文件,将可解析的文件构造成参数类型 ''' file_list = os.listdir(path) cat_list = [] cat_temp_list = [] for file_item in os.listdir(path): categary_pattern = r'param_[a-z]*\.c' matches = re.search(categary_pattern, file_item) if matches != None : cat_temp_list.append(matches.group()[6:-2]) for cat_idx in cat_temp_list: if "param_"+cat_idx+"_defination.h" in os.listdir(path) and "param_"+cat_idx+".h" in os.listdir(path): cat_list.append(cat_idx) return cat_list def __build_local_info(self, path, cat_name): ''' 读取.h文件,通过.h文件构建存储基地址 ''' with open("%s/param_%s.h"%(path,cat_name.lower()), 'r', encoding="utf-8") as f: param_h = f.read() state = 0 for line in param_h.split('\n'): line.strip() if line.find("_PARAM_STORE_ADDR") != -1: self.categorys[cat_name].base_addr = line.split("(")[1].split(')')[0].strip() def __build_extern_info(self, path, cat_name): ''' 读取_defination.h文件,通过_defination.h文件构建各个参数的数据域大小 ''' with open("%s/param_%s_defination.h"%(path, cat_name.lower()), 'r', encoding="utf-8") as f: param_h = f.read() item_index = 0 state = 0 for line in param_h.split('\n'): line.strip() if line.find("_PARAM_NUM") != -1: self.categorys[cat_name].param_num = int(line.split("(")[1].split(')')[0].strip()) categary_pattern = r'#define.*_SIZE.*\(' matches = re.search(categary_pattern, line) if matches != None : if self.categorys[cat_name].index_table[item_index]['size'] == line.split(' ')[1].split('(')[0].strip() : if line.find("(sizeof(uint8_t))") != -1: self.categorys[cat_name].index_table[item_index]['size'] = 1 elif line.find("(sizeof(int8_t))") != -1: self.categorys[cat_name].index_table[item_index]['size'] = 1 elif line.find("(sizeof(uint16_t))") != -1: self.categorys[cat_name].index_table[item_index]['size'] = 2 elif line.find("(sizeof(int16_t))") != -1: self.categorys[cat_name].index_table[item_index]['size'] = 2 elif line.find("(sizeof(uint32_t))") != -1: self.categorys[cat_name].index_table[item_index]['size'] = 4 elif line.find("(sizeof(int32_t))") != -1: self.categorys[cat_name].index_table[item_index]['size'] = 4 elif line.find("(sizeof(uint64_t))") != -1: self.categorys[cat_name].index_table[item_index]['size'] = 8 elif line.find("(sizeof(int64_t))") != -1: self.categorys[cat_name].index_table[item_index]['size'] = 8 elif line.find("(sizeof(float))") != -1: self.categorys[cat_name].index_table[item_index]['size'] = 4 elif line.find("(sizeof(double))") != -1: self.categorys[cat_name].index_table[item_index]['size'] = 8 else: self.categorys[cat_name].index_table[item_index]['size'] = int(line.split('(')[1].split(')')[0]) item_index = item_index + 1 def __build_list(self, path, cat_name): ''' 读取.c文件,通过.c文件构建各个参数的数据域的名称、名字、各索引项、默认值等 ''' with open("%s/param_%s.c"%(path, cat_name.lower()), 'r', encoding="utf-8") as f: param_h = f.read() state = 0 for line in param_h.split('\n'): line.strip() if line.find(".backup_offset") != -1: self.categorys[cat_name].backup_offset = int(line.split(",")[0].split('=')[1].strip()) if line.find(".exchange_size") != -1: self.categorys[cat_name].exchange_size = int(line.split(",")[0].split('=')[1].strip()) if state == 1 : if line.startswith("};") != True : if line.startswith("{") != True: if line.find("}") == -1: self.categorys[cat_name].default_value[line.split('=')[0].strip().strip(".")] = line.split("=")[1].split(",")[0].strip() self.categorys[cat_name].param_name_str_list.append(line.split(',')[1].strip().strip("/")) else: self.categorys[cat_name].default_value[line.split('=')[0].strip().strip(".")] = line.split("{")[1].split("}")[0] self.categorys[cat_name].param_name_str_list.append(line.split('},')[1].strip().strip("/")) self.categorys[cat_name].param_name_list.append(line.split('=')[0].strip().strip(".")) else: state = 0 if state == 2 : if line.startswith("};") != True : if line.startswith("{") != True: self.categorys[cat_name].index_table.append(gen_param_info(line)) else: state = 0 if line.startswith("const") and line.find("PARAM_DEFAULT_VALUE_TABLE") != -1: state = 1 if line.startswith("const") and line.find("PARAM_INDEX_TABLE") != -1: state = 2 def __build_export(self, path): with open("%s/param_defination.h"%(path), 'r', encoding="utf-8") as f: param_h = f.read() state = 0 for line in param_h.split('\n'): line.strip() if line.find("_REGION_NAME") != -1: self.storage_name_list[line.split("_REGION_NAME")[0].strip().split(' ')[1].lower()] = line.split("_REGION_NAME")[1].strip().split(' ')[0] if line.find("_PARAM,") != -1: self.cat_list.append(line.strip().split(',')[0].split('_')[0].upper()) def __build_storage(self, path): with open("%s/param_storage_config.c"%(path), 'r', encoding="utf-8") as f: param_c = f.read() state = 0 self.storage_type = param_c.split("};")[0].split("all_storage_info_table")[1].split("},")[0].split(".storage_read")[1].split(".storage_write")[0].strip('= ').split("_read")[0] self.file_path_prefix = param_c.split("]=\"")[1].split("\";")[0] def __init__(self, path): ''' 传入路径path,解析路径下的代码文件,找到能够解析成参数类型的三种文件:param_*.h、param_*_defination.h、param_*.c 将找到的可被解析的文件构造成参数类型信息体,并写入到excel文件中。 ''' cat_list = self.__find_param_category(path) self.cat_list = [] self.storage_name_list = {} self.categorys = {} self.storage_type = {} self.__build_export(path) self.__build_storage(path) for cat_name in cat_list: self.categorys[cat_name] = ParamCategory(cat_name) self.__build_list(path, cat_name) self.__build_extern_info(path, cat_name) self.__build_local_info(path, cat_name) def gen_data_file(self): ''' 实际执行将读取到的参数信息写入到xlsx文件中,文件名为"param_output.xlsx" ''' wb = openpyxl.Workbook() wb.remove(wb[wb.sheetnames[0]]) ''' 单元格填充黄色 ''' fill = openpyxl.styles.PatternFill("solid", fgColor="FFFF00") cell_name_list = ["序号", "唯一码(DI、点号等)", "参数名", "参数标识符", "参数存储类型", "参数数据大小(字节数)", "默认值", "对象解析类型", "缩放倍数", "参数最小值", "参数最大值", "参数标记", "参数有效性检查", "参数配置后回调", "注释"] for sheet in codes.cat_list: if sheet not in wb.sheetnames: wb.create_sheet(sheet) wb[sheet]["C1"].value = '存储区域基地址' wb[sheet]["D1"].value = self.categorys[sheet.lower()].base_addr wb[sheet]["C2"].value = '存储区域命名' wb[sheet]["D2"].value = self.storage_name_list[sheet.lower()] wb[sheet]["C3"].value = '存储区域擦写单元' wb[sheet]["D3"].value = self.categorys[sheet.lower()].exchange_size wb[sheet]["C4"].value = '存储区域单分区大小' wb[sheet]["D4"].value = self.categorys[sheet.lower()].backup_offset wb[sheet]["C5"].value = '参数个数' wb[sheet]["D5"].value = self.categorys[sheet.lower()].param_num wb[sheet]["C6"].value = '是否需要RAM参数对象' wb[sheet]["D6"].value = 'true/false' wb[sheet]["C7"].value = '存储器类型' wb[sheet]["D7"].value = self.storage_type wb[sheet]["C8"].value = '参数文件路径' wb[sheet]["D8"].value = self.file_path_prefix wb[sheet]["E8"].value = '注释:当存储器类型为fs时,需要填写参数文件路径' ''' 单元格填充黄色 ''' wb[sheet]["C1"].fill = fill wb[sheet]["C2"].fill = fill wb[sheet]["C3"].fill = fill wb[sheet]["C4"].fill = fill wb[sheet]["C5"].fill = fill wb[sheet]["C6"].fill = fill wb[sheet]["C7"].fill = fill wb[sheet]["C8"].fill = fill for i in range(1, 16): wb[sheet].cell(row = 11, column = i, value = cell_name_list[i-1]) wb[sheet].cell(row = 11, column = i).fill = fill for i in range(0, int(self.categorys[sheet.lower()].param_num)): wb[sheet].cell(row = 12+i, column = 1, value = i+1) wb[sheet].cell(row = 12+i, column = 2, value = self.categorys[sheet.lower()].index_table[i]['identity']) wb[sheet].cell(row = 12+i, column = 3, value = self.categorys[sheet.lower()].param_name_str_list[i]) wb[sheet].cell(row = 12+i, column = 4, value = self.categorys[sheet.lower()].param_name_list[i]) wb[sheet].cell(row = 12+i, column = 5, value = self.categorys[sheet.lower()].index_table[i]['store_type']) wb[sheet].cell(row = 12+i, column = 6, value = self.categorys[sheet.lower()].index_table[i]['size']) wb[sheet].cell(row = 12+i, column = 7, value = self.categorys[sheet.lower()].default_value[self.categorys[sheet.lower()].index_table[i]['offset']]) wb[sheet].cell(row = 12+i, column = 8, value = self.categorys[sheet.lower()].index_table[i]['local_type']) wb[sheet].cell(row = 12+i, column = 9, value = self.categorys[sheet.lower()].index_table[i]['ratio']) wb[sheet].cell(row = 12+i, column = 10, value = self.categorys[sheet.lower()].index_table[i]['min']) wb[sheet].cell(row = 12+i, column = 11, value = self.categorys[sheet.lower()].index_table[i]['max']) wb[sheet].cell(row = 12+i, column = 12, value = "0") wb[sheet].cell(row = 12+i, column = 13, value = self.categorys[sheet.lower()].index_table[i]['check_func']) wb[sheet].cell(row = 12+i, column = 14, value = self.categorys[sheet.lower()].index_table[i]['update_func']) wb[sheet].cell(row = 12+i, column = 15, value = "") wb.save("tools/param_output.xlsx") if __name__ == '__main__': try: opts, args = getopt.getopt(sys.argv[1:],"hgr") except getopt.GetoptError: print('param_code_automation.py -h -g -r') sys.exit(2) for opt, arg in opts: if opt == '-h': print('param_code_automation.py -h -g -r') print(' -h for help') print(' -g for generate param code, need param_input.xlsx') print(' -r for generate excel, output file name is param_output.xlsx\n') sys.exit() elif opt in ("-g"): #执行以下代码,从param_input.xlsx生成代码 storage_cofnig = StorageConfig() storage_cofnig.generate_code_files("tools/param_code_generation/param/param_defination") sys.exit() elif opt in ("-r"): ##执行一下代码,从讲代码目录逆向为param_output.xlsx codes = CodeGeneration("param/param_defination") codes.gen_data_file() sys.exit()