Files
CodeGenerator/sample/param_code_automation.py
2024-11-03 16:58:00 +08:00

932 lines
41 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/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 <stdint.h>
#include <stddef.h>
#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 <stdint.h>
#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 <stddef.h>
#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 <stdint.h>
/* ##### 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()