+#include "hart.h"
+#include "flash.h"
+#include "convert.h"
+#include "params.h"
-void hart_attribute_params_map(void)
+/**
+ * @brief 填充参数的默认值
+ *
+ * 将给定的 hart_device_variable_t 结构体指针参数填充为默认值。
+ *
+ * @param p hart_device_variable_t 结构体指针
+ */
+static void variable_params_fill_default(hart_device_variable_t *p)
{
-
+ p->value = NULL;
+ p->family = DEVICE_VARIABLE_FAMILY_CODE_6;
+ p->acquisition_period = 200;
+ p->attribute.alarm_selection_code = ALARM_CODE_NOT_USED;
+ p->attribute.transfer_function_code = TRANSMISSION_FUNCTION_CODE_NOT_USED;
+ p->attribute.analog_channel_flags = ANALOG_CHANNEL_CODE_0;
+ p->transducer.upper_and_lower_range_values_units_code = p->units_code;
+ p->status.bits.process_data_status = DEVICE_VARIABLE_STATUS_MANUAL_FIXED;
+ p->trim_point.trim_points = TRIM_POINTS_1; // HART测试必须所有变量都可测试校准点
+ p->trim_point.units_code = p->units_code;
+ osel_memset(p->units_code_allow, DIN_250, HART_VARIABLE_UNITS_ALLOWED_CNT);
+}
+
+static void constant_params_fill_default(hart_device_constant_t *p)
+{
+ p->value = NULL;
+ p->family = DEVICE_VARIABLE_FAMILY_CODE_6;
+}
+
+void hart_long_addr_set(void)
+{
+ hart_storage_variable_t *p = &hart_device_attribute.flash_variable;
+ uint32_t last_three_bytes = dev_serial_num_deal();
+ uint64_t address = (((uint64_t)(p->extended_device_type) << 24) + (uint64_t)(last_three_bytes));
+ uint8_t *address_p = (uint8_t *)&address;
+ uint8_t long_addr[HART_LONG_ADDRESS_LEN];
+ for (uint8_t i = 0; i < HART_LONG_ADDRESS_LEN; i++)
+ {
+ long_addr[i] = address_p[i];
+ }
+ REVERSE_ARRAY(long_addr, HART_LONG_ADDRESS_LEN);
+ p->long_address[0] = HI_UINT16(p->extended_device_type);
+ p->long_address[1] = LO_UINT16(p->extended_device_type);
+ p->long_address[2] = long_addr[2];
+ p->long_address[3] = long_addr[3];
+ p->long_address[4] = long_addr[4];
+}
+
+/**
+ * @brief 初始化HART属性存储
+ *
+ * 初始化HART设备的属性存储,包括销毁旧的存储(如果存在),创建新的存储,并设置读写操作函数。
+ *
+ * @param base_addr 存储的基地址
+ *
+ * @note storage_add_node 添加的顺序必须和数据结构一致,否则会导致整体读取的时候失败
+ */
+void hart_attribute_storage_init(uint32_t base_addr)
+{
+ if (hart_attribute_storage != NULL)
+ {
+ storage_destroy(hart_attribute_storage);
+ }
+ hart_storage_variable_t *p = &hart_device_attribute.flash_variable;
+ DBG_ASSERT(p != NULL __DBG_LINE);
+ hart_attribute_storage = storage_init(base_addr, FM24_PAGE_SIZE);
+ DBG_ASSERT(hart_attribute_storage != NULL __DBG_LINE);
+ hart_attribute_storage->ops.read = eeprom_fm24_read;
+ hart_attribute_storage->ops.write = eeprom_fm24_write;
+
+ storage_add_node(hart_attribute_storage, HPB_INIT_FLAG, sizeof(p->init_flag));
+ storage_add_node(hart_attribute_storage, HPB_POLL_ADDRESS, sizeof(p->poll_address));
+ storage_add_node(hart_attribute_storage, HPB_LONG_ADDRESS, ARRAY_LEN(p->long_address));
+ storage_add_node(hart_attribute_storage, HPB_WRITE_PROTECT_CODE, sizeof(p->write_protect_code));
+ storage_add_node(hart_attribute_storage, HPB_MESSAGE, ARRAY_LEN(p->message));
+ storage_add_node(hart_attribute_storage, HPB_TAG, ARRAY_LEN(p->tag));
+ storage_add_node(hart_attribute_storage, HPB_LONG_TAG, ARRAY_LEN(p->long_tag));
+ storage_add_node(hart_attribute_storage, HPB_DESCRIPTOR, ARRAY_LEN(p->descriptor));
+ storage_add_node(hart_attribute_storage, HPB_DATE, ARRAY_LEN(p->date));
+ storage_add_node(hart_attribute_storage, HPB_FINAL_ASSEMBLY_NUMBER, ARRAY_LEN(p->final_assembly_number));
+ storage_add_node(hart_attribute_storage, HPB_DEVICE_PROFILE, sizeof(p->device_profile));
+ storage_add_node(hart_attribute_storage, HPB_DEVICE_REVISION, sizeof(p->device_revision));
+ storage_add_node(hart_attribute_storage, HPB_DEVICE_SOFTWARE_REVISION, sizeof(p->device_software_revision));
+ storage_add_node(hart_attribute_storage, HPB_S2M_PREAMBLES, sizeof(p->s2m_preambles));
+ storage_add_node(hart_attribute_storage, HPB_EXTENDED_DEVICE_TYPE, sizeof(p->extended_device_type));
+ storage_add_node(hart_attribute_storage, HPB_MANUFACTURER_IDENTIFICATION_CODE, sizeof(p->manufacturer_identification_code));
+ storage_add_node(hart_attribute_storage, HPB_PRIVATE_LABEL_DISTRIBUTOR_CODE, sizeof(p->private_label_distributor_code));
+ storage_add_node(hart_attribute_storage, HPB_DEVICE_HARDWARE_REVISION, sizeof(device_hardware_revision_u));
+ storage_add_node(hart_attribute_storage, HPB_UNIT_DEVICE, sizeof(unit_device_t));
+ storage_add_node(hart_attribute_storage, HPB_COUNTRY_CODE, sizeof(p->country_code));
+ storage_add_node(hart_attribute_storage, HPB_SI_UNITS_CONTROL_CODE, sizeof(p->si_units_control_code));
+ storage_add_node(hart_attribute_storage, HPB_LOOP_CURRENT_MODE, sizeof(p->loop_current_mode));
+ storage_add_node(hart_attribute_storage, HPB_LOCK_CODE, sizeof(p->lock_code));
+ storage_add_node(hart_attribute_storage, HPB_EVENT_MANAGER_REGISTRATION_CONTROL_CODE, sizeof(p->event_manager_registration_control_code));
+ storage_add_node(hart_attribute_storage, HPB_BURST_MESSAGES, ARRAY_LEN(p->burst_messages) * sizeof(burst_message_t));
+ storage_add_node(hart_attribute_storage, HPB_MASTER_CFG_UPDATE_COUNT, sizeof(p->master_cfg_update_count));
+ storage_add_node(hart_attribute_storage, HPB_SLAVE_CFG_UPDATE_COUNT, sizeof(p->slave_cfg_update_count));
+}
+
+/**
+ * @brief 初始化HART变量存储
+ *
+ * 该函数用于初始化HART变量存储,包括销毁旧的存储、初始化新的存储,并设置读写操作函数。
+ *
+ * @param base_addr 存储的基地址
+ */
+void hart_variable_storage_init(uint32_t base_addr)
+{
+ if (hart_variable_storage != NULL)
+ {
+ storage_destroy(hart_variable_storage);
+ }
+ hart_device_variable_t *p = hart_device_attribute.device_variable;
+ DBG_ASSERT(p != NULL __DBG_LINE);
+ hart_variable_storage = storage_init(base_addr, FM24_PAGE_SIZE);
+ DBG_ASSERT(hart_variable_storage != NULL __DBG_LINE);
+ hart_variable_storage->ops.read = eeprom_fm24_read;
+ hart_variable_storage->ops.write = eeprom_fm24_write;
+
+ storage_add_node(hart_variable_storage, DIN_ANALOG_INPUT, sizeof(hart_device_variable_t));
+ storage_add_node(hart_variable_storage, DIN_INTERNAL_TEMPERATURE, sizeof(hart_device_variable_t));
+ storage_add_node(hart_variable_storage, DIN_PRESSURE_PORT_A, sizeof(hart_device_variable_t));
+ storage_add_node(hart_variable_storage, DIN_TRAVEL, sizeof(hart_device_variable_t));
+ storage_add_node(hart_variable_storage, DIN_DRIVE_SIGNAL, sizeof(hart_device_variable_t));
+ storage_add_node(hart_variable_storage, DIN_PRESSURE_PORT_B, sizeof(hart_device_variable_t));
+ storage_add_node(hart_variable_storage, DIN_TRAVEL_SETPOINT, sizeof(hart_device_variable_t));
+ storage_add_node(hart_variable_storage, DIN_DIFFERENTIAL_PRESSURE, sizeof(hart_device_variable_t));
+ storage_add_node(hart_variable_storage, DIN_SUPPLY_PRESSURE, sizeof(hart_device_variable_t));
+ storage_add_node(hart_variable_storage, DIN_IMPLIED_VALVE_POSITION, sizeof(hart_device_variable_t));
+ storage_add_node(hart_variable_storage, DIN_PRIMARY_FEEDBACK, sizeof(hart_device_variable_t));
+}
+
+void hart_standard_variable_storage_init(uint32_t base_addr)
+{
+ if (hart_standard_variable_storage != NULL)
+ {
+ storage_destroy(hart_standard_variable_storage);
+ }
+ hart_device_standard_variable_t *p = hart_device_attribute.device_standard_variable;
+ DBG_ASSERT(p != NULL __DBG_LINE);
+ hart_standard_variable_storage = storage_init(base_addr, FM24_PAGE_SIZE);
+ DBG_ASSERT(hart_standard_variable_storage != NULL __DBG_LINE);
+ hart_standard_variable_storage->ops.read = eeprom_fm24_read;
+ hart_standard_variable_storage->ops.write = eeprom_fm24_write;
+
+ storage_add_node(hart_standard_variable_storage, DIN_242, sizeof(hart_device_standard_variable_t));
+ storage_add_node(hart_standard_variable_storage, DIN_243, sizeof(hart_device_standard_variable_t));
+ storage_add_node(hart_standard_variable_storage, DIN_244, sizeof(hart_device_standard_variable_t));
+ storage_add_node(hart_standard_variable_storage, DIN_245, sizeof(hart_device_standard_variable_t));
+ storage_add_node(hart_standard_variable_storage, DIN_246, sizeof(hart_device_standard_variable_t));
+ storage_add_node(hart_standard_variable_storage, DIN_247, sizeof(hart_device_standard_variable_t));
+ storage_add_node(hart_standard_variable_storage, DIN_248, sizeof(hart_device_standard_variable_t));
+ storage_add_node(hart_standard_variable_storage, DIN_249, sizeof(hart_device_standard_variable_t));
+}
+
+void hart_constant_storage_init(uint32_t base_addr)
+{
+ if (hart_constant_storage != NULL)
+ {
+ storage_destroy(hart_constant_storage);
+ }
+ hart_device_constant_t *p = hart_device_attribute.device_constant;
+ DBG_ASSERT(p != NULL __DBG_LINE);
+ hart_constant_storage = storage_init(base_addr, FM24_PAGE_SIZE);
+ DBG_ASSERT(hart_constant_storage != NULL __DBG_LINE);
+ hart_constant_storage->ops.read = eeprom_fm24_read;
+ hart_constant_storage->ops.write = eeprom_fm24_write;
+
+ storage_add_node(hart_constant_storage, DIN_INST_MODE, sizeof(hart_device_constant_t)); // 仪器模式
+ storage_add_node(hart_constant_storage, DIN_CONTROL_MODE, sizeof(hart_device_constant_t)); // 控制模式
+ storage_add_node(hart_constant_storage, DIN_LEAD_LAG_OPEN, sizeof(hart_device_constant_t)); // 超前滞后上限
+ storage_add_node(hart_constant_storage, DIN_LEAD_LAG_CLOSE, sizeof(hart_device_constant_t)); // 超前滞后下限
+ storage_add_node(hart_constant_storage, DIN_LOOP_PST_ETT, sizeof(hart_device_constant_t)); // 部分行程测试解电至跳闸
+ storage_add_node(hart_constant_storage, DIN_LOW_SUPPLY_ALERT_PT, sizeof(hart_device_constant_t)); // 供应压力下限报警设定值
+ storage_add_node(hart_constant_storage, DIN_INPUT_UNIT, sizeof(hart_device_constant_t)); // 电流单位
+ storage_add_node(hart_constant_storage, DIN_INPUT_RANGE_HI, sizeof(hart_device_constant_t)); // 输入电流上限值
+ storage_add_node(hart_constant_storage, DIN_INPUT_RANGE_LO, sizeof(hart_device_constant_t)); // 输入电流下限值
+ storage_add_node(hart_constant_storage, DIN_LOOP_PST_DETT, sizeof(hart_device_constant_t)); // 部分行程测试充电至跳闸
+ storage_add_node(hart_constant_storage, DIN_INPUT_SPAN, sizeof(hart_device_constant_t)); // 输入电流范围
+ storage_add_node(hart_constant_storage, DIN_INPUT_OFFSET, sizeof(hart_device_constant_t)); // 输入电流偏移
+ storage_add_node(hart_constant_storage, DIN_AUX_INPUT_TYPE, sizeof(hart_device_constant_t)); // 辅助输入类型
+ storage_add_node(hart_constant_storage, DIN_PRESS_UNIT, sizeof(hart_device_constant_t)); // 压力单位
+ storage_add_node(hart_constant_storage, DIN_PRESS_100_PERCENT, sizeof(hart_device_constant_t)); // 压力控制100位置压力值(只用于显示)
+ storage_add_node(hart_constant_storage, DIN_PRESS_0_PERCENT, sizeof(hart_device_constant_t)); // 压力控制0位置压力值(只用于显示)
+ storage_add_node(hart_constant_storage, DIN_PRESS_A_SPAN, sizeof(hart_device_constant_t)); // 压力A口跨度
+ storage_add_node(hart_constant_storage, DIN_PRESS_A_OFFSET, sizeof(hart_device_constant_t)); // 压力A口偏移
+ storage_add_node(hart_constant_storage, DIN_TRAVEL_UNITS, sizeof(hart_device_constant_t)); // 行程单位
+ storage_add_node(hart_constant_storage, DIN_TRAVEL_100_PERCENT, sizeof(hart_device_constant_t)); // 行程控制100位置行程(只用于显示)
+ storage_add_node(hart_constant_storage, DIN_TRAVEL_0_PERCENT, sizeof(hart_device_constant_t)); // 行程控制0位置行程(只用于显示)
+ storage_add_node(hart_constant_storage, DIN_FEEDBACK_CHAR, sizeof(hart_device_constant_t)); // 反馈特性
+ storage_add_node(hart_constant_storage, DIN_POS_SPAN, sizeof(hart_device_constant_t)); // 位置跨度
+ storage_add_node(hart_constant_storage, DIN_POS_OFFSETR, sizeof(hart_device_constant_t)); // 位置偏移
+ storage_add_node(hart_constant_storage, DIN_MINOR_LOOP_SPAN, sizeof(hart_device_constant_t)); // 小回路跨度
+ storage_add_node(hart_constant_storage, DIN_ACCESSORY_FLAGS, sizeof(hart_device_constant_t)); // 附属标志
+ storage_add_node(hart_constant_storage, DIN_CROSS_UNSCALED, sizeof(hart_device_constant_t)); // 磁条反馈原始值,磁条ADC采样值
+ storage_add_node(hart_constant_storage, DIN_SOFT_CUTOFF_RATE_OPEN_UNSCALED, sizeof(hart_device_constant_t)); // 上限软切割速率
+ storage_add_node(hart_constant_storage, DIN_INTEGRAL_LIMIT_UNSCALED, sizeof(hart_device_constant_t)); // 积分限位
+ storage_add_node(hart_constant_storage, DIN_AER_CONFIG, sizeof(hart_device_constant_t)); // 警报记录使能
+ storage_add_node(hart_constant_storage, DIN_XMTR_MODE_FLAGS, sizeof(hart_device_constant_t)); // XMTR模式标志
+ storage_add_node(hart_constant_storage, DIN_XMTR_ENABLE, sizeof(hart_device_constant_t)); // XMTR使能
+ storage_add_node(hart_constant_storage, DIN_XMTR_INSTALLED_POSXMTRSTATE, sizeof(hart_device_constant_t)); // 位置变送器状态
+ storage_add_node(hart_constant_storage, DIN_TVL_DEV_TRIP, sizeof(hart_device_constant_t)); // 行程/压力偏差跳变点
+ storage_add_node(hart_constant_storage, DIN_TVL_DEV_TIME, sizeof(hart_device_constant_t)); // 行程/压力偏差时间
+ storage_add_node(hart_constant_storage, DIN_SIS_OVERRIDE_STATUS, sizeof(hart_device_constant_t)); // 仪表覆盖状态
+ storage_add_node(hart_constant_storage, DIN_SOFT_CUTOFF_RATE_CLOSE_UNSCALED, sizeof(hart_device_constant_t)); // 下限软切割速率
+ storage_add_node(hart_constant_storage, DIN_TRAVEL_CHAR, sizeof(hart_device_constant_t)); // 阀门特性
+ storage_add_node(hart_constant_storage, DIN_TRAVEL_CUTOFF_LIMIT_HI, sizeof(hart_device_constant_t)); // 行程切割限位上限
+ storage_add_node(hart_constant_storage, DIN_TRVEL_CUTOFF_LIMIT_LO, sizeof(hart_device_constant_t)); // 行程切割限位下限
+ storage_add_node(hart_constant_storage, DIN_CUTOFF_LIMIT_SEL, sizeof(hart_device_constant_t)); // 切割限位选择
+ storage_add_node(hart_constant_storage, DIN_AUTOCAL_BTN, sizeof(hart_device_constant_t)); // 自动校准按钮
+ storage_add_node(hart_constant_storage, DIN_RATE_LIMIT_OPEN, sizeof(hart_device_constant_t)); // 行程/压力设定点速率上限
+ storage_add_node(hart_constant_storage, DIN_RATE_LIMIT_CLOSE, sizeof(hart_device_constant_t)); // 行程/压力设定点速率下限
+ storage_add_node(hart_constant_storage, DIN_ZERO_POWER, sizeof(hart_device_constant_t)); // 零功率条件
+ storage_add_node(hart_constant_storage, DIN_TRACEL_PRESS_SEL, sizeof(hart_device_constant_t)); // 行程压力选择
+ storage_add_node(hart_constant_storage, DIN_INVERT_FEEDBACK, sizeof(hart_device_constant_t)); // 反向反馈
+ storage_add_node(hart_constant_storage, DIN_RESERVE_78, sizeof(hart_device_constant_t)); // 保留位
+ storage_add_node(hart_constant_storage, DIN_MINOR_LOOP_NORMAL, sizeof(hart_device_constant_t)); // 小回路正常值
+ storage_add_node(hart_constant_storage, DIN_AUTOCAL_STEP_ID, sizeof(hart_device_constant_t)); // 整定步骤
+ storage_add_node(hart_constant_storage, DIN_RESTART_INST_MODE, sizeof(hart_device_constant_t)); // 重启仪器模式
+ storage_add_node(hart_constant_storage, DIN_COMM_TIMEOUT, sizeof(hart_device_constant_t)); // 通讯超时设置
+ storage_add_node(hart_constant_storage, DIN_TRAVEL_KP_GAIN, sizeof(hart_device_constant_t)); // 行程比例增益
+ storage_add_node(hart_constant_storage, DIN_TRAVEL_KV_GAIN, sizeof(hart_device_constant_t)); // 行程速度增益
+ storage_add_node(hart_constant_storage, DIN_TRAVEL_MLFB_GAIN, sizeof(hart_device_constant_t)); // 行程控制小回路增益
+ storage_add_node(hart_constant_storage, DIN_PRESS_KI_GAIN, sizeof(hart_device_constant_t)); // 压力积分增益
+ storage_add_node(hart_constant_storage, DIN_TRAVEL_KI_GAIN, sizeof(hart_device_constant_t)); // 行程积分增益
+ storage_add_node(hart_constant_storage, DIN_COMP_MODE, sizeof(hart_device_constant_t)); // 积分控制使能
+ storage_add_node(hart_constant_storage, DIN_ACT_STYLE, sizeof(hart_device_constant_t)); // 执行机构类型
+ storage_add_node(hart_constant_storage, DIN_HIGH_SUPPLY_ALERT_PT, sizeof(hart_device_constant_t)); // 供应压力上限报警设置值
+ storage_add_node(hart_constant_storage, DIN_PRESS_B_SPAN, sizeof(hart_device_constant_t)); // 压力B口跨度
+ storage_add_node(hart_constant_storage, DIN_PRESS_B_OFFSET, sizeof(hart_device_constant_t)); // 压力B口偏移
+ storage_add_node(hart_constant_storage, DIN_PRESS_S_SPAN, sizeof(hart_device_constant_t)); // 气源压力跨度
+ storage_add_node(hart_constant_storage, DIN_PRESS_S_OFFSET, sizeof(hart_device_constant_t)); // 气源压力偏移
+ storage_add_node(hart_constant_storage, DIN_PRESS_SETPOINT, sizeof(hart_device_constant_t)); // 目标压力设定值
+ storage_add_node(hart_constant_storage, DIN_PRESS_SENSOR_ENABLE, sizeof(hart_device_constant_t)); // 压力传感器使能
+ storage_add_node(hart_constant_storage, DIN_MSM_6X, sizeof(hart_device_constant_t)); // 更多状态标志
+ storage_add_node(hart_constant_storage, DIN_PRESS_RNG_LO, sizeof(hart_device_constant_t)); // 压力范围下限(起点压力)
+ storage_add_node(hart_constant_storage, DIN_PRESS_RNG_HI, sizeof(hart_device_constant_t)); // 压力范围上限(顶点压力)
+ storage_add_node(hart_constant_storage, DIN_LCP_TRIP_ALERT_SEC, sizeof(hart_device_constant_t)); // LCP通讯跳闸警报时间
+ storage_add_node(hart_constant_storage, DIN_AUTOCAL_STATUS, sizeof(hart_device_constant_t)); // 上次整定结果
+ storage_add_node(hart_constant_storage, DIN_PRESS_KP_GAIN, sizeof(hart_device_constant_t)); // 压力比例增益
+ storage_add_node(hart_constant_storage, DIN_PRESS_RATE, sizeof(hart_device_constant_t)); // 压力速率
+ storage_add_node(hart_constant_storage, DIN_INTEGRAL_DB, sizeof(hart_device_constant_t)); // 积分死区
+ storage_add_node(hart_constant_storage, DIN_LVP_FILTER_SELECTOR, sizeof(hart_device_constant_t)); // 滞后时间
+ storage_add_node(hart_constant_storage, DIN_PRESS_MLFB_GAIN, sizeof(hart_device_constant_t)); // 压力控制小回路增益
+ storage_add_node(hart_constant_storage, DIN_LEAD_LAG_BOOST, sizeof(hart_device_constant_t)); // 超前滞后启动
+ storage_add_node(hart_constant_storage, DIN_SIS_OPT, sizeof(hart_device_constant_t)); // 回路电流确认
+ storage_add_node(hart_constant_storage, DIN_TRIGGER_SENSITIVITY, sizeof(hart_device_constant_t)); // 触发灵敏度
+ storage_add_node(hart_constant_storage, DIN_STROKE_ALERT_EN, sizeof(hart_device_constant_t)); // 行程报警使能/禁止
+ storage_add_node(hart_constant_storage, DIN_PRESS_A_LIMIT, sizeof(hart_device_constant_t)); // 压力A限制
+ storage_add_node(hart_constant_storage, DIN_PST_DEFERRAL_REASON, sizeof(hart_device_constant_t)); // 部分行程测试延期原因
+ storage_add_node(hart_constant_storage, DIN_OUTPUT_PRESS_LIMIT_ENABLE, sizeof(hart_device_constant_t)); // 输出压力限制使能
+ storage_add_node(hart_constant_storage, DIN_BREAKOUT_TIME_ALERT_PT, sizeof(hart_device_constant_t)); // 启动时间报警设定值
+ storage_add_node(hart_constant_storage, DIN_AUTOCAL_SETTLING_TIME, sizeof(hart_device_constant_t)); // 自动校准稳定时间
+ storage_add_node(hart_constant_storage, DIN_TRAVEL_DEV_ALERT_PT, sizeof(hart_device_constant_t)); // 行程控制偏差报警设定值
+ storage_add_node(hart_constant_storage, DIN_TRAVEL_HI_ALERT_PT, sizeof(hart_device_constant_t)); // 行程上限报警设定值
+ storage_add_node(hart_constant_storage, DIN_TRAVEL_LO_ALERT_PT, sizeof(hart_device_constant_t)); // 行程下限报警设定值
+ storage_add_node(hart_constant_storage, DIN_TRAVEL_HIHI_ALERT_PT, sizeof(hart_device_constant_t)); // 行程上限过高报警设定值
+ storage_add_node(hart_constant_storage, DIN_TRAVEL_LOLO_ALERT_PT, sizeof(hart_device_constant_t)); // 行程下限过低报警设定值
+ storage_add_node(hart_constant_storage, DIN_TRAVEL_ALERT_DEADBAND_UNSCALED, sizeof(hart_device_constant_t)); // 所有行程警报死区
+ storage_add_node(hart_constant_storage, DIN_TRAVEL_DEV_ALERT_TIME, sizeof(hart_device_constant_t)); // 行程偏差报警时间
+ storage_add_node(hart_constant_storage, DIN_RST_STROKE_TIME_ALERT_PT, sizeof(hart_device_constant_t)); // 复位时间报警设定值
+ storage_add_node(hart_constant_storage, DIN_DMD_STROKE_TIME_ALERT_PT, sizeof(hart_device_constant_t)); // 行程时间报警设定值
+ storage_add_node(hart_constant_storage, DIN_CYCLE_COUNT_DEADBAND_UNSCALED, sizeof(hart_device_constant_t)); // 周期计数累计死区(Cycle Cnt/Tv Accum Deadband (%))
+ storage_add_node(hart_constant_storage, DIN_CYCLE_COUNT_LIMIT, sizeof(hart_device_constant_t)); // 动作次数报警设定值
+ storage_add_node(hart_constant_storage, DIN_CYCLE_COUNT, sizeof(hart_device_constant_t)); // 动作次数
+ storage_add_node(hart_constant_storage, DIN_TRAVEL_ACCUM_ALERT_PT, sizeof(hart_device_constant_t)); // 累计行程报警设定值
+ storage_add_node(hart_constant_storage, DIN_TRAVEL_ACCUM, sizeof(hart_device_constant_t)); // 累计行程
+ storage_add_node(hart_constant_storage, DIN_PS1_TRIGGER_DB, sizeof(hart_device_constant_t)); // A口压力跳变点
+ storage_add_node(hart_constant_storage, DIN_PS2_TRIGGER_DB, sizeof(hart_device_constant_t)); // B口压力跳变点
+ storage_add_node(hart_constant_storage, DIN_CURRENT_TRIGGER_DB, sizeof(hart_device_constant_t)); // 输入电流跳变点
+ storage_add_node(hart_constant_storage, DIN_MIN_PST_PRESS, sizeof(hart_device_constant_t)); // 部分行程测试最小压力
+ storage_add_node(hart_constant_storage, DIN_MIN_PST_PRESS_TIME, sizeof(hart_device_constant_t)); // 部分行程测试最小压力时间
+ storage_add_node(hart_constant_storage, DIN_PRESS_DEV_ALERT_PT, sizeof(hart_device_constant_t)); // 压力控制偏差报警设定值
+ storage_add_node(hart_constant_storage, DIN_PRESS_DEV_ALERT_TIME, sizeof(hart_device_constant_t)); // 压力偏差报警时间
+ storage_add_node(hart_constant_storage, DIN_MIN_TEMP, sizeof(hart_device_constant_t)); // 温度范围下限
+ storage_add_node(hart_constant_storage, DIN_MAX_TEMP, sizeof(hart_device_constant_t)); // 温度范围上限
+ storage_add_node(hart_constant_storage, DIN_RUN_TIME, sizeof(hart_device_constant_t)); // 设备工作时长
+ storage_add_node(hart_constant_storage, DIN_POWER_UPS, sizeof(hart_device_constant_t)); // 设备上电次数
+ storage_add_node(hart_constant_storage, DIN_XMTR_STATUS, sizeof(hart_device_constant_t)); // XMTR状态
+ storage_add_node(hart_constant_storage, DIN_SERVO_OUTPUT_BIAS, sizeof(hart_device_constant_t)); // 伺服偏差输出
+ storage_add_node(hart_constant_storage, DIN_MANUAL_LOADER, sizeof(hart_device_constant_t)); // 手动加载
+ storage_add_node(hart_constant_storage, DIN_DEF_SETPT_UNSCALED, sizeof(hart_device_constant_t)); // 默认设定点
+ storage_add_node(hart_constant_storage, DIN_RESTART_CTRL_MODE, sizeof(hart_device_constant_t)); // 重新启动控制模式
+ storage_add_node(hart_constant_storage, DIN_SELFTEST_SHUTDOWN, sizeof(hart_device_constant_t)); // 停机自检
+ storage_add_node(hart_constant_storage, DIN_DRIVE_RAW, sizeof(hart_device_constant_t)); // 原始驱动
+ storage_add_node(hart_constant_storage, DIN_TEMP_UNIT, sizeof(hart_device_constant_t)); // 温度单位
+ storage_add_node(hart_constant_storage, DIN_CROSSOVER_OUT, sizeof(hart_device_constant_t)); // 变化点(与行程有关)
+ storage_add_node(hart_constant_storage, DIN_BURST_MODE, sizeof(hart_device_constant_t)); // 突发模式
+ storage_add_node(hart_constant_storage, DIN_POLLING_ADDR, sizeof(hart_device_constant_t)); // 轮询地址
+ storage_add_node(hart_constant_storage, DIN_SVT_ENABLE_FLAG, sizeof(hart_device_constant_t)); // SVT使能标志
+ storage_add_node(hart_constant_storage, DIN_SVT_ALERT_EN, sizeof(hart_device_constant_t)); // SVT报警使能/禁用
+ storage_add_node(hart_constant_storage, DIN_SVT_TRIP_PRESS_ALERT_PT, sizeof(hart_device_constant_t)); // SVT跳闸压力报警设定值
+ storage_add_node(hart_constant_storage, DIN_SVT_RECOVERY_PRESS_ALERT_PT, sizeof(hart_device_constant_t)); // SVT恢复压力报警设定值
+
+ // 自定义部分
+ storage_add_node(hart_constant_storage, DIN_AUTO_TUNING_ERR_CODE, sizeof(hart_device_constant_t)); // 自动整定错误代码
+ storage_add_node(hart_constant_storage, DIN_PART_TRAVEL_ENABLE, sizeof(hart_device_constant_t)); // 部分行程使能
+ storage_add_node(hart_constant_storage, DIN_PART_TRAVEL_LOWER, sizeof(hart_device_constant_t)); // 部分行程下限
+ storage_add_node(hart_constant_storage, DIN_PART_TRAVEL_UPPER, sizeof(hart_device_constant_t)); // 部分行程上限
+ storage_add_node(hart_constant_storage, DIN_OUTPUT_SPAN, sizeof(hart_device_constant_t)); // 输入电流范围(预留暂时不使用)
+ storage_add_node(hart_constant_storage, DIN_OUTPUT_OFFSET, sizeof(hart_device_constant_t)); // 输入电流偏移
+ storage_add_node(hart_constant_storage, DIN_DEVICE_TYPE, sizeof(hart_device_constant_t)); // 设备类型 GPS2000/GPS3000
+}
+
+void burst_params_map(void)
+{
+ osel_memset((uint8_t *)&hart_device_attribute.flash_variable.burst_messages, 0, ARRAY_LEN(hart_device_attribute.flash_variable.burst_messages) * sizeof(burst_message_t));
+ burst_message_t *burst_p = hart_device_attribute.flash_variable.burst_messages;
+ burst_message_t *p = osel_mem_alloc(sizeof(burst_message_t));
+ DBG_ASSERT(burst_p != NULL __DBG_LINE);
+ DBG_ASSERT(p != NULL __DBG_LINE);
+ // 初始化数组
+ for (uint8_t i = 0; i < HART_SOLT_DEVICE_VARIABLE_LEN; i++)
+ {
+ p->code = DIN_250;
+ osel_memcpy((uint8_t *)&burst_p[i], (uint8_t *)p, sizeof(burst_message_t));
+ }
+
+ // 暂时不用赋初值,后面有需要再添加
+ osel_mem_free(p);
+}
+
+/**
+ * @brief 映射变量地址
+ * @return {*}
+ * @note 定义该接口方便从存储中读取数据后重新将变量地址赋值
+ */
+void hart_attribute_params_map_address_update(void)
+{
+ BOOL ret = FALSE;
+ hart_device_variable_t *pv = NULL;
+ hart_device_constant_t *pc = NULL;
+ /**************************变量***************************************** */
+ pv = get_device_variable(DIN_ANALOG_INPUT); // 输入电流
+ pv->value = &rt_data.loop_current;
+
+ pv = get_device_variable(DIN_INTERNAL_TEMPERATURE); // 温度
+ pv->value = &rt_data.temperature;
+
+ pv = get_device_variable(DIN_PRESSURE_PORT_A); // A路压力
+ pv->value = &rt_data.pressure_a;
+
+ pv = get_device_variable(DIN_TRAVEL); // 阀门行程(实际行程)
+ pv->value = &rt_data.actual_travel;
+
+ pv = get_device_variable(DIN_DRIVE_SIGNAL); // 驱动信号(百分比)
+ pv->value = &rt_data.driver_signal;
+
+ pv = get_device_variable(DIN_PRESSURE_PORT_B); // B路压力
+ pv->value = &rt_data.pressure_b;
+
+ pv = get_device_variable(DIN_TRAVEL_SETPOINT); // 阀门设置点
+ pv->value = &rt_save.travel_set_pt;
+
+ pv = get_device_variable(DIN_DIFFERENTIAL_PRESSURE); // 压力A减压力B
+ pv->value = &rt_data.pressure_cross_point;
+
+ pv = get_device_variable(DIN_SUPPLY_PRESSURE); // 供气压力
+ pv->value = &rt_data.pressure_s;
+
+ pv = get_device_variable(DIN_IMPLIED_VALVE_POSITION); // 行程设置点
+ pv->value = &rt_data.target_travel;
+
+ pv = get_device_variable(DIN_PRIMARY_FEEDBACK); // 伺服反馈(和实际行程的值一样)
+ pv->value = &rt_data.servo_feedback;
+
+ /**************************常量***************************************** */
+
+ pc = get_device_constant(DIN_FEEDBACK_CHAR); // 反馈特性
+ pc->value = &udevice.feedback_char;
+
+ pc = get_device_constant(DIN_INPUT_UNIT); // 电流单位
+ pc->value = &udevice.input_unit;
+
+ pc = get_device_constant(DIN_PRESS_UNIT); // 压力单位
+ pc->value = &udevice.press_unit;
+
+ pc = get_device_constant(DIN_TEMP_UNIT); // 温度单位
+ pc->value = &udevice.temp_unit;
+
+ pc = get_device_constant(DIN_PRESS_100_PERCENT); // 压力控制100位置压力值(只用于显示)
+ pc->value = &udevice.press_100_percent;
+
+ pc = get_device_constant(DIN_PRESS_0_PERCENT); // 压力控制0位置压力值(只用于显示)
+ pc->value = &udevice.press_0_percent;
+
+ pc = get_device_constant(DIN_TRAVEL_100_PERCENT); // 行程控制100位置行程(只用于显示)
+ pc->value = &udevice.travel_100_percent;
+
+ pc = get_device_constant(DIN_TRAVEL_0_PERCENT); // 行程控制0位置行程(只用于显示)
+ pc->value = &udevice.travel_0_percent;
+
+ pc = get_device_constant(DIN_TRAVEL_CHAR); // 行程特性
+ pc->value = &udevice.travel_char;
+
+ pc = get_device_constant(DIN_ACT_STYLE); // 执行机构类型
+ pc->value = &udevice.act_style;
+
+ pc = get_device_constant(DIN_MSM_6X); // 更多状态标志
+ pc->value = udevice.more_status_mask_6x.data;
+
+ pc = get_device_constant(DIN_SIS_OVERRIDE_STATUS); // 仪表覆盖状态
+ pc->value = &udevice.sis_override_status;
+
+ pc = get_device_constant(DIN_STROKE_ALERT_EN); // 行程报警使能/禁止
+ pc->value = &udevice.demand_stroke_alert_enable;
+
+ pc = get_device_constant(DIN_RST_STROKE_TIME_ALERT_PT); // 复位时间报警设定值
+ pc->value = &udevice.reset_stroke_time_alert_pt;
+
+ pc = get_device_constant(DIN_DMD_STROKE_TIME_ALERT_PT); // 行程时间报警设定值
+ pc->value = &udevice.demand_stroke_time_alert_pt;
+
+ pc = get_device_constant(DIN_BREAKOUT_TIME_ALERT_PT); // 启动时间报警设定值
+ pc->value = &udevice.breakout_time_alert_pt;
+
+ pc = get_device_constant(DIN_HIGH_SUPPLY_ALERT_PT); // 供应压力上限报警设定值
+ pc->value = &udevice.high_supply_alert_pt;
+
+ pc = get_device_constant(DIN_LOW_SUPPLY_ALERT_PT); // 供应压力下限报警设定值
+ pc->value = &udevice.low_supply_alert_pt;
+
+ pc = get_device_constant(DIN_PRESS_DEV_ALERT_PT); // 压力控制偏差报警设定值
+ pc->value = &udevice.press_dev_alert_pt;
+
+ pc = get_device_constant(DIN_TRAVEL_DEV_ALERT_PT); // 行程控制偏差报警设定值
+ pc->value = &udevice.travel_dev_alert_pt;
+
+ pc = get_device_constant(DIN_TRAVEL_HI_ALERT_PT); // 行程上限报警设定值
+ pc->value = &udevice.travel_hi_alert_pt;
+
+ pc = get_device_constant(DIN_TRAVEL_LO_ALERT_PT); // 行程下限报警设定值
+ pc->value = &udevice.travel_lo_alert_pt;
+
+ pc = get_device_constant(DIN_TRAVEL_HIHI_ALERT_PT); // 行程上限过高报警设定值
+ pc->value = &udevice.travel_hihi_alert_pt;
+
+ pc = get_device_constant(DIN_TRAVEL_LOLO_ALERT_PT); // 行程下限过低报警设定值
+ pc->value = &udevice.travel_lolo_alert_pt;
+
+ pc = get_device_constant(DIN_CYCLE_COUNT_LIMIT); // 动作次数报警设定值
+ pc->value = &udevice.cycle_count_limit;
+
+ pc = get_device_constant(DIN_TRAVEL_ACCUM_ALERT_PT); // 累计行程报警设定值
+ pc->value = &udevice.travel_accum_alert_pt;
+
+ pc = get_device_constant(DIN_INST_MODE); // 仪器模式
+ pc->value = &udevice.inst_mode;
+
+ pc = get_device_constant(DIN_CYCLE_COUNT); // 动作次数
+ pc->value = &rt_save.cycle_count;
+
+ pc = get_device_constant(DIN_TRAVEL_ACCUM); // 累计行程
+ pc->value = &rt_save.travel_accum;
+
+ pc = get_device_constant(DIN_TRAVEL_MLFB_GAIN); // 行程控制小回路增益
+ pc->value = &udevice.travel_mlfb_gain;
+
+ pc = get_device_constant(DIN_PRESS_MLFB_GAIN); // 压力控制小回路增益
+ pc->value = &udevice.press_mlfb_gain;
+
+ pc = get_device_constant(DIN_MINOR_LOOP_NORMAL); // 小回路正常值
+ pc->value = &rt_data.minor_loop_normal;
+
+ pc = get_device_constant(DIN_CROSS_UNSCALED); // 磁条反馈原始值,磁条ADC采样值
+ pc->value = &rt_data.crossover_out_u;
+
+ pc = get_device_constant(DIN_TRACEL_PRESS_SEL); // 行程压力选择
+ pc->value = &udevice.travel_press_select;
+
+ pc = get_device_constant(DIN_SIS_OPT); // 停机触发
+ pc->value = &udevice.sis_opt;
+
+ pc = get_device_constant(DIN_PRESS_SETPOINT); // 目标压力设定值
+ pc->value = &rt_save.press_set_pt;
+
+ pc = get_device_constant(DIN_PRESS_RNG_HI); // 压力范围上限(顶点压力)
+ pc->value = &udevice.press_range_hi;
+
+ pc = get_device_constant(DIN_PRESS_RNG_LO); // 压力范围下限(起点压力)
+ pc->value = &udevice.press_range_lo;
+
+ pc = get_device_constant(DIN_MIN_TEMP); // 温度范围下限
+ pc->value = &udevice.min_temp;
+
+ pc = get_device_constant(DIN_MAX_TEMP); // 温度范围上限
+ pc->value = &udevice.max_temp;
+
+ pc = get_device_constant(DIN_RUN_TIME); // 设备工作时长
+ pc->value = &rt_save.hart_run_time_h;
+
+ pc = get_device_constant(DIN_POWER_UPS); // 设备上电次数
+ pc->value = &rt_save.power_on_cnt;
+
+ pc = get_device_constant(DIN_AUTOCAL_STATUS); // 上次整定结果
+ pc->value = &udevice.auto_cal_status;
+
+ pc = get_device_constant(DIN_BURST_MODE);
+ pc->value = &udevice.burst_mode; // 突发模式
+
+ pc = get_device_constant(DIN_XMTR_STATUS);
+ pc->value = &udevice.xmtr_status; // XMTR状态
+
+ pc = get_device_constant(DIN_CONTROL_MODE);
+ pc->value = &udevice.control_mode; // 控制模式
+
+ pc = get_device_constant(DIN_PST_DEFERRAL_REASON);
+ pc->value = &udevice.pst_deferral_reason; // 部分行程测试延期原因
+
+ pc = get_device_constant(DIN_SVT_ALERT_EN);
+ pc->value = &udevice.svt_alert_enable; // SVT报警使能/禁用
+
+ pc = get_device_constant(DIN_SVT_TRIP_PRESS_ALERT_PT);
+ pc->value = &udevice.svt_trip_press_alert_pt; // SVT跳闸压力报警设定值
+
+ pc = get_device_constant(DIN_SVT_RECOVERY_PRESS_ALERT_PT);
+ pc->value = &udevice.svt_recovery_press_alert_pt; // SVT恢复压力报警设定值
+
+ pc = get_device_constant(DIN_ZERO_POWER);
+ pc->value = &udevice.zero_power_condition; // 零功率条件
+
+ pc = get_device_constant(DIN_DEF_SETPT_UNSCALED);
+ pc->value = &udevice.default_setpoint; // 默认设定点
+
+ pc = get_device_constant(DIN_CUTOFF_LIMIT_SEL);
+ pc->value = &udevice.cutoff_limit_select; // 切割限位选择
+
+ pc = get_device_constant(DIN_TRAVEL_CUTOFF_LIMIT_HI);
+ pc->value = &udevice.cutoff_limit_hi; // 行程切割限位上限
+
+ pc = get_device_constant(DIN_TRVEL_CUTOFF_LIMIT_LO);
+ pc->value = &udevice.cutoff_limit_lo; // 行程切割限位下限
+
+ pc = get_device_constant(DIN_MANUAL_LOADER);
+ pc->value = &udevice.manual_loader; // 手动加载
+
+ pc = get_device_constant(DIN_COMM_TIMEOUT);
+ pc->value = &udevice.comm_timeout; // 通讯超时时间
+
+ pc = get_device_constant(DIN_INVERT_FEEDBACK);
+ pc->value = &udevice.invert_feedback; // 反向反馈
+
+ pc = get_device_constant(DIN_TRAVEL_KP_GAIN);
+ pc->value = &udevice.travel_kp; // 行程比例增益
+
+ pc = get_device_constant(DIN_TRAVEL_KV_GAIN);
+ pc->value = &udevice.travel_kv; // 行程速度增益
+
+ pc = get_device_constant(DIN_RESERVE_78);
+ pc->value = &udevice.reserve_78; // 保留位
+
+ pc = get_device_constant(DIN_PRESS_KP_GAIN);
+ pc->value = &udevice.press_kp; // 压力比例增益
+
+ pc = get_device_constant(DIN_PRESS_KI_GAIN);
+ pc->value = &udevice.press_ki; // 压力积分增益
+
+ pc = get_device_constant(DIN_ACCESSORY_FLAGS);
+ pc->value = &udevice.accessory_flags; // 附属标志
+
+ pc = get_device_constant(DIN_COMP_MODE);
+ pc->value = &udevice.comp_mode; // 积分控制使能
+
+ pc = get_device_constant(DIN_PRESS_RATE);
+ pc->value = &udevice.press_rate; // 压力速率
+
+ pc = get_device_constant(DIN_TRAVEL_KI_GAIN);
+ pc->value = &udevice.travel_ki; // 行程积分增益
+
+ pc = get_device_constant(DIN_INTEGRAL_DB);
+ pc->value = &udevice.integral_db; // 积分死区
+
+ pc = get_device_constant(DIN_AUTOCAL_SETTLING_TIME);
+ pc->value = &udevice.autocal_settling_time; // 自动校准稳定时间
+
+ pc = get_device_constant(DIN_XMTR_MODE_FLAGS);
+ pc->value = &udevice.xmtr_mode_flag; // XMTR模式标志
+
+ pc = get_device_constant(DIN_XMTR_ENABLE);
+ pc->value = &udevice.xntr_enable; // XMTR使能
+
+ pc = get_device_constant(DIN_SVT_ENABLE_FLAG);
+ pc->value = &udevice.svt_enable_flag; // SVT使能标志
+
+ pc = get_device_constant(DIN_PRESS_SENSOR_ENABLE);
+ pc->value = &udevice.press_sensor_enable; // 压力传感器使能
+
+ pc = get_device_constant(DIN_LEAD_LAG_OPEN);
+ pc->value = &udevice.lead_lag_open; // 超前滞后上限
+
+ pc = get_device_constant(DIN_LEAD_LAG_CLOSE);
+ pc->value = &udevice.lead_lag_close; // 超前滞后下限
+
+ pc = get_device_constant(DIN_LOOP_PST_ETT);
+ pc->value = &udevice.loop_pst_ett; // 部分行程测试解电至跳闸
+
+ pc = get_device_constant(DIN_LOOP_PST_DETT);
+ pc->value = &udevice.loop_pst_dett; // 部分行程测试充电至跳闸
+
+ pc = get_device_constant(DIN_TVL_DEV_TRIP);
+ pc->value = &udevice.tvl_dev_trip; // 行程/压力偏差跳变点
+
+ pc = get_device_constant(DIN_TVL_DEV_TIME);
+ pc->value = &udevice.tvl_dev_time; // 行程/压力偏差时间
+
+ pc = get_device_constant(DIN_AUTOCAL_BTN);
+ pc->value = &udevice.autocal_btn; // 自动校准按钮
+
+ pc = get_device_constant(DIN_RATE_LIMIT_OPEN);
+ pc->value = &udevice.rate_limit_open; // 行程/压力设定点速率上限
+
+ pc = get_device_constant(DIN_RATE_LIMIT_CLOSE);
+ pc->value = &udevice.rate_limit_close; // 行程/压力设定点速率下限
+
+ pc = get_device_constant(DIN_RESTART_INST_MODE);
+ pc->value = &udevice.restart_inst_mode; // 重启仪器模式
+
+ pc = get_device_constant(DIN_LCP_TRIP_ALERT_SEC);
+ pc->value = &udevice.lcp_trip_alert_sec; // LCP通讯跳闸警报时间
+
+ pc = get_device_constant(DIN_LVP_FILTER_SELECTOR);
+ pc->value = &udevice.lvp_filter_selector; // 滞后时间
+
+ pc = get_device_constant(DIN_LEAD_LAG_BOOST);
+ pc->value = &udevice.lead_lag_boost; // 超前滞后启动
+
+ pc = get_device_constant(DIN_PS1_TRIGGER_DB);
+ pc->value = &udevice.ps1_trigger_db; // A口压力跳变点
+
+ pc = get_device_constant(DIN_PS2_TRIGGER_DB);
+ pc->value = &udevice.ps2_trigger_db; // B口压力跳变点
+
+ pc = get_device_constant(DIN_TRIGGER_SENSITIVITY);
+ pc->value = &udevice.trigger_sensitivity; // 触发灵敏度
+
+ pc = get_device_constant(DIN_TRAVEL_DEV_ALERT_TIME);
+ pc->value = &udevice.travel_dev_alert_time; // 行程偏差报警时间
+
+ pc = get_device_constant(DIN_CURRENT_TRIGGER_DB);
+ pc->value = &udevice.current_trigger_db; // 输入电流跳变点
+
+ pc = get_device_constant(DIN_MIN_PST_PRESS);
+ pc->value = &udevice.min_pst_press; // 部分行程测试最小压力
+
+ pc = get_device_constant(DIN_MIN_PST_PRESS_TIME);
+ pc->value = &udevice.min_pst_press_time; // 部分行程测试最小压力时间
+
+ pc = get_device_constant(DIN_PRESS_DEV_ALERT_TIME);
+ pc->value = &udevice.press_dev_alert_time; // 压力偏差报警时间
+
+ pc = get_device_constant(DIN_RESTART_CTRL_MODE);
+ pc->value = &udevice.restart_ctrl_mode; // 重新启动控制模式
+
+ pc = get_device_constant(DIN_SELFTEST_SHUTDOWN);
+ pc->value = &udevice.selftest_shutdown; // 停机自检
+
+ pc = get_device_constant(DIN_AUX_INPUT_TYPE);
+ pc->value = &udevice.aux_input_type; // 辅助输入类型
+
+ pc = get_device_constant(DIN_POS_SPAN);
+ pc->value = &udevice.pos_span; // 位置跨度
+
+ pc = get_device_constant(DIN_POS_OFFSETR);
+ pc->value = &udevice.pos_offset; // 位置偏移
+
+ pc = get_device_constant(DIN_POLLING_ADDR);
+ pc->value = &udevice.polling_addr; // 轮询地址
+
+ pc = get_device_constant(DIN_SOFT_CUTOFF_RATE_OPEN_UNSCALED);
+ pc->value = &udevice.soft_cutoff_rate_open_unscaled; // 上限软切割速率
+
+ pc = get_device_constant(DIN_SOFT_CUTOFF_RATE_CLOSE_UNSCALED);
+ pc->value = &udevice.soft_cutoff_rate_close_unscaled; // 下限软切割速率
+
+ pc = get_device_constant(DIN_INTEGRAL_LIMIT_UNSCALED);
+ pc->value = &udevice.intergal_limit_unscaled; // 积分限位
+
+ pc = get_device_constant(DIN_AER_CONFIG);
+ pc->value = &udevice.aer_config; // 警报记录使能
+
+ pc = get_device_constant(DIN_OUTPUT_PRESS_LIMIT_ENABLE);
+ pc->value = &udevice.output_press_limit_enable; // 输出压力限制使能
+
+ pc = get_device_constant(DIN_PRESS_A_LIMIT);
+ pc->value = &udevice.press_a_limit; // 压力A限制
+
+ pc = get_device_constant(DIN_TRAVEL_ALERT_DEADBAND_UNSCALED);
+ pc->value = &udevice.travel_alert_deadband_unscaled; // 所有行程警报死区
+
+ pc = get_device_constant(DIN_CYCLE_COUNT_DEADBAND_UNSCALED);
+ pc->value = &udevice.cycle_count_deadband_unscaled; // 周期计数累计死区
+
+ pc = get_device_constant(DIN_TRAVEL_UNITS);
+ pc->value = &udevice.travel_units; // 行程单位
+
+ pc = get_device_constant(DIN_CROSSOVER_OUT);
+ pc->value = &udevice.crossover_out; // 变化点(与行程有关)
+
+ pc = get_device_constant(DIN_DRIVE_RAW);
+ pc->value = &udevice.driver_raw; // 原始驱动
+
+ pc = get_device_constant(DIN_SERVO_OUTPUT_BIAS);
+ pc->value = &udevice.servo_output_bias; // 伺服输出偏差
+
+ pc = get_device_constant(DIN_INPUT_RANGE_HI);
+ pc->value = &udevice.input_range_hi; // 输入电流上限值
+
+ pc = get_device_constant(DIN_INPUT_RANGE_LO);
+ pc->value = &udevice.input_range_lo; // 输入电流下限值
+
+ pc = get_device_constant(DIN_INPUT_OFFSET);
+ pc->value = &udevice.input_offset; // 输入电流偏移
+
+ pc = get_device_constant(DIN_INPUT_SPAN);
+ pc->value = &udevice.input_span; // 输入电流跨度
+
+ pc = get_device_constant(DIN_PRESS_A_OFFSET);
+ pc->value = &udevice.press_a_offset; // A路压力偏移
+
+ pc = get_device_constant(DIN_PRESS_A_SPAN);
+ pc->value = &udevice.press_a_span; // A路压力跨度
+
+ pc = get_device_constant(DIN_PRESS_B_OFFSET);
+ pc->value = &udevice.press_b_offset; // B路压力偏移
+
+ pc = get_device_constant(DIN_PRESS_B_SPAN);
+ pc->value = &udevice.press_b_span; // B路压力跨度
+
+ pc = get_device_constant(DIN_PRESS_S_OFFSET);
+ pc->value = &udevice.press_s_offset; // 气源压力偏移
+
+ pc = get_device_constant(DIN_PRESS_S_SPAN);
+ pc->value = &udevice.press_s_span; // 气源压力跨度
+
+ pc = get_device_constant(DIN_MINOR_LOOP_SPAN);
+ pc->value = &udevice.minor_loop_span; // 小回路跨度
+
+ pc = get_device_constant(DIN_AUTOCAL_STEP_ID);
+ pc->value = &rt_data.tuned_id; // 整定步骤
+
+ pc = get_device_constant(DIN_XMTR_INSTALLED_POSXMTRSTATE);
+ pc->value = &udevice.xmtr_installed_posxmtrstate; // 位置变送器状态
+
+ // 自定义:新增常量
+ pc = get_device_constant(DIN_PART_TRAVEL_ENABLE);
+ pc->value = &udevice.part_travel_enable; // 分程控制使能
+
+ pc = get_device_constant(DIN_PART_TRAVEL_LOWER);
+ pc->value = &udevice.part_travel_lower; // 分程控制下限
+
+ pc = get_device_constant(DIN_PART_TRAVEL_UPPER);
+ pc->value = &udevice.part_travel_upper; // 分程控制上限
+
+ pc = get_device_constant(DIN_OUTPUT_OFFSET);
+ pc->value = &udevice.output_offset; // 输出电流偏移
+
+ pc = get_device_constant(DIN_OUTPUT_SPAN);
+ pc->value = &udevice.output_span; // 输出电流跨度
+
+ pc = get_device_constant(DIN_DEVICE_TYPE);
+ pc->value = &udevice.dev_model; // 设备类型
+
+ /*****************标准变量****************** */
+ // 电池电压
+ ret = copy_device_dynamic_variable(DIN_242, DIN_250);
+ DBG_ASSERT(ret == TRUE __DBG_LINE);
+ // 电池寿命
+ ret = copy_device_dynamic_variable(DIN_243, DIN_250);
+ DBG_ASSERT(ret == TRUE __DBG_LINE);
+
+ // 量程百分比
+ ret = copy_device_dynamic_variable(DIN_244, DIN_TRAVEL_SETPOINT);
+ DBG_ASSERT(ret == TRUE __DBG_LINE);
+ // 回路电流
+ ret = copy_device_dynamic_variable(DIN_245, DIN_ANALOG_INPUT);
+ DBG_ASSERT(ret == TRUE __DBG_LINE);
+ // 主变量默认使用行程设置点
+ ret = copy_device_dynamic_variable(DIN_246, DIN_IMPLIED_VALVE_POSITION);
+ DBG_ASSERT(ret == TRUE __DBG_LINE);
+ // 次要变量默认使用阀门行程
+ ret = copy_device_dynamic_variable(DIN_247, DIN_TRAVEL);
+ DBG_ASSERT(ret == TRUE __DBG_LINE);
+ // 三级变量默认使用压力A
+ ret = copy_device_dynamic_variable(DIN_248, DIN_PRESSURE_PORT_A);
+ DBG_ASSERT(ret == TRUE __DBG_LINE);
+ // 四级变量默认伺服反馈
+ ret = copy_device_dynamic_variable(DIN_249, DIN_ANALOG_INPUT);
+ DBG_ASSERT(ret == TRUE __DBG_LINE);
+}
+
+/**
+ * @brief hart变量和常量映射重置
+ * @return {*}
+ * @note 之后需要调用hart_attribute_params_map_address_update完成变量映射
+ */
+void hart_attribute_params_map_restart(void)
+{
+ BOOL ret = FALSE;
+ uint8_t pv_count = 0;
+ uint8_t pc_count = 0;
+ uint8_t ps_count = 0;
+ uint8_t units_index = 0;
+ hart_device_variable_t *pv = hart_device_attribute.device_variable; // 变量
+ hart_device_constant_t *pc = hart_device_attribute.device_constant; // 常量
+ hart_device_standard_variable_t *ps = hart_device_attribute.device_standard_variable; // 标准变量
+ DBG_ASSERT(pv != NULL __DBG_LINE);
+ DBG_ASSERT(pc != NULL __DBG_LINE);
+ DBG_ASSERT(ps != NULL __DBG_LINE);
+ osel_memset((uint8_t *)hart_device_attribute.device_variable, 0, sizeof(hart_device_variable_t) * HART_DEVICE_VARIABLE_LEN);
+ osel_memset((uint8_t *)hart_device_attribute.device_constant, 0, sizeof(hart_device_constant_t) * HART_DEVICE_CONSTANT_LEN);
+ osel_memset((uint8_t *)hart_device_attribute.device_standard_variable, 0, sizeof(hart_device_constant_t) * HART_DEVICE_STANDARD_VARIABLE_LEN);
+
+ for (uint8_t i = 0; i < HART_DEVICE_VARIABLE_LEN; i++)
+ {
+ hart_device_attribute.device_variable[i].code = DIN_250;
+ }
+
+ for (uint8_t i = 0; i < HART_DEVICE_CONSTANT_LEN; i++)
+ {
+ hart_device_attribute.device_constant[i].code = DIN_250;
+ }
+
+ for (uint8_t i = 0; i < HART_DEVICE_STANDARD_VARIABLE_LEN; i++)
+ {
+ hart_device_attribute.device_standard_variable[i].code = DIN_250;
+ }
+
+ /*****************************变量************************************** */
+
+ // 输入电流
+ pv->code = DIN_ANALOG_INPUT;
+ pv->user_param.len = sizeof(rt_data.loop_current);
+ pv->user_param.type = USER_FLOAT;
+ pv->user_param.access = USER_READ_ONLY;
+ pv->classification = DEVICE_VARIABLE_CLASSIFICATION_CODE_84;
+ pv->units_code = UNITS_CODE_CURRENT_MA;
+ pv->transducer.limits_and_minimum_span_units_code = UNITS_CODE_CURRENT_MA;
+ pv->transducer.upper_limit.f = LOOP_CURRENT_MAX;
+ pv->transducer.lower_limit.f = LOOP_CURRENT_MIN;
+ pv->transducer.minimum_span.f = 1;
+ variable_params_fill_default(pv);
+ units_index = 0;
+ pv->units_code_allow[units_index++] = UNITS_CODE_CURRENT_MA;
+ pv->attribute.analog_channel_flags = ANALOG_CHANNEL_CODE_1; // 输入电流有对外的模拟信号输出
+ pv++;
+ pv_count++;
+
+ // 温度
+ pv->code = DIN_INTERNAL_TEMPERATURE;
+ pv->user_param.len = sizeof(rt_data.temperature);
+ pv->user_param.type = USER_FLOAT;
+ pv->user_param.access = USER_READ_ONLY;
+ pv->classification = DEVICE_VARIABLE_CLASSIFICATION_CODE_64;
+ pv->units_code = UNITS_CODE_TEMPERATURE_CELSIUS;
+ pv->transducer.limits_and_minimum_span_units_code = UNITS_CODE_TEMPERATURE_CELSIUS;
+ pv->transducer.upper_limit.f = TEMP_MAX;
+ pv->transducer.lower_limit.f = TEMP_MIN;
+ pv->transducer.minimum_span.f = 0.1f;
+ variable_params_fill_default(pv);
+ units_index = 0;
+ pv->units_code_allow[units_index++] = UNITS_CODE_TEMPERATURE_CELSIUS;
+ pv->units_code_allow[units_index++] = UNITS_CODE_TEMPERATURE_FAHRENHEIT;
+ pv++;
+ pv_count++;
+
+ // A路压力
+ pv->code = DIN_PRESSURE_PORT_A;
+ pv->user_param.len = sizeof(rt_data.pressure_a);
+ pv->user_param.type = USER_FLOAT;
+ pv->user_param.access = USER_READ_WRITE;
+ pv->classification = DEVICE_VARIABLE_CLASSIFICATION_CODE_65;
+ pv->units_code = UNITS_CODE_PRESSURE_KPA;
+ pv->transducer.limits_and_minimum_span_units_code = UNITS_CODE_PRESSURE_KPA;
+ pv->transducer.upper_limit.f = PRESS_MAX;
+ pv->transducer.lower_limit.f = PRESS_MIN;
+ pv->transducer.minimum_span.f = 0.1f;
+ variable_params_fill_default(pv);
+ units_index = 0;
+ pv->units_code_allow[units_index++] = UNITS_CODE_PRESSURE_KPA;
+ pv->units_code_allow[units_index++] = UNITS_CODE_PRESSURE_PSI;
+ pv->units_code_allow[units_index++] = UNITS_CODE_PRESSURE_BAR;
+ pv->units_code_allow[units_index++] = UNITS_CODE_PRESSURE_KGCM2;
+ pv++;
+ pv_count++;
+
+ // 阀门行程(实际行程)
+ pv->code = DIN_TRAVEL;
+ pv->user_param.len = sizeof(rt_data.actual_travel);
+ pv->user_param.type = USER_FLOAT;
+ pv->user_param.access = USER_READ_ONLY;
+ pv->classification = DEVICE_VARIABLE_CLASSIFICATION_CODE_0;
+ pv->units_code = UNITS_CODE_OTHER_PERCENT;
+ pv->transducer.limits_and_minimum_span_units_code = UNITS_CODE_OTHER_PERCENT;
+ pv->transducer.upper_limit.f = MAX_TARGET_PERCENT;
+ pv->transducer.lower_limit.f = MIN_TARGET_PERCENT;
+ pv->transducer.minimum_span.f = 0.1f;
+ variable_params_fill_default(pv);
+ units_index = 0;
+ pv->units_code_allow[units_index++] = UNITS_CODE_OTHER_PERCENT;
+ pv++;
+ pv_count++;
+
+ // 驱动信号(百分比)
+ pv->code = DIN_DRIVE_SIGNAL;
+ pv->user_param.len = sizeof(rt_data.driver_signal);
+ pv->user_param.type = USER_FLOAT;
+ pv->user_param.access = USER_READ_WRITE;
+ pv->classification = DEVICE_VARIABLE_CLASSIFICATION_CODE_0;
+ pv->units_code = UNITS_CODE_OTHER_PERCENT;
+ pv->transducer.limits_and_minimum_span_units_code = UNITS_CODE_OTHER_PERCENT;
+ pv->transducer.upper_limit.f = 100;
+ pv->transducer.lower_limit.f = 0;
+ pv->transducer.minimum_span.f = 0.1f;
+ variable_params_fill_default(pv);
+ units_index = 0;
+ pv->units_code_allow[units_index++] = UNITS_CODE_OTHER_PERCENT;
+ pv++;
+ pv_count++;
+
+ // B路压力
+ pv->code = DIN_PRESSURE_PORT_B;
+ pv->user_param.len = sizeof(rt_data.pressure_b);
+ pv->user_param.type = USER_FLOAT;
+ pv->user_param.access = USER_READ_WRITE;
+ pv->classification = DEVICE_VARIABLE_CLASSIFICATION_CODE_65;
+ pv->units_code = UNITS_CODE_PRESSURE_KPA;
+ pv->transducer.limits_and_minimum_span_units_code = UNITS_CODE_TEMPERATURE_CELSIUS;
+ pv->transducer.upper_limit.f = PRESS_MAX;
+ pv->transducer.lower_limit.f = PRESS_MIN;
+ pv->transducer.minimum_span.f = 0.1f;
+ variable_params_fill_default(pv);
+ pv->trim_point.trim_points = TRIM_POINTS_1;
+ units_index = 0;
+ pv->units_code_allow[units_index++] = UNITS_CODE_PRESSURE_KPA;
+ pv->units_code_allow[units_index++] = UNITS_CODE_PRESSURE_PSI;
+ pv->units_code_allow[units_index++] = UNITS_CODE_PRESSURE_BAR;
+ pv->units_code_allow[units_index++] = UNITS_CODE_PRESSURE_KGCM2;
+ pv++;
+ pv_count++;
+
+ // 阀门设置点
+ pv->code = DIN_TRAVEL_SETPOINT;
+ pv->user_param.len = sizeof(rt_save.travel_set_pt);
+ pv->user_param.type = USER_FLOAT;
+ pv->user_param.access = USER_READ_WRITE;
+ pv->classification = DEVICE_VARIABLE_CLASSIFICATION_CODE_0;
+ pv->units_code = UNITS_CODE_OTHER_PERCENT;
+ pv->transducer.limits_and_minimum_span_units_code = UNITS_CODE_OTHER_PERCENT;
+ pv->transducer.upper_limit.f = MAX_TARGET_PERCENT;
+ pv->transducer.lower_limit.f = MIN_TARGET_PERCENT;
+ pv->transducer.minimum_span.f = 0.1f;
+ variable_params_fill_default(pv);
+ units_index = 0;
+ pv->units_code_allow[units_index++] = UNITS_CODE_OTHER_PERCENT;
+ pv++;
+ pv_count++;
+
+ // 压力A减压力B
+ pv->code = DIN_DIFFERENTIAL_PRESSURE;
+ pv->user_param.len = sizeof(rt_data.pressure_cross_point);
+ pv->user_param.type = USER_FLOAT;
+ pv->user_param.access = USER_READ_ONLY;
+ pv->classification = DEVICE_VARIABLE_CLASSIFICATION_CODE_0;
+ pv->units_code = UNITS_CODE_OTHER_PERCENT;
+ pv->transducer.limits_and_minimum_span_units_code = UNITS_CODE_OTHER_PERCENT;
+ pv->transducer.upper_limit.f = 100;
+ pv->transducer.lower_limit.f = 0;
+ pv->transducer.minimum_span.f = 0.1f;
+ variable_params_fill_default(pv);
+ units_index = 0;
+ pv->units_code_allow[units_index++] = UNITS_CODE_OTHER_PERCENT;
+ pv++;
+ pv_count++;
+
+ // 供气压力
+ pv->code = DIN_SUPPLY_PRESSURE;
+ pv->user_param.len = sizeof(rt_data.pressure_s);
+ pv->user_param.type = USER_FLOAT;
+ pv->user_param.access = USER_READ_WRITE;
+ pv->classification = DEVICE_VARIABLE_CLASSIFICATION_CODE_65;
+ pv->units_code = UNITS_CODE_PRESSURE_KPA;
+ pv->transducer.limits_and_minimum_span_units_code = UNITS_CODE_TEMPERATURE_CELSIUS;
+ pv->transducer.upper_limit.f = PRESS_MAX;
+ pv->transducer.lower_limit.f = PRESS_MIN;
+ pv->transducer.minimum_span.f = 0.1f;
+ variable_params_fill_default(pv);
+ pv->trim_point.trim_points = TRIM_POINTS_1;
+ units_index = 0;
+ pv->units_code_allow[units_index++] = UNITS_CODE_PRESSURE_KPA;
+ pv->units_code_allow[units_index++] = UNITS_CODE_PRESSURE_PSI;
+ pv->units_code_allow[units_index++] = UNITS_CODE_PRESSURE_BAR;
+ pv->units_code_allow[units_index++] = UNITS_CODE_PRESSURE_KGCM2;
+ pv++;
+ pv_count++;
+
+ // 行程设置点
+ pv->code = DIN_IMPLIED_VALVE_POSITION;
+ pv->user_param.len = sizeof(rt_data.target_travel);
+ pv->user_param.type = USER_FLOAT;
+ pv->user_param.access = USER_READ_ONLY;
+ pv->classification = DEVICE_VARIABLE_CLASSIFICATION_CODE_0;
+ pv->units_code = UNITS_CODE_OTHER_PERCENT;
+ pv->transducer.limits_and_minimum_span_units_code = UNITS_CODE_OTHER_PERCENT;
+ pv->transducer.upper_limit.f = 100;
+ pv->transducer.lower_limit.f = 0;
+ pv->transducer.minimum_span.f = 0.1f;
+ variable_params_fill_default(pv);
+ units_index = 0;
+ pv->units_code_allow[units_index++] = UNITS_CODE_OTHER_PERCENT;
+ pv++;
+ pv_count++;
+
+ // 伺服反馈(和实际行程的值一样,现在会加上系统偏差)
+ pv->code = DIN_PRIMARY_FEEDBACK;
+ pv->user_param.len = sizeof(rt_data.servo_feedback);
+ pv->user_param.type = USER_FLOAT;
+ pv->user_param.access = USER_READ_ONLY;
+ pv->classification = DEVICE_VARIABLE_CLASSIFICATION_CODE_0;
+ pv->units_code = UNITS_CODE_OTHER_PERCENT;
+ pv->transducer.limits_and_minimum_span_units_code = UNITS_CODE_OTHER_PERCENT;
+ pv->transducer.upper_limit.f = 100;
+ pv->transducer.lower_limit.f = 0;
+ pv->transducer.minimum_span.f = 0.1f;
+ variable_params_fill_default(pv);
+ units_index = 0;
+ pv->units_code_allow[units_index++] = UNITS_CODE_OTHER_PERCENT;
+ pv++;
+ pv_count++;
+
+ /*********************************常量***************************************************/
+ // 反馈特性
+ pc->code = DIN_FEEDBACK_CHAR;
+ pc->user_param.len = sizeof(udevice.feedback_char);
+ pc->user_param.type = USER_BYTE;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 电流单位
+ pc->code = DIN_INPUT_UNIT;
+ pc->user_param.len = sizeof(udevice.input_unit);
+ pc->user_param.type = USER_BYTE;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 压力单位
+ pc->code = DIN_PRESS_UNIT;
+ pc->user_param.len = sizeof(udevice.press_unit);
+ pc->user_param.type = USER_BYTE;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 温度单位
+ pc->code = DIN_TEMP_UNIT;
+ pc->user_param.len = sizeof(udevice.temp_unit);
+ pc->user_param.type = USER_BYTE;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 压力控制100位置压力值(只用于显示)
+ pc->code = DIN_PRESS_100_PERCENT;
+ pc->user_param.len = sizeof(udevice.press_100_percent);
+ pc->user_param.type = USER_FLOAT;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 压力控制0位置压力值(只用于显示)
+ pc->code = DIN_PRESS_0_PERCENT;
+ pc->user_param.len = sizeof(udevice.press_0_percent);
+ pc->user_param.type = USER_FLOAT;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 行程控制100位置行程(只用于显示)
+ pc->code = DIN_TRAVEL_100_PERCENT;
+ pc->user_param.len = sizeof(udevice.travel_100_percent);
+ pc->user_param.type = USER_FLOAT;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 行程控制0位置行程(只用于显示)
+ pc->code = DIN_TRAVEL_0_PERCENT;
+ pc->user_param.len = sizeof(udevice.travel_0_percent);
+ pc->user_param.type = USER_FLOAT;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 行程特性
+ pc->code = DIN_TRAVEL_CHAR;
+ pc->user_param.len = sizeof(udevice.travel_char);
+ pc->user_param.type = USER_BYTE;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 执行机构类型
+ pc->code = DIN_ACT_STYLE;
+ pc->user_param.len = sizeof(udevice.act_style);
+ pc->user_param.type = USER_BYTE;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 更多状态标志
+ pc->code = DIN_MSM_6X;
+ pc->value = udevice.more_status_mask_6x.data;
+ pc->user_param.len = ARRAY_LEN(udevice.more_status_mask_6x.data);
+ pc->user_param.type = USER_BYTE;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 仪表覆盖状态
+ pc->code = DIN_SIS_OVERRIDE_STATUS;
+ pc->user_param.len = sizeof(udevice.sis_override_status);
+ pc->user_param.type = USER_BYTE;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 行程报警使能/禁止
+ pc->code = DIN_STROKE_ALERT_EN;
+ pc->user_param.len = sizeof(udevice.demand_stroke_alert_enable);
+ pc->user_param.type = USER_BYTE;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 复位时间报警设定值
+ pc->code = DIN_RST_STROKE_TIME_ALERT_PT;
+ pc->user_param.len = sizeof(udevice.reset_stroke_time_alert_pt);
+ pc->user_param.type = USER_FLOAT;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 行程时间报警设定值
+ pc->code = DIN_DMD_STROKE_TIME_ALERT_PT;
+ pc->user_param.len = sizeof(udevice.demand_stroke_time_alert_pt);
+ pc->user_param.type = USER_FLOAT;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 启动时间报警设定值
+ pc->code = DIN_BREAKOUT_TIME_ALERT_PT;
+ pc->user_param.len = sizeof(udevice.breakout_time_alert_pt);
+ pc->user_param.type = USER_FLOAT;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 供应压力上限报警设定值
+ pc->code = DIN_HIGH_SUPPLY_ALERT_PT;
+ pc->user_param.len = sizeof(udevice.high_supply_alert_pt);
+ pc->user_param.type = USER_FLOAT;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 供应压力下限报警设定值
+ pc->code = DIN_LOW_SUPPLY_ALERT_PT;
+ pc->user_param.len = sizeof(udevice.low_supply_alert_pt);
+ pc->user_param.type = USER_FLOAT;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 压力控制偏差报警设定值
+ pc->code = DIN_PRESS_DEV_ALERT_PT;
+ pc->user_param.len = sizeof(udevice.press_dev_alert_pt);
+ pc->user_param.type = USER_FLOAT;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 行程控制偏差报警设定值
+ pc->code = DIN_TRAVEL_DEV_ALERT_PT;
+ pc->user_param.len = sizeof(udevice.travel_dev_alert_pt);
+ pc->user_param.type = USER_FLOAT;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 行程上限报警设定值
+ pc->code = DIN_TRAVEL_HI_ALERT_PT;
+ pc->user_param.len = sizeof(udevice.travel_hi_alert_pt);
+ pc->user_param.type = USER_FLOAT;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 行程下限报警设定值
+ pc->code = DIN_TRAVEL_LO_ALERT_PT;
+ pc->user_param.len = sizeof(udevice.travel_lo_alert_pt);
+ pc->user_param.type = USER_FLOAT;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 行程上限过高报警设定值
+ pc->code = DIN_TRAVEL_HIHI_ALERT_PT;
+ pc->user_param.len = sizeof(udevice.travel_hihi_alert_pt);
+ pc->user_param.type = USER_FLOAT;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 行程下限过低报警设定值
+ pc->code = DIN_TRAVEL_LOLO_ALERT_PT;
+ pc->user_param.len = sizeof(udevice.travel_lolo_alert_pt);
+ pc->user_param.type = USER_FLOAT;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 动作次数报警设定值
+ pc->code = DIN_CYCLE_COUNT_LIMIT;
+ pc->user_param.len = sizeof(udevice.cycle_count_limit);
+ pc->user_param.type = USER_UINT32;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 累计行程报警设定值
+ pc->code = DIN_TRAVEL_ACCUM_ALERT_PT;
+ pc->user_param.len = sizeof(udevice.travel_accum_alert_pt);
+ pc->user_param.type = USER_UINT32;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 仪器模式
+ pc->code = DIN_INST_MODE;
+ pc->user_param.len = sizeof(udevice.inst_mode);
+ pc->user_param.type = USER_BYTE;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 动作次数
+ pc->code = DIN_CYCLE_COUNT;
+ pc->user_param.len = sizeof(rt_save.cycle_count);
+ pc->user_param.type = USER_UINT32;
+ pc->user_param.access = USER_READ_ONLY;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 累计行程
+ pc->code = DIN_TRAVEL_ACCUM;
+ pc->user_param.len = sizeof(rt_save.travel_accum);
+ pc->user_param.type = USER_UINT32;
+ pc->user_param.access = USER_READ_ONLY;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 行程控制小回路增益
+ pc->code = DIN_TRAVEL_MLFB_GAIN;
+ pc->user_param.len = sizeof(udevice.travel_mlfb_gain);
+ pc->user_param.type = USER_FLOAT;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 压力控制小回路增益
+ pc->code = DIN_PRESS_MLFB_GAIN;
+ pc->user_param.len = sizeof(udevice.press_mlfb_gain);
+ pc->user_param.type = USER_FLOAT;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 小回路正常值
+ pc->code = DIN_MINOR_LOOP_NORMAL;
+ pc->user_param.len = sizeof(rt_data.minor_loop_normal);
+ pc->user_param.type = USER_WORD;
+ pc->user_param.access = USER_READ_ONLY;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 磁条反馈原始值,磁条ADC采样值
+ pc->code = DIN_CROSS_UNSCALED;
+ pc->user_param.len = sizeof(rt_data.crossover_out_u);
+ pc->user_param.type = USER_WORD;
+ pc->user_param.access = USER_READ_ONLY;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 行程压力选择
+ pc->code = DIN_TRACEL_PRESS_SEL;
+ pc->user_param.len = sizeof(udevice.travel_press_select);
+ pc->user_param.type = USER_BYTE;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 停机触发
+ pc->code = DIN_SIS_OPT;
+ pc->user_param.len = sizeof(udevice.sis_opt);
+ pc->user_param.type = USER_BYTE;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 目标压力设定值
+ pc->code = DIN_PRESS_SETPOINT;
+ pc->user_param.len = sizeof(rt_save.press_set_pt);
+ pc->user_param.type = USER_FLOAT;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 压力范围上限(顶点压力)
+ pc->code = DIN_PRESS_RNG_HI;
+ pc->user_param.len = sizeof(udevice.press_range_hi);
+ pc->user_param.type = USER_FLOAT;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 压力范围下限(起点压力)
+ pc->code = DIN_PRESS_RNG_LO;
+ pc->user_param.len = sizeof(udevice.press_range_lo);
+ pc->user_param.type = USER_FLOAT;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 温度范围下限
+ pc->code = DIN_MIN_TEMP;
+ pc->user_param.len = sizeof(udevice.min_temp);
+ pc->user_param.type = USER_FLOAT;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 温度范围上限
+ pc->code = DIN_MAX_TEMP;
+ pc->user_param.len = sizeof(udevice.max_temp);
+ pc->user_param.type = USER_FLOAT;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 设备工作时长
+ pc->code = DIN_RUN_TIME;
+ pc->user_param.len = sizeof(rt_save.hart_run_time_h);
+ pc->user_param.type = USER_WORD;
+ pc->user_param.access = USER_READ_ONLY;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 设备上电次数
+ pc->code = DIN_POWER_UPS;
+ pc->user_param.len = sizeof(rt_save.power_on_cnt);
+ pc->user_param.type = USER_WORD;
+ pc->user_param.access = USER_READ_ONLY;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 上次整定结果
+ pc->code = DIN_AUTOCAL_STATUS;
+ pc->user_param.len = sizeof(udevice.auto_cal_status);
+ pc->user_param.type = USER_BYTE;
+ pc->user_param.access = USER_READ_ONLY;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 突发模式
+ pc->code = DIN_BURST_MODE;
+ pc->user_param.len = sizeof(udevice.burst_mode);
+ pc->user_param.type = USER_BYTE;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // XMTR状态
+ pc->code = DIN_XMTR_STATUS;
+ pc->user_param.len = sizeof(udevice.xmtr_status);
+ pc->user_param.type = USER_BYTE;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 控制模式
+ pc->code = DIN_CONTROL_MODE;
+ pc->user_param.len = sizeof(udevice.control_mode);
+ pc->user_param.type = USER_BYTE;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 部分行程测试延期原因
+ pc->code = DIN_PST_DEFERRAL_REASON;
+ pc->user_param.len = sizeof(udevice.pst_deferral_reason);
+ pc->user_param.type = USER_BYTE;
+ pc->user_param.access = USER_READ_ONLY;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // SVT报警使能/禁用
+ pc->code = DIN_SVT_ALERT_EN;
+ pc->user_param.len = sizeof(udevice.svt_alert_enable);
+ pc->user_param.type = USER_BYTE;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // SVT跳闸压力报警设定值
+ pc->code = DIN_SVT_TRIP_PRESS_ALERT_PT;
+ pc->user_param.len = sizeof(udevice.svt_trip_press_alert_pt);
+ pc->user_param.type = USER_FLOAT;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // SVT恢复压力报警设定值
+ pc->code = DIN_SVT_RECOVERY_PRESS_ALERT_PT;
+ pc->user_param.len = sizeof(udevice.svt_recovery_press_alert_pt);
+ pc->user_param.type = USER_FLOAT;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 零功率条件
+ pc->code = DIN_ZERO_POWER;
+ pc->user_param.len = sizeof(udevice.zero_power_condition);
+ pc->user_param.type = USER_BYTE;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 默认设定点
+ pc->code = DIN_DEF_SETPT_UNSCALED;
+ pc->user_param.len = sizeof(udevice.default_setpoint);
+ pc->user_param.type = USER_FLOAT;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 切割限位选择
+ pc->code = DIN_CUTOFF_LIMIT_SEL;
+ pc->user_param.len = sizeof(udevice.cutoff_limit_select);
+ pc->user_param.type = USER_BYTE;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 行程切割限位上限
+ pc->code = DIN_TRAVEL_CUTOFF_LIMIT_HI;
+ pc->user_param.len = sizeof(udevice.cutoff_limit_hi);
+ pc->user_param.type = USER_FLOAT;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 行程切割限位下限
+ pc->code = DIN_TRVEL_CUTOFF_LIMIT_LO;
+ pc->user_param.len = sizeof(udevice.cutoff_limit_lo);
+ pc->user_param.type = USER_FLOAT;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 手动加载
+ pc->code = DIN_MANUAL_LOADER;
+ pc->user_param.len = sizeof(udevice.manual_loader);
+ pc->user_param.type = USER_BYTE;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 通讯超时时间
+ pc->code = DIN_COMM_TIMEOUT;
+ pc->user_param.len = sizeof(udevice.comm_timeout);
+ pc->user_param.type = USER_BYTE;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 反向反馈
+ pc->code = DIN_INVERT_FEEDBACK;
+ pc->user_param.len = sizeof(udevice.invert_feedback);
+ pc->user_param.type = USER_BYTE;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 行程比例增益
+ pc->code = DIN_TRAVEL_KP_GAIN;
+ pc->user_param.len = sizeof(udevice.travel_kp);
+ pc->user_param.type = USER_FLOAT;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 行程速度增益
+ pc->code = DIN_TRAVEL_KV_GAIN;
+ pc->user_param.len = sizeof(udevice.travel_kv);
+ pc->user_param.type = USER_FLOAT;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 保留位
+ pc->code = DIN_RESERVE_78;
+ pc->user_param.len = sizeof(udevice.reserve_78);
+ pc->user_param.type = USER_WORD;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 压力比例增益
+ pc->code = DIN_PRESS_KP_GAIN;
+ pc->user_param.len = sizeof(udevice.press_kp);
+ pc->user_param.type = USER_FLOAT;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 压力积分增益
+ pc->code = DIN_PRESS_KI_GAIN;
+ pc->user_param.len = sizeof(udevice.press_ki);
+ pc->user_param.type = USER_FLOAT;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 附属标志
+ pc->code = DIN_ACCESSORY_FLAGS;
+ pc->user_param.len = sizeof(udevice.accessory_flags);
+ pc->user_param.type = USER_BYTE;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 积分控制使能
+ pc->code = DIN_COMP_MODE;
+ pc->user_param.len = sizeof(udevice.comp_mode);
+ pc->user_param.type = USER_BYTE;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 压力速率
+ pc->code = DIN_PRESS_RATE;
+ pc->user_param.len = sizeof(udevice.press_rate);
+ pc->user_param.type = USER_FLOAT;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 行程积分增益
+ pc->code = DIN_TRAVEL_KI_GAIN;
+ pc->user_param.len = sizeof(udevice.travel_ki);
+ pc->user_param.type = USER_FLOAT;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 积分死区
+ pc->code = DIN_INTEGRAL_DB;
+ pc->user_param.len = sizeof(udevice.integral_db);
+ pc->user_param.type = USER_FLOAT;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 自动校准稳定时间
+ pc->code = DIN_AUTOCAL_SETTLING_TIME;
+ pc->user_param.len = sizeof(udevice.autocal_settling_time);
+ pc->user_param.type = USER_BYTE;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // XMTR模式标志
+ pc->code = DIN_XMTR_MODE_FLAGS;
+ pc->user_param.len = sizeof(udevice.xmtr_mode_flag);
+ pc->user_param.type = USER_BYTE;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // XMTR使能
+ pc->code = DIN_XMTR_ENABLE;
+ pc->user_param.len = sizeof(udevice.xntr_enable);
+ pc->user_param.type = USER_BYTE;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // SVT使能标志
+ pc->code = DIN_SVT_ENABLE_FLAG;
+ pc->user_param.len = sizeof(udevice.svt_enable_flag);
+ pc->user_param.type = USER_BYTE;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 压力传感器使能
+ pc->code = DIN_PRESS_SENSOR_ENABLE;
+ pc->user_param.len = sizeof(udevice.press_sensor_enable);
+ pc->user_param.type = USER_BYTE;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 超前滞后上限
+ pc->code = DIN_LEAD_LAG_OPEN;
+ pc->user_param.len = sizeof(udevice.lead_lag_open);
+ pc->user_param.type = USER_WORD;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 超前滞后下限
+ pc->code = DIN_LEAD_LAG_CLOSE;
+ pc->user_param.len = sizeof(udevice.lead_lag_close);
+ pc->user_param.type = USER_WORD;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 部分行程测试解电至跳闸
+ pc->code = DIN_LOOP_PST_ETT;
+ pc->user_param.len = sizeof(udevice.loop_pst_ett);
+ pc->user_param.type = USER_FLOAT;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 部分行程测试充电至跳闸
+ pc->code = DIN_LOOP_PST_DETT;
+ pc->user_param.len = sizeof(udevice.loop_pst_dett);
+ pc->user_param.type = USER_FLOAT;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 行程/压力偏差跳变点
+ pc->code = DIN_TVL_DEV_TRIP;
+ pc->user_param.len = sizeof(udevice.tvl_dev_trip);
+ pc->user_param.type = USER_FLOAT;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 行程/压力偏差时间
+ pc->code = DIN_TVL_DEV_TIME;
+ pc->user_param.len = sizeof(udevice.tvl_dev_time);
+ pc->user_param.type = USER_FLOAT;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 自动校准按钮
+ pc->code = DIN_AUTOCAL_BTN;
+ pc->user_param.len = sizeof(udevice.autocal_btn);
+ pc->user_param.type = USER_BYTE;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 行程/压力设定点速率上限
+ pc->code = DIN_RATE_LIMIT_OPEN;
+ pc->user_param.len = sizeof(udevice.rate_limit_open);
+ pc->user_param.type = USER_FLOAT;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 行程/压力设定点速率下限
+ pc->code = DIN_RATE_LIMIT_CLOSE;
+ pc->user_param.len = sizeof(udevice.rate_limit_close);
+ pc->user_param.type = USER_FLOAT;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 重启仪器模式
+ pc->code = DIN_RESTART_INST_MODE;
+ pc->user_param.len = sizeof(udevice.restart_inst_mode);
+ pc->user_param.type = USER_BYTE;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // LCP通讯跳闸警报时间
+ pc->code = DIN_LCP_TRIP_ALERT_SEC;
+ pc->user_param.len = sizeof(udevice.lcp_trip_alert_sec);
+ pc->user_param.type = USER_WORD;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 滞后时间
+ pc->code = DIN_LVP_FILTER_SELECTOR;
+ pc->user_param.len = sizeof(udevice.lvp_filter_selector);
+ pc->user_param.type = USER_WORD;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 超前滞后启动
+ pc->code = DIN_LEAD_LAG_BOOST;
+ pc->user_param.len = sizeof(udevice.lead_lag_boost);
+ pc->user_param.type = USER_FLOAT;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // A口压力跳变点
+ pc->code = DIN_PS1_TRIGGER_DB;
+ pc->user_param.len = sizeof(udevice.ps1_trigger_db);
+ pc->user_param.type = USER_FLOAT;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // B口压力跳变点
+ pc->code = DIN_PS2_TRIGGER_DB;
+ pc->user_param.len = sizeof(udevice.ps2_trigger_db);
+ pc->user_param.type = USER_FLOAT;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 触发灵敏度
+ pc->code = DIN_TRIGGER_SENSITIVITY;
+ pc->user_param.len = sizeof(udevice.trigger_sensitivity);
+ pc->user_param.type = USER_WORD;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 行程偏差报警时间
+ pc->code = DIN_TRAVEL_DEV_ALERT_TIME;
+ pc->user_param.len = sizeof(udevice.travel_dev_alert_time);
+ pc->user_param.type = USER_FLOAT;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 输入电流跳变点
+ pc->code = DIN_CURRENT_TRIGGER_DB;
+ pc->user_param.len = sizeof(udevice.current_trigger_db);
+ pc->user_param.type = USER_FLOAT;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 部分行程测试最小压力
+ pc->code = DIN_MIN_PST_PRESS;
+ pc->user_param.len = sizeof(udevice.min_pst_press);
+ pc->user_param.type = USER_FLOAT;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 部分行程测试最小压力时间
+ pc->code = DIN_MIN_PST_PRESS_TIME;
+ pc->user_param.len = sizeof(udevice.min_pst_press_time);
+ pc->user_param.type = USER_FLOAT;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 压力偏差报警时间
+ pc->code = DIN_PRESS_DEV_ALERT_TIME;
+ pc->user_param.len = sizeof(udevice.press_dev_alert_time);
+ pc->user_param.type = USER_FLOAT;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 重新启动控制模式
+ pc->code = DIN_RESTART_CTRL_MODE;
+ pc->user_param.len = sizeof(udevice.restart_ctrl_mode);
+ pc->user_param.type = USER_BYTE;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 停机自检
+ pc->code = DIN_SELFTEST_SHUTDOWN;
+ pc->user_param.len = ARRAY_LEN(udevice.selftest_shutdown);
+ pc->user_param.type = USER_BYTE;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 辅助输入类型
+ pc->code = DIN_AUX_INPUT_TYPE;
+ pc->user_param.len = sizeof(udevice.aux_input_type);
+ pc->user_param.type = USER_BYTE;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 位置跨度
+ pc->code = DIN_POS_SPAN;
+ pc->user_param.len = sizeof(udevice.pos_span);
+ pc->user_param.type = USER_WORD;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 位置偏移
+ pc->code = DIN_POS_OFFSETR;
+ pc->user_param.len = sizeof(udevice.pos_offset);
+ pc->user_param.type = USER_WORD;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 轮询地址
+ pc->code = DIN_POLLING_ADDR;
+ pc->user_param.len = sizeof(udevice.polling_addr);
+ pc->user_param.type = USER_BYTE;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 上限软切割速率
+ pc->code = DIN_SOFT_CUTOFF_RATE_OPEN_UNSCALED;
+ pc->user_param.len = sizeof(udevice.soft_cutoff_rate_open_unscaled);
+ pc->user_param.type = USER_FLOAT;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 下限软切割速率
+ pc->code = DIN_SOFT_CUTOFF_RATE_CLOSE_UNSCALED;
+ pc->user_param.len = sizeof(udevice.soft_cutoff_rate_close_unscaled);
+ pc->user_param.type = USER_FLOAT;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 积分限位
+ pc->code = DIN_INTEGRAL_LIMIT_UNSCALED;
+ pc->user_param.len = sizeof(udevice.intergal_limit_unscaled);
+ pc->user_param.type = USER_FLOAT;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 警报记录使能
+ pc->code = DIN_AER_CONFIG;
+ pc->user_param.len = sizeof(udevice.aer_config);
+ pc->user_param.type = USER_BYTE;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 输出压力限制使能
+ pc->code = DIN_OUTPUT_PRESS_LIMIT_ENABLE;
+ pc->user_param.len = sizeof(udevice.output_press_limit_enable);
+ pc->user_param.type = USER_BYTE;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 压力A限制
+ pc->code = DIN_PRESS_A_LIMIT;
+ pc->user_param.len = sizeof(udevice.press_a_limit);
+ pc->user_param.type = USER_FLOAT;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 所有行程警报死区
+ pc->code = DIN_TRAVEL_ALERT_DEADBAND_UNSCALED;
+ pc->user_param.len = sizeof(udevice.travel_alert_deadband_unscaled);
+ pc->user_param.type = USER_FLOAT;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 周期计数累计死区
+ pc->code = DIN_CYCLE_COUNT_DEADBAND_UNSCALED;
+ pc->user_param.len = sizeof(udevice.cycle_count_deadband_unscaled);
+ pc->user_param.type = USER_FLOAT;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 行程单位
+ pc->code = DIN_TRAVEL_UNITS;
+ pc->user_param.len = sizeof(udevice.travel_units);
+ pc->user_param.type = USER_BYTE;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 变化点(与行程有关)
+ pc->code = DIN_CROSSOVER_OUT;
+ pc->user_param.len = sizeof(udevice.crossover_out);
+ pc->user_param.type = USER_WORD;
+ pc->user_param.access = USER_READ_ONLY;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 原始驱动
+ pc->code = DIN_DRIVE_RAW;
+ pc->user_param.len = sizeof(udevice.driver_raw);
+ pc->user_param.type = USER_WORD;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 伺服输出偏差
+ pc->code = DIN_SERVO_OUTPUT_BIAS;
+ pc->user_param.len = sizeof(udevice.servo_output_bias);
+ pc->user_param.type = USER_WORD;
+ pc->user_param.access = USER_READ_ONLY;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 输入电流上限值
+ pc->code = DIN_INPUT_RANGE_HI;
+ pc->user_param.len = sizeof(udevice.input_range_hi);
+ pc->user_param.type = USER_FLOAT;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 输入电流下限值
+ pc->code = DIN_INPUT_RANGE_LO;
+ pc->user_param.len = sizeof(udevice.input_range_lo);
+ pc->user_param.type = USER_FLOAT;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 输入电流偏移
+ pc->code = DIN_INPUT_OFFSET;
+ pc->user_param.len = sizeof(udevice.input_offset);
+ pc->user_param.type = USER_WORD;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 输入电流跨度
+ pc->code = DIN_INPUT_SPAN;
+ pc->user_param.len = sizeof(udevice.input_span);
+ pc->user_param.type = USER_WORD;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // A路压力偏移
+ pc->code = DIN_PRESS_A_OFFSET;
+ pc->user_param.len = sizeof(udevice.press_a_offset);
+ pc->user_param.type = USER_WORD;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // A路压力跨度
+ pc->code = DIN_PRESS_A_SPAN;
+ pc->user_param.len = sizeof(udevice.press_a_span);
+ pc->user_param.type = USER_WORD;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // B路压力偏移
+ pc->code = DIN_PRESS_B_OFFSET;
+ pc->user_param.len = sizeof(udevice.press_b_offset);
+ pc->user_param.type = USER_WORD;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // B路压力跨度
+ pc->code = DIN_PRESS_B_SPAN;
+ pc->user_param.len = sizeof(udevice.press_b_span);
+ pc->user_param.type = USER_WORD;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 气源压力偏移
+ pc->code = DIN_PRESS_S_OFFSET;
+ pc->user_param.len = sizeof(udevice.press_s_offset);
+ pc->user_param.type = USER_WORD;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 气源压力跨度
+ pc->code = DIN_PRESS_S_SPAN;
+ pc->user_param.len = sizeof(udevice.press_s_span);
+ pc->user_param.type = USER_WORD;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+ // 小回路跨度
+ pc->code = DIN_MINOR_LOOP_SPAN;
+ pc->user_param.len = sizeof(udevice.minor_loop_span);
+ pc->user_param.type = USER_WORD;
+ pc->user_param.access = USER_READ_ONLY;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+
+ // 位置变送器状态
+ pc->code = DIN_XMTR_INSTALLED_POSXMTRSTATE;
+ pc->user_param.len = sizeof(udevice.xmtr_installed_posxmtrstate);
+ pc->user_param.type = USER_BYTE;
+ pc->user_param.access = USER_READ_ONLY;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+
+ // 整定步骤
+ pc->code = DIN_AUTOCAL_STEP_ID;
+ pc->user_param.len = sizeof(rt_data.tuned_id);
+ pc->user_param.type = USER_BYTE;
+ pc->user_param.access = USER_READ_ONLY;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+
+ // 自定义:新增常量
+
+ // 部分行程使能
+ pc->code = DIN_PART_TRAVEL_ENABLE;
+ pc->user_param.len = sizeof(udevice.part_travel_enable);
+ pc->user_param.type = USER_BYTE;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+
+ // 分程控制下限
+ pc->code = DIN_PART_TRAVEL_LOWER;
+ pc->user_param.len = sizeof(udevice.part_travel_lower);
+ pc->user_param.type = USER_FLOAT;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+
+ // 分程控制上限
+ pc->code = DIN_PART_TRAVEL_UPPER;
+ pc->user_param.len = sizeof(udevice.part_travel_upper);
+ pc->user_param.type = USER_FLOAT;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+
+ // 输出电流偏移
+ pc->code = DIN_OUTPUT_OFFSET;
+ pc->user_param.len = sizeof(udevice.output_offset);
+ pc->user_param.type = USER_WORD;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+
+ // 输出电流跨度
+ pc->code = DIN_OUTPUT_SPAN;
+ pc->user_param.len = sizeof(udevice.output_span);
+ pc->user_param.type = USER_WORD;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+
+ // 定位器型号
+ pc->code = DIN_DEVICE_TYPE;
+ pc->user_param.len = sizeof(udevice.dev_model);
+ pc->user_param.type = USER_WORD;
+ pc->user_param.access = USER_READ_WRITE;
+ constant_params_fill_default(pc);
+ pc++;
+ pc_count++;
+
+ /********************标准变量******************************* */
+ ps->code = DIN_242; // 电池电压
+ ps++;
+ ps_count++;
+ ps->code = DIN_243; // 电池寿命
+ ps++;
+ ps_count++;
+
+ ps->code = DIN_244; // 量程百分比
+ ps++;
+ ps_count++;
+
+ ps->code = DIN_245; // 回路电流
+ ps++;
+ ps_count++;
+ // 设置主变量、次要变量 、三级变量、四级变量
+ ps->code = DIN_246;
+ ps++;
+ ps_count++;
+
+ ps->code = DIN_247;
+ ps++;
+ ps_count++;
+
+ ps->code = DIN_248;
+ ps++;
+ ps_count++;
+
+ ps->code = DIN_249;
+ ps++;
+ ps_count++;
+
+ if (pv_count > HART_DEVICE_VARIABLE_LEN)
+ {
+ DBG_ASSERT(FALSE __DBG_LINE);
+ }
+
+ if (pc_count > HART_DEVICE_CONSTANT_LEN)
+ {
+ DBG_ASSERT(FALSE __DBG_LINE);
+ }
+
+ if (ps_count > HART_DEVICE_STANDARD_VARIABLE_LEN)
+ {
+ DBG_ASSERT(FALSE __DBG_LINE);
+ }
+
+ hart_device_variable_sort(); // 参数变量排序
+ hart_device_constant_sort(); // 常量变量排序
+
+ hart_attribute_params_map_address_update(); // 映射变量和常量地址
+ // 写入到外部EPPROM
+ for (uint8_t i = 0; i < HART_WRITE_MAX_COUNT; i++)
+ {
+ ret = storage_write_all(hart_variable_storage, (uint8_t *)&hart_device_attribute.device_variable);
+ }
+ DBG_ASSERT(ret != FALSE __DBG_LINE);
+
+ for (uint8_t i = 0; i < HART_WRITE_MAX_COUNT; i++)
+ {
+ ret = storage_write_all(hart_constant_storage, (uint8_t *)&hart_device_attribute.device_constant);
+ }
+ DBG_ASSERT(ret != FALSE __DBG_LINE);
+
+ for (uint8_t i = 0; i < HART_WRITE_MAX_COUNT; i++)
+ {
+ ret = storage_write_all(hart_standard_variable_storage, (uint8_t *)&hart_device_attribute.device_standard_variable);
+ }
+ DBG_ASSERT(ret != FALSE __DBG_LINE);
}
/**
@@ -17,5 +2175,133 @@ void hart_attribute_params_map(void)
*/
void hart_attribute_params_restart(void)
{
-
+ BOOL ret = FALSE;
+ uint16_t year = rt_save.real_time.date.year;
+ uint8_t month = rt_save.real_time.date.month;
+ uint8_t day = rt_save.real_time.date.day;
+ uint8_t hour = rt_save.real_time.date.hour;
+ uint8_t minute = rt_save.real_time.date.minute;
+ uint8_t second = rt_save.real_time.date.second;
+ uint8_t tag[HART_PACKED8_LEN] = ""; // 标签
+ uint8_t long_tag[HART_PACKED32_LEN] = "";
+ uint8_t descriptor[HART_PACKED16_LEN] = ""; // 描述符
+ uint8_t message[HART_PACKED32_LEN] = "";
+ hart_storage_variable_t *p = &hart_device_attribute.flash_variable;
+ real_time_clock_t *pd = &hart_device_attribute.real_time_clock;
+ osel_memset((uint8_t *)p, 0, sizeof(hart_storage_variable_t));
+ osel_memcpy(tag, DESCRIPTOR, osel_mstrlen(DESCRIPTOR));
+ osel_memcpy(descriptor, DESCRIPTOR, osel_mstrlen(DESCRIPTOR));
+
+ covert_rtc_year_to_standard(&year);
+ sprintf((char *)long_tag, "GSDT %02d-%02d-%02d", year, month, day);
+ sprintf((char *)message, "GSDT RUN:%02d-%02d-%02d %02d:%02d:%02d", year, month, day, hour, minute, second);
+
+ // 基本属性更新
+ p->init_flag = HART_INIT_FLAG; // 初始化标志
+ p->poll_address = HART_SHORT_ADDRESS; // 轮询地址
+ p->extended_device_type = udevice.dev_model; // 扩展设备类型
+ p->device_revision = DW_VER; // 设备修订
+ p->device_software_revision = udevice.dev_sw_version; // 设备软件修订
+ p->device_hardware_revision.bits.physical_signaling_code = PHYSICAL_SIGNALS_1; // 物理信号
+ p->device_hardware_revision.bits.hardware_revision = udevice.dev_hw_version; // 硬件修订
+ hart_long_addr_set(); // 长地址设置
+
+ p->manufacturer_identification_code = MANUFACTURER_IDENTIFICATION_CODE; // 制造商标识码
+ p->private_label_distributor_code = MANUFACTURER_IDENTIFICATION_CODE; // 私有标签分销商代码
+ p->device_profile = DEVICE_CONFIGURATION_FILE_CODE_1; // 设备配置文件
+ osel_memcpy(p->tag, tag, ARRAY_LEN(tag)); // 标签
+ osel_memcpy(p->descriptor, descriptor, ARRAY_LEN(descriptor)); // 描述
+ osel_memcpy(p->long_tag, long_tag, ARRAY_LEN(long_tag)); // 长标签
+ osel_memcpy(p->message, message, sizeof(message)); // 消息
+ p->write_protect_code = WRITE_PROTECT_CODE_NOT_WRITE_PROTECT; // 默认开启写保护
+ p->poll_address = HART_SHORT_ADDRESS; // 轮询地址
+ p->country_code = COUNTRY_CODE_CN; // 国家代码
+ p->si_units_control_code = SI_UNITS_CONTROL_CODE_0; // SI单位控制码
+ p->s2m_preambles = HART_PREAMBLE_DEFAULT_LEN; // S2M前导码
+ pd->rtc_flags = REAL_TIME_CLOCK_FLAGS_2; // RTC标志
+
+ for (uint8_t i = 0; i < HART_WRITE_MAX_COUNT; i++)
+ {
+ ret = storage_write_all(hart_attribute_storage, (uint8_t *)p);
+ }
+
+ DBG_ASSERT(ret != FALSE __DBG_LINE);
+}
+
+/**
+ * @brief hart规格表数据映射
+ *
+ * 根据给定的逆序标志,对hart规格表数据进行映射操作。
+ *
+ * @param inverse 逆序标志
+ * - 如果为TRUE,表示进行逆序映射 udevice->spec_table
+ * - 如果为FALSE,表示进行正序映射 spec_table->udevice
+ */
+void spec_table_data_mapping(BOOL inverse)
+{
+ if (inverse == TRUE)
+ {
+ // udevice->spec_table
+ }
+ else
+ {
+ // spec_table->udevice
+ }
+}
+
+/**
+ * @brief 重置 规格表数据
+ *
+ * 重置 规格表数据,并调用 spec_table_data_mapping 函数进行数据映射。
+ */
+void spec_table_data_reset(void)
+{
+ osel_memset((uint8_t *)&spec_table_data, 0, sizeof(specification_table_data_t));
+
+ spec_table_data.ss2_ver = 1; // 版本
+ spec_table_data.ss2_u_travel = 0; // 行程
+ spec_table_data.ss2_u_length = 2; // 长度单位
+ spec_table_data.ss2_u_area = 10; // 区域单位
+ spec_table_data.ss2_u_torque = 16; // 扭矩单位
+ spec_table_data.ss2_u_springrate = 20; // 弹簧力
+ spec_table_data.ss2_v_manuf = 0; // 阀门制造商标识
+ spec_table_data.ss2_v_model = 0; // 阀门型号
+ spec_table_data.ss2_v_size = 2; // 阀门尺寸
+ spec_table_data.ss2_v_class = 0; // 阀门类型
+ spec_table_data.ss2_v_rated_travel = 25; // 阀门额定行程
+ spec_table_data.ss2_v_actual_travel = 24.66; // 阀门实际行程
+ spec_table_data.ss2_v_stem_size = 2; // 阀杆直径
+ spec_table_data.ss2_v_packing = 0; // 阀门填料类型
+ spec_table_data.ss2_v_inlet_press = 360; // 阀门入口压力
+ spec_table_data.ss2_v_outlet_press = 1000; // 阀门出口压力
+ spec_table_data.ss2_v_dyn_torque = 0; // 阀门动态扭矩
+ spec_table_data.ss2_v_breakout_torque = 0; // 阀门突破扭矩
+ spec_table_data.ss2_t_seat_type = 0; // 修整座类型
+ spec_table_data.ss2_t_class = 0; // 修整泄漏等级
+ spec_table_data.ss2_t_port_diam = 0; // 修整端口直径
+ spec_table_data.ss2_t_port_type_ss2_t_flow_dir_ss2_t_pdt_ss2_t_ftt = 0; // 修整端口类型
+ spec_table_data.ss2_t_unbal_area = 0; // 修整不平衡面积
+ spec_table_data.ss2_a_manuf = 0; // 执行器制造商*
+ spec_table_data.ss2_a_model = 0; // 执行器型号*
+ spec_table_data.ss2_a_size = 0; // 执行器尺寸
+ spec_table_data.ss2_a_eff_area = 35000; // 执行器有效面积
+ spec_table_data.ss2_a_air = 0; // 执行器空气
+ spec_table_data.ss2_a_lever_style = 0; // 执行器杠杆样式
+ spec_table_data.ss2_a_bench_lo = 0; // 执行器下限设置
+ spec_table_data.ss2_a_bench_hi = 0; // 执行器上限设置
+ spec_table_data.ss2_a_nom_press = 6000; // 执行器额定供应压力
+ spec_table_data.ss2_a_springrate = 0; // 执行器弹簧率
+ spec_table_data.ss2_a_lever_arm_length = 0; // 执行器杠杆臂长度
+ spec_table_data.ss2_acc_vol_booster_ss2_acc_quick_rel = 0; // 执行器体积助推器快速释放
+ spec_table_data.ss2_acc_sol_valve = 0; // 执行器电磁阀
+ spec_table_data.ss2_acc_pos_xmtr = 0; // 执行器位置发射器
+ spec_table_data.ss2_acc_lim_sw_open_ss2_acc_lim_sw_closed = 0; // 执行器限位开关,阀门打开限位开关,阀门关闭
+ spec_table_data.ss2_t_trim1 = 0; // 修整样式
+ spec_table_data.ss2_v_rated_pressure = 160;
+ spec_table_data.ss2_v_nominal_diameter = 25;
+ // 其他的不用赋初值
+
+ spec_table_data_mapping(FALSE);
+
+ storage_write_all(specification_table_data_storage, (uint8_t *)&spec_table_data);
}
diff --git a/User/application/src/pdctrl.c b/User/application/src/pdctrl.c
index 833b199..66071fe 100644
--- a/User/application/src/pdctrl.c
+++ b/User/application/src/pdctrl.c
@@ -4,6 +4,7 @@
#include "leds.h"
#include "board.h"
pdctrl_t pdctrl_data;
+pdctrl_t pdctrl_data_out;
__IO static pdctrl_mode_e out_mode = PDCTRL_DAC;
__IO static BOOL pdctrl_run_flag = FALSE;
@@ -50,6 +51,7 @@ static void pwmp_init(void)
{
pdctrl_data.last_out = 0xffff;
GPIO_SET_ALTERNATE(PDCTRL_PWM_GPIO_Port, PDCTRL_PWM_Pin);
+ ENABLE_TIM_ARR_RELOAD(PDCTRL_PWMP_TIM);
PWM_START(PDCTRL_PWMP_TIM, PDCTRL_PWMP_CHINNEL); // PWM通道使能
}
@@ -65,7 +67,6 @@ void pdctrl_init(pdctrl_mode_e mode)
out_mode = mode;
pdctrl_data.pwm_wid = PWM_WID;
osel_memset((uint8_t *)&pdctrl_data, 0, sizeof(pdctrl_t));
- VIP_H_EN_DISABLE();
dac_dinit();
pwm_dinit();
pwmp_dinit();
@@ -186,8 +187,8 @@ uint16_t calculate_pwm_duty(uint32_t arr)
pdctrl_data.arr_us = 1000.0f / pdctrl_data.freq;
pdctrl_data.duty_percent = ((float32)wid * 100.0f) / pdctrl_data.arr_us;
- uint16_t duty = arr * pdctrl_data.duty_percent / 100;
- return duty;
+ pdctrl_data.duty = arr * pdctrl_data.duty_percent / 100;
+ return pdctrl_data.duty;
}
/**
@@ -218,15 +219,8 @@ void pdctrl_pwm_set_arr(uint32_t arr)
{
arr = pdctrl_data.pwm_arr_default;
}
- if (arr > pdctrl_data.pwm_arr_default)
- {
- // arr = pdctrl_data.pwm_arr_default;
- pdctrl_data.pwm_arr_default = arr;
- }
LL_TIM_SetAutoReload(PDCTRL_PWM_TIM, arr);
-
uint16_t duty = calculate_pwm_duty(arr);
-
#if PDCTRL_PWM_CHINNEL == LL_TIM_CHANNEL_CH4
PWM_SET_DUTY(PDCTRL_PWM_TIM, 4, duty);
#else
@@ -259,7 +253,7 @@ void pdctrl_out(uint16_t out)
return;
}
- if (pdctrl_data.last_out == out && (pdctrl_data.sysclk == (SystemCoreClock / 1000)))
+ if (pdctrl_data.last_out == out && (pdctrl_data.sysclk != (SystemCoreClock / 1000)))
{
return;
}
diff --git a/User/board/inc/board.h b/User/board/inc/board.h
index 32e966f..8e06b60 100644
--- a/User/board/inc/board.h
+++ b/User/board/inc/board.h
@@ -11,17 +11,31 @@
#include "main.h"
#include "bsp.h"
#include "tim.h"
+#include "lcds.h"
#include "menu.h"
+#include "leds.h"
#include "rtc_rx8010.h"
#include "eeprom_m95.h"
#include "eeprom_fm24.h"
#include "eeprom_lc02b.h"
#include "ntc_3950.h"
-#include "leds.h"
+#include "sht40.h"
+#include "dac161p997.h"
-#define APP_PRELOAD_AREA 0x10007FF0 ///< 预加载区域
-#define VREF_VALUE 3000 ///< 参考电压mV
-#define FONT_TYPE FONT_0816 ///< 字体类型
+#define LCD_SPI SPI2
+
+#define HART_UART1 USART1
+#define HART_UART2 UART5
+#define HART_UART1_BAUDRATE (1200U)
+#define HART_UART2_BAUDRATE (115200U)
+
+#define APP_PRELOAD_AREA 0x10007FF0 ///< 预加载区域
+#define VREF_VALUE (CPU_VREF * 1000) ///< 参考电压mV
+#define TASK_TIM TIM6 ///< 任务定时器
+#define MODE_TIM TIM7 ///< 模式定时器
+#define MODE_GATHE_TIM TIM17 ///< 模式采集定时器
+#define HART_TIM TIM16 ///< HART定时器
+#define HART_OUT_TIM TIM3 ///< HART输出定时器
#ifndef ADC_MAX
#define ADC_MAX 4095 //< ADC最大
@@ -34,12 +48,12 @@
#define BLE_EN_DISABLE() GPIO_RESET(BLE_PWR_GPIO_Port, BLE_PWR_Pin) ///< 蓝牙禁用
#define BLE_IS_ENABLE() (GPIO_READ(BLE_PWR_GPIO_Port, BLE_PWR_Pin) == SET) ///< 蓝牙使能状态
-#define LCD_DMA DMA1 ///< LCD DMA
-#define LCD_DMA_TX_CHANNEL LL_DMA_CHANNEL_5 ///< LCD DMA发送通道
-#define LCD_POWER_ON() GPIO_SET(LCD_PWR_GPIO_Port, LCD_PWR_Pin) ///< LCD电源使能
-#define LCD_POWER_OFF() GPIO_RESET(LCD_PWR_GPIO_Port, LCD_PWR_Pin) ///< LCD电源禁用
-#define LCD_IS_POWER_ON() (GPIO_READ(LCD_PWR_GPIO_Port, LCD_PWR_Pin) == SET) ///< LCD电源使能状态
-#define LCD_DETECT() (0) ///< LCD检测,高电平没有接入,低电平接入
+#define LCD_DMA DMA1 ///< LCD DMA
+#define LCD_DMA_TX_CHANNEL LL_DMA_CHANNEL_5 ///< LCD DMA发送通道
+#define LCD_POWER_ON() GPIO_SET(LCD_PWR_GPIO_Port, LCD_PWR_Pin) ///< LCD电源使能
+#define LCD_POWER_OFF() GPIO_RESET(LCD_PWR_GPIO_Port, LCD_PWR_Pin) ///< LCD电源禁用
+#define LCD_IS_POWER_ON() (GPIO_READ(LCD_PWR_GPIO_Port, LCD_PWR_Pin) == SET) ///< LCD电源使能状态
+#define LCD_DETECT() (GPIO_READ(LCD_EXTCOMIN_GPIO_Port, LCD_EXTCOMIN_Pin) == SET) ///< LCD检测,高电平没有接入,低电平接入
#define BP_S_POWER_ON() GPIO_SET(BP_S_PWR_GPIO_Port, BP_S_PWR_Pin)
#define BP_S_POWER_OFF() GPIO_RESET(BP_S_PWR_GPIO_Port, BP_S_PWR_Pin)
@@ -53,7 +67,7 @@
#define BP_B_POWER_OFF() GPIO_RESET(BP_B_PWR_GPIO_Port, BP_B_PWR_Pin)
#define BP_B_IS_POWER_ON() (GPIO_READ(BP_B_PWR_GPIO_Port, BP_B_PWR_Pin) == SET)
-/// 禁用 I/P 电流输出 0-6.2V
+////< 禁用 I/P 电流输出 0-6.2V
#define VIP_H_EN_DISABLE() \
do \
{ \
@@ -61,7 +75,7 @@
GPIO_SET_ANALOG(IP_H_PWR_GPIO_Port, IP_H_PWR_Pin); \
} while (0)
-/// 使能 I/P 电流输出 0-6.2V
+////< 使能 I/P 电流输出 0-6.2V
#define VIP_H_EN_ENABLE() \
do \
{ \
@@ -69,7 +83,7 @@
GPIO_SET(IP_H_PWR_GPIO_Port, IP_H_PWR_Pin); \
} while (0)
-// PWM对外输出
+///< PWM对外输出
#define PWM_CTRL_OUTPUT(out) PWM_SET_DUTY(TIM3, 3, out)
/* HART */
@@ -84,15 +98,20 @@
/* HART */
/* SWO */
-#define SWO1_OPEN() GPIO_SET(SWO1_GPIO_Port, SWO1_Pin) ///< SWO1 开
-#define SWO1_CLOSE() GPIO_RESET(SWO1_GPIO_Port, SWO1_Pin) ///< SWO1 关
-#define SWO2_OPEN() GPIO_SET(SWO2_GPIO_Port, SWO2_Pin) ///< SWO2 开
-#define SWO2_CLOSE() GPIO_RESET(SWO2_GPIO_Port, SWO2_Pin) ///< SWO2 关
+#define SWO1_OPEN() GPIO_SET(SWO1_GPIO_Port, SWO1_Pin) ///< SWO1 开
+#define SWO1_CLOSE() GPIO_RESET(SWO1_GPIO_Port, SWO1_Pin) ///< SWO1 关
+#define SWO1_TOGGLE() GPIO_TOGGLE(SWO1_GPIO_Port, SWO1_Pin) ///< SWO1 翻转
+#define SWO1_IS_OPEN() (GPIO_READ(SWO1_GPIO_Port, SWO1_Pin) == SET)
+#define SWO2_OPEN() GPIO_SET(SWO2_GPIO_Port, SWO2_Pin) ///< SWO2 开
+#define SWO2_CLOSE() GPIO_RESET(SWO2_GPIO_Port, SWO2_Pin) ///< SWO2 关
+#define SWO2_TOGGLE() GPIO_TOGGLE(SWO2_GPIO_Port, SWO2_Pin) ///< SWO2 翻转
+#define SWO2_IS_OPEN() (GPIO_READ(SWO2_GPIO_Port, SWO2_Pin) == SET)
typedef enum
{
FILTER_AVERAGE = 1,
FILTER_MEDIAN,
+ FILTER_MEDIAN_AVERAGE,
} filter_e;
typedef enum
@@ -104,42 +123,53 @@ typedef enum
typedef enum
{
- // 不需要跳转到bootload
+ ///< 不需要跳转到bootload
APP_PRELOAD_BOOTLOAD_JUMP_NONE = 0,
- // 更新完成等待用户通知跳转到bootload
- APP_PRELOAD_BOOTLOAD_JUMP_WAIT = 1,
- // 更新完成立即跳转到bootload
- APP_PRELOAD_BOOTLOAD_JUMP_IMMEDIATELY,
+ ///< 更新完成等待用户通知跳转到bootload
+ APP_PRELOAD_BOOTLOAD_JUMP_WAIT = 0xd501,
+ ///< 更新完成立即跳转到bootload
+ APP_PRELOAD_BOOTLOAD_JUMP_IMMEDIATELY = 0xc802,
} app_preload_bootload_jump_e; ///< 预加载BOOTLOAD跳转标志
-extern const uint32_t NTC_100K_B3950_List[];
-extern __IO uint8_t app_preload_flag; ///< 预加载标志位
-extern __IO uint8_t app_preload_language_flag; ///< 语言标志位
-extern __IO uint8_t app_preload_bootload_flag; ///< 触发BOOTLOAD启动标志(在用户代码中接受代码文件)
-extern __IO uint8_t app_preload_bootload_jump_flag; ///< 触发BOOTLOAD跳转标志(在用户代码中接受代码文件)
-extern __IO uint32_t app_preload_cupid_encrypt; ///< CPU加密值
+typedef struct
+{
+ uint16_t app_preload_flag; ///< 预加载标志
+ uint8_t app_preload_language_flag; ///< 语言标志
+ uint32_t app_preload_cupid_encrypt; ///< 加密后的CPUID
+} board_data_t;
-extern void board_init(void); ///< 板卡初始化
-extern void board_dinit(void); ///< 板卡反初始化
-extern void board_work_stop_or_run(void); ///< 板卡工作停止或运行
-extern void board_cache_reset(void); ///< 板卡缓存复位
-extern uint16_t board_cache_get(board_cache_e index); ///< 板卡缓存获取
-extern void driver_init(void); ///< 功耗引脚初始化
-extern void driver_dinit(void); ///< 功耗引脚反初始化
-extern void lcd_init(void); ///< LCD初始化
-extern void lcd_dinit(void); ///< LCD反初始化
-extern void system_clock_config_set_flag(BOOL flag); ///< 设置系统时钟配置标志
-extern void system_clock_config_low(void); ///< 系统时钟配置低频
-extern void system_clock_config_hight(void); ///< 系统时钟配置高频
-extern void gui_flush(void); ///< LCD刷新
-extern void gui_flush_Clear(void); ///< LCD刷新并清屏
-extern void gui_clr(void); ///< 清屏
-extern void gui_full(void); ///< 全屏黑色
-extern void gui_open(void); ///< 打开GUI
-extern void gui_close(void); ///< 关闭GUI
-extern void gui_set_scandir(uint8_t dir); ///< 设置扫描方向
-extern void gui_set_clear_flag(void); ///< 设置清屏标志
-extern BOOL gui_get_clear_flag(void); ///< 获取清屏标志
+extern board_data_t board_data; ///< 板卡数据
+extern lcd_t *lcd; ///< LCD句柄
+extern __IO uint16_t dbg_assert_line;
+extern __IO uint16_t app_preload_bootload_flag; ///< 触发BOOTLOAD启动标志(在用户代码中接受代码文件)
+extern __IO uint16_t app_preload_bootload_jump_flag; ///< 触发BOOTLOAD跳转标志(在用户代码中接受代码文件)
+
+extern void board_init(void); ///< 板卡初始化
+extern void board_dinit(void); ///< 板卡反初始化
+extern void board_srand(void); ///< 板卡随机数种子
+extern void board_work_stop_or_run(void); ///< 板卡工作停止或运行
+extern uint16_t board_cache_get(board_cache_e index); ///< 板卡缓存获取
+extern void driver_init(void); ///< 功耗引脚初始化
+extern void driver_dinit(void); ///< 功耗引脚反初始化
+extern BOOL is_lcd_ext_board(void); ///< 是否接入了LCD扩展板
+extern void lcd_init(void); ///< LCD初始化
+extern void lcd_dinit(void); ///< LCD反初始化
+extern void system_clock_config_low(void); ///< 系统时钟配置低频
+extern void system_clock_config_high(void); ///< 系统时钟配置高频
+extern BOOL gui_can_work(void); ///< GUI是否可以工作
+extern BOOL gui_is_idle(void); ///< GUI是否空闲
+extern void gui_flush(void); ///< LCD刷新
+extern void gui_flush_Clear(void); ///< LCD刷新并清屏
+extern void gui_clr(void); ///< 清屏
+extern void gui_full(void); ///< 全屏黑色
+extern void gui_open(void); ///< 打开GUI
+extern void gui_close(void); ///< 关闭GUI
+extern void gui_set_scandir(uint8_t dir); ///< 设置扫描方向
+extern void gui_set_clear_flag(void); ///< 设置清屏标志
+extern BOOL gui_get_clear_flag(void); ///< 获取清屏标志
+extern BOOL flash_read(uint32_t address, uint8_t *data, uint16_t length); ///< 读取Flash
+extern BOOL flash_write(uint32_t address, const uint8_t *data, uint16_t length); ///< 写入Flash
+extern BOOL flash_erase_page(uint32_t page); ///< 擦除Flash页
extern uint16_t get_dac(float32 output); ///< 根据目标行程计算DAC输出理论值
extern void pwm_output_position(float32 position_per); ///< PWM输出阀位百分比
@@ -147,36 +177,50 @@ extern void calib_loop(void);
extern void calib_kpa(void); ///< 校准压力
extern void calib_pwm_out(void); ///< 校准PWM输出
extern void calib_parapos_perent(void); ///< 校准阀门位置参数
-extern uint16_t get_actual_travel_adc_average(void); ///< 获取当前实际行程ADC值
extern uint16_t get_actual_travel_adc(void); ///< 获取当前实际行程ADC值
extern float32 get_actual_travel(filter_e filter); ///< 获取当前实际行程
-extern float32 get_actual_travel_2(filter_e filter); ///< 获取当前实际行程
-extern float32 get_current(void); ///< 获取当前回路电流
-extern float32 get_current_deal(float32 current); ///< 获取当前回路电流
+extern float32 get_current_by_resistance(void); ///< 通过电阻测算获取当前回路电流
+extern float32 get_current(filter_e filter); ///< 获取当前回路电流
+extern float32 get_current_deal(float32 current); ///< 电流数据处理
extern float32 get_temperature(void); ///< 获取当前温度值
-extern float32 get_pressure(pressure_index_e id); ///< 获取当前压力
+extern float32 get_pressure(pressure_type_e id); ///< 获取当前压力
+extern float32 get_dead_zone(void); ///< 获取死区
extern float32 get_flow(void); ///< 获取当前流量
-extern void get_timestamp(uDateTime_TypeDef *time); ///< 获取时间戳
-extern void get_real_time(uint8_t *year, uint8_t *month, uint8_t *day, uint8_t *hour, uint8_t *min, uint8_t *sec); ///< 获取实时时间
-extern void set_real_time(uint8_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t min, uint8_t sec);
-extern BOOL get_app_preload_bootload_flag(void); ///< 获取预加载BOOTLOAD标志位
-extern app_preload_bootload_jump_e get_app_preload_bootload_jump_flag(void); ///< 获取预加载BOOTLOAD跳转标志
-extern void set_pwm_calib_current(void); ///< 设置输出PWM校准电流
-extern void set_loop_4ma(void); ///< 设置回路电流4mA
-extern void set_loop_20ma(void); ///< 设置回路电流20mA
-extern void set_200kpa(void); ///< 设置200kpa
-extern void set_400kpa(void); ///< 设置400kpa
-extern void set_output_4ma_pwm(uint16_t value); ///< 设置输出4mA时的PWM值
-extern void set_output_20ma_pwm(uint16_t value); ///< 设置输出20mA时的PWM值
-extern void set_app_preload_language_flag(uint8_t language); ///< 设置预加载语言标志位
-extern void set_app_preload_bootload_flag(uint8_t flag); ///< 设置预加载BOOTLOAD标志位
-extern void set_app_preload_bootload_jump_flag(app_preload_bootload_jump_e flag); ///< 设置预加载BOOTLOAD标志位
+extern BOOL update_real_time(date_time_t *real_time); ///< 更新实时时间
+extern BOOL get_timestamp(date_time_t *time); ///< 获取时间戳
+extern BOOL get_real_time(uint8_t *year, uint8_t *month, uint8_t *day, uint8_t *hour, uint8_t *min, uint8_t *sec); ///< 获取实时时间
+extern float32 get_cpu_temperature(void); ///< 获取CPU温度
+extern float32 get_cpu_volt(void); ///< 获取CPU电压
+extern float32 get_board_current(void); ///< 获取板卡电流
+extern uint32_t get_seed(void); ///< 获取随机种子
+extern BOOL uart1_get_idel_status(void); ///< 获取UART1空闲状态
+extern uint32_t rt_data_time_timestamp(void); ///< 获取实时时间戳
+extern BOOL rtc_get_datetime(rtc_date_t *const date, rtc_time_t *const time); ///< 获取RTC时间
+extern BOOL set_real_time(uint8_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t min, uint8_t sec);
+extern uint8_t get_language(void); ///< 获取语言
+extern uint8_t get_work_page_index(void); ///< 获取工作菜单索引
+extern uint16_t get_app_preload_bootload_flag(void); ///< 获取预加载BOOTLOAD标志位
+extern uint8_t get_app_preload_language_flag(void); ///< 获取预加载语言标志位
+extern app_preload_bootload_jump_e get_app_preload_bootload_jump_flag(void); ///< 获取预加载BOOTLOAD跳转标志
+extern void set_loop_4ma(void); ///< 设置回路电流4mA
+extern void set_loop_20ma(void); ///< 设置回路电流20mA
+extern void set_pressure_min(uint8_t unit, float32 set_value, pressure_type_e index); ///< 设置最小压力
+extern void set_pressure_max(uint8_t unit, float32 set_value, pressure_type_e index); ///< 设置最大压力
+extern void set_output_4ma_pwm(uint16_t value); ///< 设置输出4mA时的PWM值
+extern void set_output_20ma_pwm(uint16_t value); ///< 设置输出20mA时的PWM值
+extern void set_app_preload_language_flag(uint8_t language); ///< 设置预加载语言标志位
+extern void set_language(uint8_t language); ///< 设置语言
+extern void set_work_page_index(uint8_t index); ///< 设置工作菜单索引
+extern void set_app_preload_bootload_flag(uint16_t flag); ///< 设置预加载BOOTLOAD标志位
+extern void set_app_preload_bootload_jump_flag(app_preload_bootload_jump_e flag); ///< 设置预加载BOOTLOAD标志位
+extern void uart1_set_idel_handle_1_sec(void); ///< 设置UART1空闲处理,1秒执行一次
+extern void uart1_set_idel_status(BOOL idel); ///< 设置UART1空闲状态
/************************************** 通过电阻测算,只在测试程序中使用 **************************************/
extern float32 actual_adc_convert_percent(uint16_t adc); ///< 实际行程ADC值转换为百分比
extern float32 loop_current_convert(uint16_t adc); ///< 回路电流检测转换
extern float32 ip_dac2current(uint16_t dac); ///< DAC:IP输出电流值转换
extern float32 ip2current(void); ///< IP输出电流值转换
+extern float32 pressure_adc2kpa(uint16_t adc); ///< 压力ADC值转换
extern void pwm_duty2current(float32 cur_ma); ///< PWM输出电流值转换
-
-#endif // __BOARD_H__
+#endif ///< __BOARD_H__
diff --git a/User/board/inc/dac161p997.h b/User/board/inc/dac161p997.h
new file mode 100644
index 0000000..5c53d0b
--- /dev/null
+++ b/User/board/inc/dac161p997.h
@@ -0,0 +1,81 @@
+#ifndef __DAC161P997_H__
+#define __DAC161P997_H__
+#include "main.h"
+#include "gpios.h"
+
+#define DAC161P997_IO_PORT (DAC161P997_GPIO_Port)
+#define DAC161P997_IO_PIN (DAC161P997_Pin)
+
+#define DAC161P997_CURRENT_SLOPE 2730.625f // adc = (current / 24) * 0xffff
+
+// Symbol Periods
+#define DUTY_CYCLE_100 (1000U) // (CPU_CLK / BAUD_RATE)
+#define DUTY_CYCLE_75 (DUTY_CYCLE_100 * 0.75f)
+#define DUTY_CYCLE_50 (DUTY_CYCLE_100 * 0.50f)
+#define DUTY_CYCLE_25 (DUTY_CYCLE_100 * 0.25f)
+
+/************************************************************
+ * TI DAC161P997 REGISTER SET ADDRESSES
+ ************************************************************/
+#define DAC161P997_LCK_REG (0x0000)
+#define DAC161P997_CONFIG1_REG (0x0100)
+#define DAC161P997_CONFIG2_REG (0x0200)
+#define DAC161P997_CONFIG3_REG (0x0300)
+#define DAC161P997_ERR_LOW_REG (0x0400)
+#define DAC161P997_ERR_HIGH_REG (0x0500)
+
+// TI DAC161P997 Register Bits
+#define DAC161P997_LCK_REG_LOCK (0x00AA) // any value other than 0x95
+#define DAC161P997_LCK_REG_UNLOCK (0x0095)
+#define DAC161P997_CONFIG1_REG_RST (0x0001)
+#define DAC161P997_CONFIG1_REG_NOP (0 * 0x08u)
+#define DAC161P997_CONFIG1_REG_SET_ERR (1 * 0x08u)
+#define DAC161P997_CONFIG1_REG_CLEAR_ERR (2 * 0x08u)
+#define DAC161P997_CONFIG1_REG_NOP3 (3 * 0x08u)
+#define DAC161P997_CONFIG2_REG_LOOP (0x0001)
+#define DAC161P997_CONFIG2_REG_CHANNEL (0x0002)
+#define DAC161P997_CONFIG2_REG_PARITY (0x0004)
+#define DAC161P997_CONFIG2_REG_FRAME (0x0008)
+#define DAC161P997_CONFIG2_REG_ACK_EN (0x0010)
+#define DAC161P997_CONFIG3_REG_RX_ERR_CNT_16 (0x000F)
+#define DAC161P997_CONFIG3_REG_RX_ERR_CNT_8 (0x0007)
+#define DAC161P997_CONFIG3_REG_RX_ERR_CNT_1 (0x0000)
+
+// Tags
+#define DACCODE_WRITE (0x00)
+#define CONFIG_WRITE (0x01)
+
+// Valid Symbols
+#define ZERO_SYM (0x00)
+#define ONE_SYM (0x01)
+#define IDLE_SYM (0x02)
+#define STATIC_LOW_SYM (0x03)
+
+// DAC Codes for different currents
+#define DACCODE_0mA (0x0000)
+#define DACCODE_4mA (0x2AAA)
+#define DACCODE_8mA (0x5555)
+#define DACCODE_12mA (0x7FFF)
+#define DACCODE_16mA (0xAAAA)
+#define DACCODE_20mA (0xD555)
+#define DACCODE_24mA (0xFFFF)
+
+// cycles
+// #define QUARTER_CYCLES (625)
+// #define HALF_CYCLES (1250)
+// #define THREE_CYCLES (1875)
+// #define FULL_CYCLES (2500)
+
+typedef struct
+{
+ gpio_t *io;
+} dac161p997_t;
+
+void dac161p997_output_0(void);
+void dac161p997_output_1(void);
+void dac161p997_output_d(void);
+void dac161p997_output_symbol(uint8_t sym);
+void dac161p997_swif_write_reg(uint16_t data, uint8_t tag);
+extern void dac161p997_output_current(float32 current);
+extern void dac161p997_init(void);
+#endif
diff --git a/User/board/inc/eeprom_fm24.h b/User/board/inc/eeprom_fm24.h
index a11409c..dde5f13 100644
--- a/User/board/inc/eeprom_fm24.h
+++ b/User/board/inc/eeprom_fm24.h
@@ -9,7 +9,7 @@
#ifndef __EEPROM_FM24_H__
#define __EEPROM_FM24_H__
#include "main.h"
-
+#include "spis.h"
//========在此设定芯片地址=============
#define W_ADD_COM 0xa0 // 写字节命令及器件地址(根据地址实际情况改变), 1010 A2 A1 A0 0
@@ -47,13 +47,44 @@
#define FM24_PAGE_SIZE 256
#define FM24_SIZE (16384)
#elif e2prom == 256
-#define FM24_PAGE_SIZE 512
-#define FM24_SIZE (32768) // 32K
+#define FM24_PAGE_SIZE 256
+#define FM24_SIZE (32768) // 32K 128页
#elif e2prom == 512
#define FM24_PAGE_SIZE 512
#define FM24_SIZE (65536)
#endif
+#define FM24_CMD_RDSR 0x05 /*!< Read Status Register instruction */
+#define FM24_CMD_WRSR 0x01 /*!< Write Status Register instruction */
+
+#define FM24_CMD_WREN 0x06 /*!< Write enable instruction */
+#define FM24_CMD_WRDI 0x04 /*!< Write disable instruction */
+
+#define FM24_CMD_READ 0x03 /*!< Read from Memory instruction */
+#define FM24_CMD_WRITE 0x02 /*!< Write to Memory instruction */
+
+#define FM24_DUMMY_BYTE 0x00 ///< 无用数据
+
+typedef union
+{
+ uint8_t data;
+ struct
+ {
+ uint8_t reserve1 : 1;
+ uint8_t wel : 1; ///< Write enable latch
+ uint8_t bp0 : 1; ///< Block protect 0
+ uint8_t bp1 : 1; ///< Block protect 1
+ uint8_t reserve2 : 3;
+ uint8_t wpen : 1; ///< Write protect enable
+ } bits;
+} fm24_write_protection_u;
+
+typedef struct
+{
+ fm24_write_protection_u write_protection;
+ spi_t *spi;
+} fm24_t;
+
/**
* @brief Initializes the FM24 EEPROM module.
*/
@@ -64,6 +95,12 @@ extern void eeprom_fm24_init(void);
*/
extern void eeprom_fm24_dinit(void);
+/**
+ * @brief Gets the fm24_t handle of the FM24 EEPROM module.
+ * @return The fm24_t handle of the FM24 EEPROM module.
+ */
+extern fm24_t *eeprom_fm24_get(void);
+
/**
* @brief Enables the FM24 EEPROM module.
*/
@@ -92,6 +129,17 @@ extern BOOL eeprom_fm24_read(uint32_t read_addr, uint8_t *data, uint16_t length)
*/
extern BOOL eeprom_fm24_write(uint32_t write_addr, uint8_t *data, uint16_t length);
+/**
+ * @brief Closes the write protection of the FM24 EEPROM module.
+ */
+extern void eeprom_fm24_write_protection_close(void);
+
+/**
+ * @brief Gets the write protection state of the FM24 EEPROM module.
+ * @return TRUE if the FM24 EEPROM module is not write-protected, FALSE otherwise.
+ */
+extern BOOL eeprom_fm24_write_protection_state(void);
+
/**
* @brief Performs a test on the FM24 EEPROM module.
*/
diff --git a/User/board/inc/eeprom_lc02b.h b/User/board/inc/eeprom_lc02b.h
index 214ea9e..aaf9700 100644
--- a/User/board/inc/eeprom_lc02b.h
+++ b/User/board/inc/eeprom_lc02b.h
@@ -10,7 +10,7 @@
#include "main.h"
#include "entity.h"
-
+#define PRRESSURE_CALIBRATION_ADDRESS 0x00 ///< 压力校准地址
/**
* @brief Initializes the LC02B EEPROM module.
@@ -44,4 +44,4 @@ void eeprom_lc02b_read(uint32_t read_addr, uint8_t *data, uint16_t length);
* @brief Performs a test on the LC02B EEPROM module.
*/
void eeprom_lc02b_test(void);
-#endif // !__EEPROM_LC02B_H
+#endif ///< !__EEPROM_LC02B_H
diff --git a/User/board/inc/eeprom_m95.h b/User/board/inc/eeprom_m95.h
index 0adb7c9..30f287e 100644
--- a/User/board/inc/eeprom_m95.h
+++ b/User/board/inc/eeprom_m95.h
@@ -9,7 +9,7 @@
#ifndef __EEPROM_M95_H
#define __EEPROM_M95_H
#include "main.h"
-#include "entity.h"
+#include "spis.h"
#define _M95010_ 128
#define _M95020_ 256
@@ -23,8 +23,8 @@
#define _M95128_ 16384
#define _M95256_ 32768
-#define _M95512_ 65536 // 65K
-#define _M95M02_ 262144 // 256K
+#define _M95512_ 65536 ///< 65K
+#define _M95M02_ 262144 ///< 256K
#define _M95_SIZE _M95512_
@@ -37,22 +37,22 @@
#define M95_CMD_READ 0x03 /*!< Read from Memory instruction */
#define M95_CMD_WRITE 0x02 /*!< Write to Memory instruction */
-// Instruction available only for the M95_2-D device.
+///< Instruction available only for the M95_2-D device.
#define M95_CMD_RDID 0x83 /*!< Read identification page*/
#define M95_CMD_WRID 0x82 /*!< Write identification page*/
#define M95_CMD_RDLS 0x83 /*!< Reads the Identification page lock status*/
#define M95_CMD_LID 0x82 /*!< Locks the Identification page in read-only mode*/
-#define M95_DUMMY_BYTE 0xA5 // 虚拟字节
+#define M95_DUMMY_BYTE 0xA5 ///< 虚拟字节
-// 定义存储器大小(Bytes)
+///< 定义存储器大小(Bytes)
typedef enum
{
- M95_PAGE_SIZE_16 = 16, // _M95010_ 、_M95020_ 、_M95040_
- M95_PAGE_SIZE_32 = 32, // _M95080_ 、_M95160_、_M95320_、_M95640_
- M95_PAGE_SIZE_64 = 64, // _M95128_、_M95256_
- M95_PAGE_SIZE_128 = 128, // _M95512_
- M95_PAGE_SIZE_256 = 256, // _M95M02_
+ M95_PAGE_SIZE_16 = 16, ///< _M95010_ 、_M95020_ 、_M95040_
+ M95_PAGE_SIZE_32 = 32, ///< _M95080_ 、_M95160_、_M95320_、_M95640_
+ M95_PAGE_SIZE_64 = 64, ///< _M95128_、_M95256_
+ M95_PAGE_SIZE_128 = 128, ///< _M95512_
+ M95_PAGE_SIZE_256 = 256, ///< _M95M02_
} m95_page_size_e;
typedef enum
@@ -60,21 +60,30 @@ typedef enum
M95_1,
M95_2,
M95_MAX,
-} m95_number_e; // 板卡上2块m95芯片定义
+} m95_number_e; ///< 板卡上2块m95芯片定义
+
+typedef union
+{
+ uint8_t data;
+ struct
+ {
+ uint8_t wip : 1; ///< Write in progress
+ uint8_t wel : 1; ///< Write enable latch
+ uint8_t bp0 : 1; ///< Block protect 0
+ uint8_t bp1 : 1; ///< Block protect 1
+ uint8_t reserve : 3;
+ uint8_t srwd : 1; ///< Status register write protect
+ } bits;
+} m95_write_protection_u;
typedef struct
{
m95_number_e num;
- uint32_t page_size;
- uint32_t total_size;
+ m95_write_protection_u write_protection;
spi_t *spi;
- uint8_t address_bytes; // M95M02 地址大小3个字节,其余M95型号芯片为2个字节
- uint8_t *rxbuf;
- uint8_t *txbuf;
} m95_number_t;
-extern __IO m95_number_e current_m95_number; ///< 当前使用的m95芯片编号
-extern m95_number_t eeprom_m95s[M95_MAX]; ///< m95芯片数组
+extern m95_number_t eeprom_m95s[M95_MAX]; ///< m95芯片数组
/**
* @brief Initializes the M95 EEPROM module.
@@ -100,6 +109,20 @@ extern void eeprom_m95_enable(void);
*/
extern void eeprom_m95_disable(void);
+/**
+ * @brief Closes the write protection of the M95 EEPROM module.
+ *
+ * @param num The M95 EEPROM number.
+ */
+extern void eeprom_m95_write_protection_close(m95_number_e num);
+
+/**
+ * @brief write protection state of the M95 EEPROM module.
+ *
+ * @param num The M95 EEPROM number.
+ */
+extern BOOL eeprom_m95_write_protection_state(m95_number_e num);
+
/**
* @brief Reads data from the M95 EEPROM module.
*
@@ -108,7 +131,7 @@ extern void eeprom_m95_disable(void);
* @param data The buffer to store the read data.
* @param length The number of bytes to read.
*/
-extern void eeprom_m95_read(m95_number_e num, uint32_t read_addr, uint8_t *data, uint16_t length);
+extern BOOL eeprom_m95_read(m95_number_e num, uint32_t read_addr, uint8_t *data, uint16_t length);
/**
* @brief Writes data to the M95 EEPROM module.
@@ -118,7 +141,7 @@ extern void eeprom_m95_read(m95_number_e num, uint32_t read_addr, uint8_t *data,
* @param data The data to write.
* @param length The number of bytes to write.
*/
-extern void eeprom_m95_write(m95_number_e num, uint32_t write_addr, uint8_t *data, uint16_t length);
+extern BOOL eeprom_m95_write(m95_number_e num, uint32_t write_addr, uint8_t *data, uint16_t length);
/**
* @brief Performs a test on the M95 EEPROM module.
@@ -126,4 +149,9 @@ extern void eeprom_m95_write(m95_number_e num, uint32_t write_addr, uint8_t *dat
* @param num The M95 EEPROM number.
*/
extern void eeprom_m95_test(m95_number_e num);
-#endif // __EEPROM_M95_H
+
+extern BOOL eeprom_m95_1_read(uint32_t addr, uint8_t *buf, uint16_t size);
+extern BOOL eeprom_m95_1_write(uint32_t addr, uint8_t *buf, uint16_t size);
+extern BOOL eeprom_m95_2_read(uint32_t addr, uint8_t *buf, uint16_t size);
+extern BOOL eeprom_m95_2_write(uint32_t addr, uint8_t *buf, uint16_t size);
+#endif ///< __EEPROM_M95_H
diff --git a/User/board/inc/leds.h b/User/board/inc/leds.h
index 4d0ba3d..c70094b 100644
--- a/User/board/inc/leds.h
+++ b/User/board/inc/leds.h
@@ -4,11 +4,11 @@
#include "lib.h"
typedef enum
{
- LEDS_1_RED,
- LEDS_1_GREEN,
- LEDS_1_YELLOW,
- LEDS_2_ORANGE,
- LEDS_2_BLUE,
+ LEDS_RED,
+ LEDS_GREEN,
+ LEDS_YELLOW,
+ LEDS_ORANGE,
+ LEDS_BLUE,
LEDS_MAX,
} leds_e;
@@ -52,4 +52,4 @@ extern void leds_off_all(void);
* @param led The LED to toggle.
*/
extern void leds_toggle(leds_e led);
-#endif // !__LEDS_H__
+#endif ///< !__LEDS_H__
diff --git a/User/board/inc/ntc_3950.h b/User/board/inc/ntc_3950.h
index c22c39b..a5e19f9 100644
--- a/User/board/inc/ntc_3950.h
+++ b/User/board/inc/ntc_3950.h
@@ -12,4 +12,4 @@
extern float32_u ntc_get_temp(uint16_t adc); ///< 获取温度值
-#endif // __NTC_B3950_H__
+#endif ///< __NTC_B3950_H__
diff --git a/User/board/inc/rtc_rx8010.h b/User/board/inc/rtc_rx8010.h
index 41675b4..5fc384a 100644
--- a/User/board/inc/rtc_rx8010.h
+++ b/User/board/inc/rtc_rx8010.h
@@ -40,17 +40,17 @@ typedef enum
THUR = BIT4,
FRI = BIT5,
SAT = BIT6
-} rtc_week_e; // 星期码
+} rtc_week_e; ///< 星期码
typedef struct
{
- uint8_t year; // 7 bit - 1 63
- uint8_t month; // 4 bit
- uint8_t day; // 5 bit
- uint8_t weekday; // rtc_week_e
- uint8_t hour; // 5 bit
- uint8_t minute; // 6 bit
- uint8_t second; // 6 bit
+ uint8_t year; ///< 7 bit - 1 63
+ uint8_t month; ///< 4 bit
+ uint8_t day; ///< 5 bit
+ uint8_t weekday; ///< rtc_week_e
+ uint8_t hour; ///< 5 bit
+ uint8_t minute; ///< 6 bit
+ uint8_t second; ///< 6 bit
} rtc_date;
/**
@@ -79,6 +79,12 @@ extern BOOL rtc_get_clock_time(uint8_t *read_buf);
*/
extern BOOL rtc_set_clock_time(rtc_date *data);
+/**
+ * @brief Retrieves the current alarm time from the RTC module.
+ * @param read_buf Pointer to the buffer to store the alarm time.
+ * @return TRUE if the alarm time is successfully retrieved, FALSE otherwise.
+ */
+extern uint32_t rtc_timestamp(void);
/**
* @brief Converts the weekday value to a human-readable format.
* @param weekday Pointer to the weekday value to be converted.
@@ -90,4 +96,4 @@ extern void rtc_weekday_convert(uint8_t *weekday);
* @param weekday Pointer to the weekday value to be converted.
*/
extern void rtc_weekday_rconvert(uint8_t *weekday);
-#endif // !__RTC_RX8010_H__
+#endif ///< !__RTC_RX8010_H__
diff --git a/User/board/inc/sht40.h b/User/board/inc/sht40.h
new file mode 100644
index 0000000..4a6af98
--- /dev/null
+++ b/User/board/inc/sht40.h
@@ -0,0 +1,9 @@
+#ifndef __SHT40_H
+#define __SHT40_H
+#include "main.h"
+
+void sht40_init(void); ///< 初始化 SHT40 传感器
+void sht40_dinit(void); ///< 反初始化 SHT40 传感器
+BOOL sht40_read(float32 *temperature, float32 *humidity); ///< 读取温湿度传感器数据
+
+#endif ///< !__SHT40_H
diff --git a/User/board/src/board.c b/User/board/src/board.c
deleted file mode 100644
index 9bca3b8..0000000
--- a/User/board/src/board.c
+++ /dev/null
@@ -1,1053 +0,0 @@
-/**
- * @file board.c
- * @author xxx
- * @date 2023-09-12 13:52:37
- * @brief
- * @copyright Copyright (c) 2023 by xxx, All Rights Reserved.
- */
-#include "board.h"
-#include "entity.h"
-#include "delay.h"
-
-#include "filter.h"
-void SystemClock_Config(void);
-
-static BOOL driver_init_flag = FALSE;
-
-static uint16_t board_cache[BOARD_CACHE_MAX]; ///< 调节缓存
-static lpf_t lpf_temperature; ///< 温度滤波器
-__IO static BOOL system_clock_config_flag = FALSE; ///< 系统时钟配置改变标志
-
-__IO uint8_t app_preload_flag __attribute__((at(APP_PRELOAD_AREA))); // 预加载标志
-__IO uint8_t app_preload_language_flag __attribute__((at(APP_PRELOAD_AREA + 1))); // 语言标志
-__IO uint8_t app_preload_bootload_flag __attribute__((at(APP_PRELOAD_AREA + 2))); // 触发BOOTLOAD启动标志(在用户代码中接受代码文件)
-__IO uint8_t app_preload_bootload_jump_flag __attribute__((at(APP_PRELOAD_AREA + 3))); // 触发BOOTLOAD跳转更新标志(在BOOTLOAD代码中更新用户代码)
-__IO uint32_t app_preload_cupid_encrypt __attribute__((at(APP_PRELOAD_AREA + 4))); // 加密后的CPUID
-/***************************************** 板卡初始化相关函数 *****************************************/
-
-/**
- * @brief LCD设计
- * @return {*}
- * @note
- */
-void lcd_design(void)
-{
-}
-
-/**
- * @brief LCD初始化
- * @return {*}
- * @note
- */
-void lcd_init(void)
-{
- // 设置功能引脚
- GPIO_SET_OUTPUT(LCD_PWR_GPIO_Port, LCD_PWR_Pin);
- GPIO_SET_OUTPUT(LCD_CS_GPIO_Port, LCD_CS_Pin);
- GPIO_SET_OUTPUT(LCD_DISP_GPIO_Port, LCD_DISP_Pin);
-
- if (0 == LCD_IS_POWER_ON())
- {
- }
-}
-
-/**
- * @brief LCD反初始化
- * @return {*}
- * @note
- */
-void lcd_dinit(void)
-{
-}
-
-/**
- * @brief 功耗引脚初始化
- * @return {*}
- * @note
- */
-void driver_init(void)
-{
- // 标志位检查:driver_init_flag = TRUE,表示已经初始化
- if (driver_init_flag == TRUE)
- {
- return;
- }
- driver_init_flag = TRUE;
-
- pdctrl_run(); // 控制输出使能
- PWM_START(TIM3, LL_TIM_CHANNEL_CH3); // PWM OUT使能
-}
-
-/**
- * @brief 功耗引脚反初始化
- * @return {*}
- * @note
- */
-void driver_dinit(void)
-{
- // 标志位检查:driver_init_flag = FALSE,表示已经反初始化
- if (driver_init_flag == FALSE)
- {
- return;
- }
- driver_init_flag = FALSE;
-
- pdctrl_stop(); // 控制输出禁用
- PWM_STOP(TIM3, LL_TIM_CHANNEL_CH3); // PWM OUT禁用
-}
-
-/**
- * @brief 板卡初始化
- * @return {*}
- * @note
- */
-void board_init(void)
-{
- VIP_H_EN_DISABLE(); // IP禁用,满足条件时才使能
-
- adc_init(ADCS_1, ADC1, DMA1, LL_DMA_CHANNEL_1, 30,
- IN5 | IN6 | IN7 | IN8 | IN9 | IN11 | IN12 | IN13 | IN14 | INTEMP | INVREF); // 初始化ADC1通道,默认采集AD
-
- adc_init(ADCS_2, ADC2, DMA1, LL_DMA_CHANNEL_2, 10,
- IN5 | IN6); // 初始化ADC2通道,慢速采集通道
-
- rtc_init(); // 初始化RTC
- eeprom_m95_init(M95_1); // 初始化SPI EEPROM1
- eeprom_m95_init(M95_2); // 初始化SPI EEPROM2
- eeprom_fm24_init(); // 初始化 IIC EEPROM
- eeprom_lc02b_init(); // 初始化 IIC EEPROM
- leds_init(); // 初始化LED
-
- lpf_init(&lpf_temperature);
- system_clock_config_low();
- // debug_freeze_watchdog(); // 冻结看门狗
-}
-
-void board_dinit(void)
-{
- adc_dinit(ADCS_1); // ADC反初始化
- DISABLE_TIM(TIM6);
- DISABLE_TIM(TIM7);
- driver_dinit();
-
- rtc_dinit(); // RTC反初始化
- eeprom_m95_dinit(M95_1);
- eeprom_m95_dinit(M95_2);
- eeprom_fm24_dinit();
- eeprom_lc02b_dinit();
- leds_dinit(); // LED Deinitialization
- lcd_dinit(); // LCD screen Deinitialization
-}
-
-/**
- * @brief 板卡工作暂停
- * @return {*}
- * @note 在用户层处理bootload接收数据时需要暂时关闭一些应用层的处理
- */
-void board_work_stop_or_run(void)
-{
- static BOOL stop_or_run_state = FALSE;
-
- if (get_app_preload_bootload_flag() != stop_or_run_state)
- {
- // 如果stop_or_run_state是FALSE,那么app_preload_bootload_flag是TRUE,表示当前需要暂停工作
- // 目前先暂停TIM7控制模块,TIM6的任务执行不受影响,因为任务模块会执行最简单的任务
- if (stop_or_run_state == FALSE)
- {
- DISABLE_TIM(TIM7);
- }
- else
- {
- ENABLE_TIM(TIM7);
- }
- stop_or_run_state = get_app_preload_bootload_flag();
- }
-}
-
-/**
- * @brief 缓存数据初始化
- * @return {*}
- * @note
- */
-void board_cache_reset(void)
-{
- for (uint8_t i = 0; i < BOARD_CACHE_MAX; i++)
- {
- board_cache[i] = 0;
- }
-}
-
-/**
- * @brief 缓存数据获取
- * @param {board_cache_e} index
- * @return {*}
- * @note
- */
-uint16_t board_cache_get(board_cache_e index)
-{
- return board_cache[index];
-}
-
-/**
- * @brief 系统时钟配置低频
- * @return {*}
- * @note 2M 默认使用系统时钟配置低频
- */
-// static void system_clock_config_low_2m(void)
-//{
-// LL_FLASH_SetLatency(LL_FLASH_LATENCY_0);
-// while (LL_FLASH_GetLatency() != LL_FLASH_LATENCY_0)
-// {
-// }
-// LL_PWR_SetRegulVoltageScaling(LL_PWR_REGU_VOLTAGE_SCALE1);
-// while (LL_PWR_IsActiveFlag_VOS() != 0)
-// {
-// }
-// LL_RCC_HSE_Enable();
-
-// /* Wait till HSE is ready */
-// while (LL_RCC_HSE_IsReady() != 1)
-// {
-// }
-// LL_RCC_PLL_ConfigDomain_SYS(LL_RCC_PLLSOURCE_HSE, LL_RCC_PLLM_DIV_1, 8, LL_RCC_PLLR_DIV_2);
-// LL_RCC_PLL_EnableDomain_SYS();
-// LL_RCC_PLL_Enable();
-
-// /* Wait till PLL is ready */
-// while (LL_RCC_PLL_IsReady() != 1)
-// {
-// }
-// LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL);
-
-// /* Wait till System clock is ready */
-// while (LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_PLL)
-// {
-// }
-// LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_16);
-// LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_1);
-// LL_RCC_SetAPB2Prescaler(LL_RCC_APB2_DIV_1);
-
-// LL_Init1msTick(2000000);
-
-// LL_SetSystemCoreClock(2000000);
-//}
-
-void system_clock_config_set_flag(BOOL flag)
-{
- system_clock_config_flag = flag;
-}
-
-/**
- * @brief 系统时钟配置低频
- * @return {*}
- * @note 4M 默认使用系统时钟配置低频
- */
-void system_clock_config_low(void)
-{
- if (system_clock_config_flag == FALSE)
- {
- return;
- }
- system_clock_config_set_flag(FALSE);
-
- // if (udevice.dev_algorithm_mode == MODE_VARIABLE_FREQUENCY_CONTROL_ALGORITHM)
- // {
- // system_clock_config_low_2m();
- // }
- // else
- // {
- // SystemClock_Config();
- // }
- SystemClock_Config();
-
- uint32_t hclk = SystemCoreClock / 1000000;
- delay_init(hclk);
- uint16_t pres = (hclk * 100) - 1;
- if (LL_TIM_GetPrescaler(TIM6) != pres)
- {
- LL_TIM_SetPrescaler(TIM6, pres);
- }
- if (LL_TIM_GetPrescaler(TIM7) != pres)
- {
- LL_TIM_SetPrescaler(TIM7, pres);
- }
- uint32_t reload = (hclk * 1000) - 1;
- pdctrl_pwm_set_arr(reload);
- if (LL_TIM_GetAutoReload(TIM3) != reload)
- {
- LL_TIM_SetAutoReload(TIM3, reload);
- }
-}
-
-/**
- * @brief 系统时钟配置高频
- * @return {*}
- * @note 16M
- */
-void system_clock_config_hight(void)
-{
- if (system_clock_config_flag == FALSE)
- {
- return;
- }
-
- LL_FLASH_SetLatency(LL_FLASH_LATENCY_0);
- while (LL_FLASH_GetLatency() != LL_FLASH_LATENCY_0)
- {
- }
- LL_PWR_SetRegulVoltageScaling(LL_PWR_REGU_VOLTAGE_SCALE1);
- while (LL_PWR_IsActiveFlag_VOS() != 0)
- {
- }
- LL_RCC_HSE_Enable();
-
- /* Wait till HSE is ready */
- while (LL_RCC_HSE_IsReady() != 1)
- {
- }
- LL_RCC_PLL_ConfigDomain_SYS(LL_RCC_PLLSOURCE_HSE, LL_RCC_PLLM_DIV_1, 8, LL_RCC_PLLR_DIV_2);
- LL_RCC_PLL_EnableDomain_SYS();
- LL_RCC_PLL_Enable();
-
- /* Wait till PLL is ready */
- while (LL_RCC_PLL_IsReady() != 1)
- {
- }
- LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL);
-
- /* Wait till System clock is ready */
- while (LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_PLL)
- {
- }
- LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_2);
- LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_1);
- LL_RCC_SetAPB2Prescaler(LL_RCC_APB2_DIV_1);
-
- LL_Init1msTick(16000000);
-
- LL_SetSystemCoreClock(16000000);
-
- uint32_t hclk = SystemCoreClock / 1000000;
- uint16_t pres = (hclk * 100) - 1;
- if (LL_TIM_GetPrescaler(TIM6) != pres)
- {
- LL_TIM_SetPrescaler(TIM6, pres);
- }
- if (LL_TIM_GetPrescaler(TIM7) != pres)
- {
- LL_TIM_SetPrescaler(TIM7, pres);
- }
- uint32_t reload = (hclk * 1000) - 1;
- pdctrl_pwm_set_arr(reload);
- if (LL_TIM_GetAutoReload(TIM3) != reload)
- {
- LL_TIM_SetAutoReload(TIM3, reload);
- }
-}
-
-/***************************************** 板卡LCD操作相关函数 *****************************************/
-
-/**
- * @brief LCD刷新
- * @return {*}
- * @note
- */
-void gui_flush(void)
-{
-}
-
-/**
- * @brief LCD刷新并清除缓存
- * @return {*}
- * @note
- */
-void gui_flush_Clear(void)
-{
-}
-
-/**
- * @brief LCD全屏清除
- * @return {*}
- * @note
- */
-void gui_clr(void)
-{
-}
-
-/**
- * @brief LCD设置清屏标志
- * @return {*}
- * @note
- */
-void gui_set_clear_flag(void)
-{
-}
-
-/**
- * @brief LCD获取清屏标志
- * @return {*}
- * @note
- */
-BOOL gui_get_clear_flag(void)
-{
- return TRUE;
-}
-
-/**
- * @brief LCD全屏填充
- * @return {*}
- * @note
- */
-void gui_full(void)
-{
-}
-
-/**
- * @brief LCD启动
- * @return {*}
- * @note
- */
-void gui_open()
-{
-}
-
-/**
- * @brief LCD关闭
- * @return {*}
- * @note
- */
-void gui_close()
-{
-}
-
-/**
- * @brief 设置扫描方向
- * @return {*}
- * @note
- */
-void gui_set_scandir(uint8_t dir)
-{
-}
-
-/***************************************** 板卡参数相关函数 *****************************************/
-/**
- * @brief 根据目标行程计算DAC输出理论值
- * @param {float32} output - 目标行程(百分比)
- * @return {uint16_t} DAC输出理论值
- * @note 计算公式如下:
- * > (Osh-Osl)/(Ish-Isl)=(Ov-Osl)/(Iv-Isl)
- * > Ov=[(Osh-Osl)*(Iv-Isl)/(Ish-Isl)]+Osl
- */
-uint16_t get_dac(float32 output)
-{
- return ((udevice.output_max - udevice.output_min) * (output - 0) / (100 - 0)) + udevice.output_min;
-}
-
-/**
- * @brief PWM输出阀位百分比
- * @param {float32} position_per-阀位百分比
- * @return {*}
- * @note 阀位反馈输出, 0%输出4.00mA, 100.0%输出20.00mA
- *> 0% - 4.0mA
- *> 10% - 5.6mA
- *> 20% - 7.2mA
- *> 30% - 8.8mA
- *> 40% - 10.4mA
- *> 50% - 12.0mA
- *> 55% - 12.8mA
- *> 60% - 13.6mA
- *> 70% - 15.2mA
- *> 80% - 16.8mA
- *> 90% - 18.4mA
- *> 100% - 20.0mA
- */
-void pwm_output_position(float32 position_per)
-{
- float32 ftemp = 0;
-
- // 根据阀位百分比计算对应的电流
- ftemp = position_per;
- ftemp *= 16;
- ftemp += 400;
-
- // 根据校准参数计算占空比
- ftemp *= calib_param[CALIBPARA_VIP].value[0];
- ftemp += calib_param[CALIBPARA_VIP].value[1];
-
- // PWM输出
- PWM_SET_DUTY(TIM2, 4, ftemp);
-}
-
-/**
- * @brief 校准4-20mA输出电流
- * @return {*}
- * @note
- */
-void calib_loop(void)
-{
-#define MA4 (LOOP_CURRENT_MIN * 1000)
-#define MA20 (LOOP_CURRENT_MAX * 1000)
- uint16_t ma = 0, adc = 0;
- float32 f;
- // 计算校准参数
- ma = MA20 - MA4;
- adc = board_cache[BOARD_CACHE_2] - board_cache[BOARD_CACHE_1];
- f = ma;
- f = f / adc;
- calib_param[CALIBPARA_LOOP].value[0] = f / 10;
- f = f * board_cache[BOARD_CACHE_2];
- calib_param[CALIBPARA_LOOP].value[1] = (MA20 - f) / 10;
-
- calib_param[CALIBPARA_LOOP].is_calibration = TRUE;
-}
-
-/**
- * @brief 校准压力表
- * @return {*}
- * @note
- */
-void calib_kpa(void)
-{
-#define PRESSURE_200_KPA 200.0f // 200kPa
-#define PRESSURE_400_KPA 400.0f // 400kPa
- uint16_t ma = 0, adc = 0;
- float32 f;
- // 计算校准参数
- ma = PRESSURE_400_KPA - PRESSURE_200_KPA;
- adc = board_cache[BOARD_CACHE_2] - board_cache[BOARD_CACHE_1];
- f = ma;
- f = f / adc;
- calib_param[CALIBPARA_PS].value[0] = f;
- f = f * board_cache[BOARD_CACHE_2];
- calib_param[CALIBPARA_PS].value[1] = PRESSURE_400_KPA - f;
-
- calib_param[CALIBPARA_PSB].value[0] = calib_param[CALIBPARA_PS].value[0];
- calib_param[CALIBPARA_PSB].value[1] = calib_param[CALIBPARA_PS].value[1];
-
- calib_param[CALIBPARA_PB].value[0] = calib_param[CALIBPARA_PS].value[0];
- calib_param[CALIBPARA_PB].value[1] = calib_param[CALIBPARA_PS].value[1];
-}
-
-/**
- * @brief 校准4-20mA输出电流
- * @return {*}
- * @note
- */
-void calib_pwm_out(void)
-{
- // 计算校准参数
- float32 mA4 = 400;
- float32 mA20 = 2000;
- float32 TDuty4 = board_cache[BOARD_CACHE_1];
- float32 TDuty20 = board_cache[BOARD_CACHE_2];
- calib_param[CALIBPARA_VIP].value[0] = (TDuty20 - TDuty4) / (mA20 - mA4);
- calib_param[CALIBPARA_VIP].value[1] = TDuty20 - calib_param[CALIBPARA_VIP].value[0] * mA20;
-}
-/**
- * @brief 校准阀门位置参数,电压转换成%(放大10倍,1位小数)
- * @return {*}
- * @note 计算公式如下:
- * > k = (y2-y1) / (x2-x1)
- * > m = y2 - k * x2
- */
-void calib_parapos_perent(void)
-{
- float32 ftmp = 0.0;
-
- // 直行程位置反馈
- ftmp = udevice.pos100_travel_vol - udevice.pos0_travel_vol;
- calib_param[CALIBPARA_PSB].value[0] = 100 / ftmp;
-
- ftmp = calib_param[CALIBPARA_PSB].value[0] * udevice.pos100_travel_vol;
- calib_param[CALIBPARA_PSB].value[1] = 100 - ftmp;
- calib_param[CALIBPARA_PSB].is_calibration = TRUE;
-
- // 小回路
- ftmp = udevice.pos100_minor_vol - udevice.pos0_minor_vol;
- calib_param[CALIBPARA_IPSB].value[0] = 100 / ftmp;
-
- ftmp = calib_param[CALIBPARA_IPSB].value[0] * udevice.pos100_minor_vol;
- calib_param[CALIBPARA_IPSB].value[1] = 100 - ftmp;
-
- calib_param[CALIBPARA_IPSB].is_calibration = TRUE;
-}
-
-/**
- * @brief 获取当前实际行程ADC值
- * @return {*}
- * @note
- */
-uint16_t get_actual_travel_adc(void)
-{
- adc_raw[ADC_PSB_CHANNEL] = adc_result_median(ADCS_1, ADC_PSB_CHANNEL);
- return adc_raw[ADC_PSB_CHANNEL];
-}
-
-/**
- * @brief 获取当前实际行程ADC值
- * @return {*}
- * @note
- */
-uint16_t get_actual_travel_adc_average(void)
-{
- adc_raw[ADC_PSB_CHANNEL] = adc_result_average(ADCS_1, ADC_PSB_CHANNEL);
- return adc_raw[ADC_PSB_CHANNEL];
-}
-
-/**
- * @brief 获取当前实际行程百分比
- * @param {uint16_t} adc
- * @return {*}
- * @note
- */
-float32 actual_adc_convert_percent(uint16_t adc)
-{
- float32 f = adc * 1.0f;
- // 计算当前位置
- f *= calib_param[CALIBPARA_PSB].value[0];
- f += calib_param[CALIBPARA_PSB].value[1];
- if (f < 0)
- {
- f = 0;
- }
- if (f > 100)
- {
- f = 100;
- }
-
- return f;
-}
-
-/**
- * @brief 获取当前实际行程
- * @param {uint8_t} filter 1:平均 2:中值
- * @return {*}
- * @note
- */
-float32 get_actual_travel(filter_e filter)
-{
- uint16_t raw = 0;
-
- // 读取位置反馈ADC值
- if (filter == FILTER_AVERAGE)
- {
- raw = adc_result_average(ADCS_1, ADC_PSB_CHANNEL);
- }
- else if (filter == FILTER_MEDIAN)
- {
- raw = adc_result_median(ADCS_1, ADC_PSB_CHANNEL);
- }
- else
- {
- raw = adc_result_average(ADCS_1, ADC_PSB_CHANNEL);
- }
-
- adc_raw[ADC_PSB_CHANNEL] = raw;
- return actual_adc_convert_percent(raw);
-}
-
-/**
- * @brief 获取当前实际行程
- * @param {uint8_t} filter 1:平均 2:中值
- * @return {*}
- * @note
- */
-float32 get_actual_travel_2(filter_e filter)
-{
- uint16_t raw = 0;
-
- // 读取位置反馈ADC值
- if (filter == FILTER_AVERAGE)
- {
- raw = adc_result_average(ADCS_2, ADC_PSB_CHANNEL);
- }
- else if (filter == FILTER_MEDIAN)
- {
- raw = adc_result_median(ADCS_2, ADC_PSB_CHANNEL);
- }
- else
- {
- raw = adc_result_average(ADCS_2, ADC_PSB_CHANNEL);
- }
-
- adc_raw[ADC_PSB_CHANNEL] = raw;
- return actual_adc_convert_percent(raw);
-}
-
-/**
- * @brief 获取当前回路电流
- * @return {float32} 回路电流值
- * @note
- */
-float32 get_current(void)
-{
- float32 f = 0.0;
-
- // 读取回路电流ADC值
- adc_raw[ADC_LOOP_CHANNEL] = adc_result_median_average(ADCS_1, ADC_LOOP_CHANNEL);
- f = adc_raw[ADC_LOOP_CHANNEL];
-
- // 计算回路电流
- f *= calib_param[CALIBPARA_LOOP].value[0];
- f += calib_param[CALIBPARA_LOOP].value[1];
- f = f / 100;
-
- if (f < 0)
- {
- f = 0;
- }
-
- return f;
-}
-
-/**
- * @brief 获取当前回路电流,保留小数点后1位
- * @param {float32} current
- * @return {*}
- * @note
- */
-float32 get_current_deal(float32 current)
-{
- // 判断current小数点后第二位是否大于5
- if ((uint16_t)(current * 100) % 10 >= 5)
- {
- return (uint16_t)(current * 10) * 0.1f + 0.1f;
- }
- else
- {
- return (uint16_t)(current * 100) * 0.01f;
- }
-}
-
-/**
- * @brief 获取当前温度值
- * @return {float32} 温度值
- * @note
- */
-float32 get_temperature(void)
-{
- float32 tmp = 0.0f;
- // 采集ADC原始数据
- adc_raw[ADC_NTC_CHANNEL] = adc_result_average(ADCS_1, ADC_NTC_CHANNEL);
-
- // 使用NTC算法计算温度值
- tmp = ntc_get_temp(adc_raw[ADC_NTC_CHANNEL]).f;
- tmp = lpf_update(&lpf_temperature, tmp);
- return tmp;
-}
-
-/**
- * @brief 获取当前流量
- * @return {*}
- * @note
- */
-float32 get_flow(void)
-{
- float32 v = 0.0f;
- adc_raw[ADC_FLOW] = adc_result_average(ADCS_1, ADC_BPB_CHANNEL);
- v = ((CPU_VREF * adc_raw[ADC_FLOW] / ADC_MAX) - 0.4) * 600 / 1.6;
-
- return v < 0 ? 0 : v;
-}
-
-/**
- * @brief 获取当前压力
- * @return {float32} 压力值
- * @note
- */
-float32 get_pressure(pressure_index_e id)
-{
- float32 f = 0.0;
-
- switch (id)
- {
- case ADC_INDEX_PRESSSOURCE:
- // 读取气源压力ADC
- adc_raw[ADC_BP_CHANNEL] = adc_result_average(ADCS_1, ADC_BP_CHANNEL);
- f = adc_raw[ADC_BP_CHANNEL];
- // 计算气源压力
- f *= calib_param[CALIBPARA_PS].value[0];
- f += calib_param[CALIBPARA_PS].value[1];
- rt_data.pressure_s = f;
- break;
- case ADC_INDEX_PRESSOUTA:
- // 读取A路压力ADC
- adc_raw[ADC_BPA_CHANNEL] = adc_result_average(ADCS_1, ADC_BPA_CHANNEL);
- f = adc_raw[ADC_BPA_CHANNEL];
- // 计算A路压力
- f *= calib_param[CALIBPARA_PSB].value[0];
- f += calib_param[CALIBPARA_PSB].value[1];
- rt_data.pressure_a = f;
- break;
- case ADC_INDEX_PRESSOUTB:
- // 读取B路压力ADC
- adc_raw[ADC_BPB_CHANNEL] = adc_result_average(ADCS_1, ADC_BPB_CHANNEL);
- f = adc_raw[ADC_BPB_CHANNEL];
- // 计算B路压力
- f *= calib_param[CALIBPARA_PB].value[0];
- f += calib_param[CALIBPARA_PB].value[1];
- rt_data.pressure_b = f;
- break;
- default:
- break;
- }
- return f;
-}
-
-/***************************** 通过电阻测算,只在测试程序中使用 *****************************/
-/**
- * @brief 回路电流检测转换
- * @param {uint16_t} adc
- * @return {float32} 回路电流值
- * @note 计算公式如下:
- * > 压力和电流关系:(adc/4096)*VREF_VALUE/(5*20) = ma
- * > 简化后:adc*VREF_VALUE/409600 = ma
- */
-float32 loop_current_convert(uint16_t adc)
-{
- float32 f;
- f = ((float32)(adc * VREF_VALUE)) / 409600;
- return f;
-}
-
-/**
- * @brief DAC:IP输出电流值转换
- * @param {uint16_t} dac
- * @return {float32} IP输出电流值
- * @note
- */
-float32 ip_dac2current(uint16_t dac)
-{
- float32 vol = 0, cur = 0;
- // 计算电压值 mv
- vol = (float32)dac / 4096 * VREF_VALUE;
-
- // 计算电流值 ma
- cur = vol / (40 * 40);
-
- // 如果电流值大于2.5,则设置为2.5
- if (cur > 2.5f)
- {
- cur = 2.5;
- }
-
- return cur;
-}
-
-/**
- * @brief IP输出电流值转换
- * @return {*}
- * @note
- */
-float32 ip2current(void)
-{
- float32 cur = 0;
- adc_raw[ADC_VIP_CHANNEL] = adc_result_average(ADCS_1, ADC_VIP_CHANNEL);
- // 计算电流值 ma
- cur = (float32)adc_raw[ADC_VIP_CHANNEL] / (float32)(10 * 101);
- return cur;
-}
-
-/**
- * @brief PWM输出电流值转换
- * @param {float32} current
- * @return {*}
- * @note: 计算公式如下:
- * > I_OUT=3V*Duty/10K*100(mA)
- */
-void pwm_duty2current(float32 cur_ma)
-{
- float32 current;
-
- if (cur_ma < 4)
- current = 4;
- else if (cur_ma > 20)
- current = 20;
- else
- current = cur_ma;
-
- float32 duty = current / 30;
- uint16_t count = duty * 4095;
- PWM_CTRL_OUTPUT(count);
-}
-
-/**
- * @brief 获取RTC时间
- * @param {uDateTime_TypeDef} *time
- * @return {*}
- * @note
- */
-void get_timestamp(uDateTime_TypeDef *time)
-{
- uint8_t tmp[7];
- rtc_get_clock_time(tmp);
-
- time->Date.Year = tmp[6]; // 将年存储在data结构体的year字段中
- time->Date.Month = tmp[5]; // 将月存储在data结构体的month字段中
- time->Date.Day = tmp[4]; // 将日存储在data结构体的day字段中
- time->Date.Hour = tmp[2]; // 将时存储在data结构体的hour字段中
- time->Date.Minute = tmp[1]; // 将分存储在data结构体的minute字段中
- time->Date.Second = tmp[0]; // 将秒存储在data结构体的second字段中
-}
-
-void get_real_time(uint8_t *year, uint8_t *month, uint8_t *day, uint8_t *hour, uint8_t *min, uint8_t *sec)
-{
- get_timestamp((uDateTime_TypeDef *)&rt_data.save.real_time);
- *year = hex_format_dec(rt_data.save.real_time.Date.Year);
- *month = hex_format_dec(rt_data.save.real_time.Date.Month);
- *day = hex_format_dec(rt_data.save.real_time.Date.Day);
- *hour = hex_format_dec(rt_data.save.real_time.Date.Hour);
- *min = hex_format_dec(rt_data.save.real_time.Date.Minute);
- *sec = hex_format_dec(rt_data.save.real_time.Date.Second);
-}
-
-void set_real_time(uint8_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t min, uint8_t sec)
-{
- rtc_date date = {
- .year = year,
- .month = month,
- .day = day,
- .hour = hour,
- .minute = min,
- .second = sec,
- .weekday = get_weekday(2000 + hex_format_dec(year),
- hex_format_dec(month),
- hex_format_dec(day)),
- };
- rtc_weekday_convert(&date.weekday);
- rtc_set_clock_time(&date);
- get_timestamp((uDateTime_TypeDef *)&rt_data.save.real_time);
-}
-
-/**
- * @brief 设置输出PWM校准电流
- * @return {*}
- * @note 计算公式如下:
- * > y = k*x + m (x表示电流,y表示PWM占空比)
- * > k = (TDuty20 - TDuty4) / (mA20 - mA4)
- * > m = TDuty20 - k * mA20
- */
-
-void set_pwm_calib_current()
-{
- float32 mA4 = 400;
- float32 mA20 = 2000;
- float32 TDuty4 = udevice.output_4ma_duty;
- float32 TDuty20 = udevice.output_20ma_duty;
- calib_param[CALIBPARA_VIP].value[0] = (TDuty20 - TDuty4) / (mA20 - mA4);
- calib_param[CALIBPARA_VIP].value[1] = TDuty20 - calib_param[CALIBPARA_VIP].value[0] * mA20;
-}
-
-/**
- * @brief 读取4mA输入时的ADC电压
- * @return {*}
- */
-void set_loop_4ma(void)
-{
- board_cache[BOARD_CACHE_1] = adc_result_average(ADCS_1, ADC_LOOP_CHANNEL); // 获取4mA输入时adc值
-}
-
-/**
- * @brief 读取20mA输入时的ADC值
- * @return {*}
- */
-void set_loop_20ma(void)
-{
- board_cache[BOARD_CACHE_2] = adc_result_average(ADCS_1, ADC_LOOP_CHANNEL);
-}
-
-/**
- * @brief 读取200kPa输入时的ADC电压
- * @return {*}
- */
-void set_200kpa(void)
-{
- board_cache[BOARD_CACHE_1] = adc_result_average(ADCS_1, ADC_BP_CHANNEL); // 获取200kPa时adc值
-}
-
-/**
- * @brief 读取400kPa输入时的ADC电压
- * @return {*}
- */
-void set_400kpa(void)
-{
- board_cache[BOARD_CACHE_2] = adc_result_average(ADCS_1, ADC_BP_CHANNEL);
-}
-
-/**
- * @brief 记录输出4mA时的PWM值
- * @return {*}
- */
-void set_output_4ma_pwm(uint16_t value)
-{
- board_cache[BOARD_CACHE_1] = value;
-}
-
-/**
- * @brief 记录输出20mA时的PWM值
- * @return {*}
- */
-void set_output_20ma_pwm(uint16_t value)
-{
- board_cache[BOARD_CACHE_2] = value;
-}
-
-/**
- * @brief 设置语言预加载标志
- * @param {uint8_t} language
- * @return {*}
- * @note
- */
-void set_app_preload_language_flag(uint8_t flag)
-{
- if (app_preload_language_flag != flag)
- {
- app_preload_language_flag = flag;
- }
-}
-
-/**
- * @brief 设置预加载BOOTLOAD标志位
- * @param {uint8_t} flag
- * @return {*}
- * @note
- */
-void set_app_preload_bootload_flag(uint8_t flag)
-{
- if (app_preload_bootload_flag != flag)
- {
- app_preload_bootload_flag = flag;
- }
-}
-
-/**
- * @brief Get the application preload bootload flag
- * @return The application preload bootload flag
- */
-BOOL get_app_preload_bootload_flag(void)
-{
- return app_preload_bootload_flag;
-}
-
-/**
- * @brief 设置预加载BOOTLOAD标志位
- * @param {app_preload_bootload_jump_e} flag
- * @return {*}
- * @note
- */
-void set_app_preload_bootload_jump_flag(app_preload_bootload_jump_e flag)
-{
- if (app_preload_bootload_jump_flag != flag)
- {
- app_preload_bootload_jump_flag = flag;
- }
-}
-
-/**
- * @brief Get the application preload bootload jump flag
- * @return The application preload bootload jump flag
- */
-app_preload_bootload_jump_e get_app_preload_bootload_jump_flag(void)
-{
- return (app_preload_bootload_jump_e)app_preload_bootload_jump_flag;
-}
diff --git a/User/board/src/eeprom_fm24.c b/User/board/src/eeprom_fm24.c
deleted file mode 100644
index 2c1d1b7..0000000
--- a/User/board/src/eeprom_fm24.c
+++ /dev/null
@@ -1,178 +0,0 @@
-/**
- * @file eeprom_fm24.c
- * @author xxx
- * @date 2023-08-29 07:58:27
- * @brief 用于实现FM24 EEPROM相关的读写操作
- * @copyright Copyright (c) 2023 by xxx, All Rights Reserved.
- */
-#include "entity.h"
-#include "board.h"
-#include "eeprom_m95.h"
-#include "eeprom_fm24.h"
-#include "i2cs.h"
-#include "delay.h"
-#include "diagnosis.h"
-
-#define FM24_I2C I2C1
-#define FM24_DMA DMA1
-#define FM24_DMA_RX_CHANNEL LL_DMA_CHANNEL_7
-#define FM24_DMA_TX_CHANNEL LL_DMA_CHANNEL_6
-
-#define EEPROM_FM24_SDA_PORT I2C1_SDA_GPIO_Port
-#define EEPROM_FM24_SDA_PIN I2C1_SDA_Pin
-#define EEPROM_FM24_SCL_PORT I2C1_SCL_GPIO_Port
-#define EEPROM_FM24_SCL_PIN I2C1_SCL_Pin
-
-#if e2prom == 256
-#define FM24_USER_SPACE 32000
-#define FM24_ERASE_UPPER 10000000
-#endif
-
-i2c_t *eeprom_fm24_i2c;
-
-// dma发送回调函数
-static void eeprom_fm24_dma_tx_cb(i2c_t *handle)
-{
- DBG_ASSERT(handle != NULL __DBG_LINE);
- DMA_ClEAR_FLAG(handle->dma, 6, handle->tx_dma_ok);
-}
-
-// dma接收回调函数
-static void eeprom_fm24_dma_rx_cb(i2c_t *handle)
-{
- DBG_ASSERT(handle != NULL __DBG_LINE);
- DMA_ClEAR_FLAG(handle->dma, 7, handle->rx_dma_ok);
-}
-
-/**
- * @brief 初始化FM24 EEPROM
- * @return {*} void
- * @note 初始化FM24模块时,需要配置I2C总线的相关参数
- */
-void eeprom_fm24_init(void)
-{
- eeprom_fm24_i2c = i2c_create_dma(FM24_I2C, FM24_DMA, FM24_PAGE_SIZE + 2, FM24_DMA_RX_CHANNEL, eeprom_fm24_dma_rx_cb,
- FM24_PAGE_SIZE + 2, FM24_DMA_TX_CHANNEL, eeprom_fm24_dma_tx_cb);
- i2c_dma_set_address(eeprom_fm24_i2c, W_ADD_COM, R_ADD_COM);
- // eeprom_fm24_test();
-}
-
-/**
- * @brief FM24 EEPROM反初始化
- * @return {*} void
- * @note
- */
-void eeprom_fm24_dinit(void)
-{
- LL_I2C_Disable(FM24_I2C);
- GPIO_SET_ANALOG(EEPROM_FM24_SDA_PORT, EEPROM_FM24_SDA_PIN);
- GPIO_SET_ANALOG(EEPROM_FM24_SCL_PORT, EEPROM_FM24_SCL_PIN);
-}
-
-/**
- * @brief FM24 EEPROM使能
- * @return {*}
- * @note
- */
-void eeprom_fm24_enable(void)
-{
- // LL_I2C_Enable(FM24_I2C);
-}
-
-/**
- * @brief FM24 EEPROM失能
- * @return {*}
- * @note
- */
-void eeprom_fm24_disable(void)
-{
- // LL_I2C_Disable(FM24_I2C);
-}
-
-/**
- * @brief FM24 EEPROM写入多个字节数据
- * @param {uint32_t} write_addr - 要写入的地址
- * @param {uint8_t} *data - 存储要写入数据的缓冲区
- * @param {uint16_t} length - 要写入的字节数
- * @return {*}
- * @note
- */
-BOOL eeprom_fm24_write(uint32_t write_addr, uint8_t *data, uint16_t length)
-{
- BOOL res = TRUE;
- uint8_t start_page = write_addr / FM24_PAGE_SIZE; // 起始页
- uint16_t start_write_size = (start_page + 1) * FM24_PAGE_SIZE - write_addr; // 第一页需要写入的字节数
- if (start_write_size > length) // 如果第一页可以写入的字节数大于总字节数
- {
- res = eeprom_fm24_i2c->interface.write_mem_dma(eeprom_fm24_i2c, write_addr, 2, data, length);
- }
- else
- {
- res = eeprom_fm24_i2c->interface.write_mem_dma(eeprom_fm24_i2c, write_addr, 2, data, start_write_size);
- if (res == TRUE)
- {
- data += start_write_size;
- uint16_t end_write_size = length - start_write_size; // 剩余需要写入的字节数
- if (end_write_size > 0)
- {
- uint8_t page = end_write_size / FM24_PAGE_SIZE;
- uint8_t remainder = end_write_size % FM24_PAGE_SIZE;
- write_addr += start_write_size;
- uint8_t i = 0;
- for (i = 0; i < page; i++)
- {
- res = eeprom_fm24_i2c->interface.write_mem_dma(eeprom_fm24_i2c, write_addr, 2, data, FM24_PAGE_SIZE);
- if (res == FALSE)
- {
- break;
- }
-
- write_addr += FM24_PAGE_SIZE;
- data += FM24_PAGE_SIZE;
- }
- if (remainder != 0 && res == TRUE)
- {
- res = eeprom_fm24_i2c->interface.write_mem_dma(eeprom_fm24_i2c, write_addr, 2, data, remainder);
- }
- }
- }
- }
- return res;
-}
-
-/**
- * @brief FM24 EEPROM读取多个字节数据
- * @param {uint32_t} read_addr - 要读取的地址
- * @param {uint8_t} *data - 存储读取数据的缓冲区
- * @param {uint16_t} length - 要读取的字节数
- * @return {*}
- * @note
- */
-BOOL eeprom_fm24_read(uint32_t read_addr, uint8_t *data, uint16_t length)
-{
- BOOL res = eeprom_fm24_i2c->interface.read_mem_dma(eeprom_fm24_i2c, read_addr, 2, data, length);
- return res;
-}
-
-/**
- * @brief 用于FM24 EEPROM测试
- * @return {*}
- * @note
- */
-void eeprom_fm24_test(void)
-{
-#define TEST_SIZE 30
- uint16_t test_address = FM24_SIZE - TEST_SIZE;
- uint8_t buf[TEST_SIZE];
- osel_memset(buf, 0, ARRAY_LEN(buf));
- buf[0] = 0xD5;
- buf[1] = 0xC8;
- buf[2] = 0x00;
- buf[3] = 0x01;
- buf[4] = 0x02;
- buf[TEST_SIZE - 1] = 0xfe;
- eeprom_fm24_write(test_address, buf, TEST_SIZE);
- osel_memset(buf, 0, ARRAY_LEN(buf));
- eeprom_fm24_read(test_address, buf, TEST_SIZE);
- __NOP();
-}
diff --git a/User/board/src/eeprom_lc02b.c b/User/board/src/eeprom_lc02b.c
deleted file mode 100644
index d5fa636..0000000
--- a/User/board/src/eeprom_lc02b.c
+++ /dev/null
@@ -1,139 +0,0 @@
-#include "eeprom_lc02b.h"
-#include "delay.h"
-
-#define W_ADD_COM 0xa8 // 写字节命令及器件地址(根据地址实际情况改变), 1010 A2 A1 A0 0
-#define R_ADD_COM 0xa9 // 读命令字节及器件地址(根据地址实际情况改变), 1010 A2 A1 A0 1
-#define PAGE_SIZE 8U
-#define SIZE 256U
-
-#define EEPROM_LC02B_SDA_PORT I2C2_SDA_GPIO_Port
-#define EEPROM_LC02B_SDA_PIN I2C2_SDA_Pin
-#define EEPROM_LC02B_SCL_PORT I2C2_SCL_GPIO_Port
-#define EEPROM_LC02B_SCL_PIN I2C2_SCL_Pin
-
-static i2c_t *eeprom_24lc028bt_i2c;
-
-void eeprom_lc02b_test(void)
-{
-#define TEST_SIZE 15
- uint16_t test_address = SIZE - TEST_SIZE;
- uint8_t buf[TEST_SIZE];
- for (uint8_t i = 0; i < TEST_SIZE; i++)
- {
- buf[i] = i + 1;
- }
-
- eeprom_lc02b_write(test_address, buf, TEST_SIZE);
- delay_ms(10);
- osel_memset(buf, 0, ARRAY_LEN(buf));
- eeprom_lc02b_read(test_address, buf, TEST_SIZE);
-
- __NOP();
-}
-
-/**
- * @brief EEPROM LC02B初始化
- * @return {*}
- * @note
- */
-void eeprom_lc02b_init(void)
-{
- i2c_gpio_group_t gpios;
- gpios.scl = gpio_create(EEPROM_LC02B_SCL_PORT, EEPROM_LC02B_SCL_PIN);
- gpios.sda = gpio_create(EEPROM_LC02B_SDA_PORT, EEPROM_LC02B_SDA_PIN);
-
- eeprom_24lc028bt_i2c = i2c_create(gpios, 0);
- // eeprom_lc02b_test();
-}
-
-/**
- * @brief EEPROM LC02B反初始化
- * @return {*}
- * @note
- */
-void eeprom_lc02b_dinit(void)
-{
- GPIO_SET_ANALOG(EEPROM_LC02B_SDA_PORT, EEPROM_LC02B_SDA_PIN);
- GPIO_SET_ANALOG(EEPROM_LC02B_SCL_PORT, EEPROM_LC02B_SCL_PIN);
-}
-/**
- * @brief 写入数据
- * @param {uint32_t} write_addr
- * @param {uint8_t} *data
- * @param {uint16_t} length
- * @return {*}
- * @note
- */
-void eeprom_lc02b_write(uint32_t write_addr, uint8_t *data, uint16_t length)
-{
- // 发送开始信号
- eeprom_24lc028bt_i2c->interface.start(eeprom_24lc028bt_i2c);
- // 发送写入地址命令
- eeprom_24lc028bt_i2c->interface.write_byte(eeprom_24lc028bt_i2c, W_ADD_COM);
- // 等待写入地址命令响应
- eeprom_24lc028bt_i2c->interface.wait_ack(eeprom_24lc028bt_i2c);
- // 发送要写入的地址
- eeprom_24lc028bt_i2c->interface.write_byte(eeprom_24lc028bt_i2c, (uint8_t)write_addr);
- eeprom_24lc028bt_i2c->interface.wait_ack(eeprom_24lc028bt_i2c);
-
- // 循环写入数据
-
- for (uint16_t i = 0; i < length; i++)
- {
- // 写入一个字节数据
- eeprom_24lc028bt_i2c->interface.write_byte(eeprom_24lc028bt_i2c, *data++);
- // 等待响应
- eeprom_24lc028bt_i2c->interface.wait_ack(eeprom_24lc028bt_i2c);
- write_addr++;
- if (write_addr % PAGE_SIZE == 0)
- {
- eeprom_24lc028bt_i2c->interface.stop(eeprom_24lc028bt_i2c);
- delay_ms(10); // 延时10ms,等待写入完成
- eeprom_24lc028bt_i2c->interface.start(eeprom_24lc028bt_i2c);
- eeprom_24lc028bt_i2c->interface.write_byte(eeprom_24lc028bt_i2c, W_ADD_COM);
- eeprom_24lc028bt_i2c->interface.wait_ack(eeprom_24lc028bt_i2c);
- eeprom_24lc028bt_i2c->interface.write_byte(eeprom_24lc028bt_i2c, (uint8_t)write_addr);
- eeprom_24lc028bt_i2c->interface.wait_ack(eeprom_24lc028bt_i2c);
- }
- }
- // 写入完成,停止I2C总线
- eeprom_24lc028bt_i2c->interface.stop(eeprom_24lc028bt_i2c);
-}
-
-/**
- * @brief 读取数据
- * @param {uint32_t} read_addr
- * @param {uint8_t} *data
- * @param {uint16_t} length
- * @return {*}
- * @note
- */
-void eeprom_lc02b_read(uint32_t read_addr, uint8_t *data, uint16_t length)
-{
- // 发送开始信号
- eeprom_24lc028bt_i2c->interface.start(eeprom_24lc028bt_i2c);
- // 发送写入地址命令
- eeprom_24lc028bt_i2c->interface.write_byte(eeprom_24lc028bt_i2c, W_ADD_COM);
- // 等待写入地址命令响应
- eeprom_24lc028bt_i2c->interface.wait_ack(eeprom_24lc028bt_i2c);
-
- // 发送要读取的地址
- eeprom_24lc028bt_i2c->interface.write_byte(eeprom_24lc028bt_i2c, (uint8_t)read_addr);
- eeprom_24lc028bt_i2c->interface.wait_ack(eeprom_24lc028bt_i2c);
-
- // 发送开始信号
- eeprom_24lc028bt_i2c->interface.start(eeprom_24lc028bt_i2c);
- // 发送读取地址命令
- eeprom_24lc028bt_i2c->interface.write_byte(eeprom_24lc028bt_i2c, R_ADD_COM);
- // 等待读取地址命令响应
- eeprom_24lc028bt_i2c->interface.wait_ack(eeprom_24lc028bt_i2c);
- // 循环读取数据
- for (uint16_t i = 0; i < length - 1; i++)
- {
- // 读取一个字节数据
- *data++ = eeprom_24lc028bt_i2c->interface.read_byte(eeprom_24lc028bt_i2c, TRUE);
- }
- *data++ = eeprom_24lc028bt_i2c->interface.read_byte(eeprom_24lc028bt_i2c, FALSE);
- // 停止I2C总线
- eeprom_24lc028bt_i2c->interface.stop(eeprom_24lc028bt_i2c);
-}
diff --git a/User/board/src/eeprom_m95.c b/User/board/src/eeprom_m95.c
deleted file mode 100644
index f68a68c..0000000
--- a/User/board/src/eeprom_m95.c
+++ /dev/null
@@ -1,339 +0,0 @@
-/**
- * @file eeprom_m95.c
- * @author xxx
- * @date 2023-08-30 08:58:43
- * @brief 用于实现M95 EEPROM相关的读写操作
- * @copyright Copyright (c) 2023 by xxx, All Rights Reserved.
- */
-
-#include "eeprom_m95.h"
-#include "spis.h"
-#include "delay.h"
-#include "entity.h"
-#include "board.h"
-#include "diagnosis.h"
-
-#define M95_SPI SPI1
-#define M95_DMA DMA1
-#define M95_DMA_RX_CHANNEL LL_DMA_CHANNEL_2
-#define M95_DMA_TX_CHANNEL LL_DMA_CHANNEL_3
-
-#define EEPROM_M95_1_CS_PORT EE1_CS_GPIO_Port
-#define EEPROM_M95_1_CS_PIN EE1_CS_Pin
-#define EEPROM_M95_2_CS_PORT EE2_CS_GPIO_Port
-#define EEPROM_M95_2_CS_PIN EE2_CS_Pin
-
-// 下面宏定义为2个EEPROM_M95的引脚定义
-#define EEPROM_M95_MOSI_PORT SPI_MOSI_GPIO_Port
-#define EEPROM_M95_MOSI_PIN SPI_MOSI_Pin
-#define EEPROM_M95_MISO_PORT SPI_MISO_GPIO_Port
-#define EEPROM_M95_MISO_PIN SPI_MISO_Pin
-#define EEPROM_M95_SCK_PORT SPI_CLK_GPIO_Port
-#define EEPROM_M95_SCK_PIN SPI_CLK_Pin
-
-__IO m95_number_e current_m95_number;
-m95_number_t eeprom_m95s[M95_MAX];
-
-static void write_enable(spi_t *eeprom_m95_spi); // 写使能
-static void write_disable(spi_t *eeprom_m95_spi); // 写保护
-static uint8_t read_status(spi_t *eeprom_m95_spi); // 读状态
-static void eeprom_m95_ready(m95_number_e num); // 等待就绪
-
-// DMA TX回调函数
-static void dma_tx_cb(spi_t *handle)
-{
- DMA_ClEAR_FLAG(handle->dma, 3, handle->tx_dma_ok);
-}
-
-// DMA RX回调函数
-static void dma_rx_cb(spi_t *handle)
-{
- DMA_ClEAR_FLAG(handle->dma, 2, handle->rx_dma_ok);
-}
-
-/**
- * @brief 初始化EEPROM_M95eeprom_m95s
- * @param {m95_number_e} num
- * @return {*}
- * @note 初始化函数对板卡上不同的芯片定义了块大小
- */
-void eeprom_m95_init(m95_number_e num)
-{
- DBG_ASSERT(num < M95_MAX __DBG_LINE);
- current_m95_number = num;
- spi_gpio_group_t gpios;
- spi_t *eeprom_m95_spi;
- // 128 byte
- if (num == M95_1)
- {
- // 创建CS引脚
- gpios.cs = gpio_create(EEPROM_M95_1_CS_PORT, EEPROM_M95_1_CS_PIN);
- // 设置页面大小
- eeprom_m95s[num].page_size = M95_PAGE_SIZE_128;
- // 设置总大小
- eeprom_m95s[num].total_size = _M95512_;
-
- eeprom_m95s[num].address_bytes = 2;
- }
- // 256 byte
- else if (num == M95_2)
- {
- // 创建CS引脚
- gpios.cs = gpio_create(EEPROM_M95_2_CS_PORT, EEPROM_M95_2_CS_PIN);
- // 设置页面大小
- eeprom_m95s[num].page_size = M95_PAGE_SIZE_256;
- // 设置总大小
- eeprom_m95s[num].total_size = _M95M02_;
-
- eeprom_m95s[num].address_bytes = 3;
- }
- else
- {
- DBG_ASSERT(FALSE __DBG_LINE);
- }
-
- eeprom_m95s[num].rxbuf = (uint8_t *)osel_mem_alloc(eeprom_m95s[num].page_size + (eeprom_m95s[num].address_bytes + 1) * 2);
- eeprom_m95s[num].txbuf = (uint8_t *)osel_mem_alloc(eeprom_m95s[num].page_size + eeprom_m95s[num].address_bytes + 1);
-
- gpios.mosi = gpio_create(SPI_MOSI_GPIO_Port, SPI_MOSI_Pin);
- gpios.sck = gpio_create(SPI_CLK_GPIO_Port, SPI_CLK_Pin);
- gpios.miso = gpio_create(SPI_MISO_GPIO_Port, SPI_MISO_Pin);
- gpios.rst = gpio_create(NULL, 0);
- gpios.rdy = gpio_create(NULL, 0);
-
- // 创建SPI对象
- eeprom_m95_spi = spi_create(SPI_TYPE_NORMAL, gpios, 0);
- DBG_ASSERT(eeprom_m95_spi != NULL __DBG_LINE);
-
- // 使能SPI
- eeprom_m95_spi->interface.hardware_enable(eeprom_m95_spi, M95_SPI);
- eeprom_m95_spi->interface.dma_enable(eeprom_m95_spi, M95_DMA, M95_DMA_RX_CHANNEL, dma_rx_cb, M95_DMA_TX_CHANNEL, dma_tx_cb);
- eeprom_m95s[num].num = num;
- eeprom_m95s[num].spi = eeprom_m95_spi;
- // 这里需要设置,否则读出的数据不对
- eeprom_m95_spi->gpios.cs->reset(*eeprom_m95_spi->gpios.cs);
- delay_tick(10);
- eeprom_m95_spi->gpios.cs->set(*eeprom_m95_spi->gpios.cs);
- delay_tick(10);
-
- // eeprom_m95_test(num);
-}
-
-/**
- * @brief 反初始化EEPROM_M95
- * @param {m95_number_e} num
- * @return {*}
- * @note
- */
-void eeprom_m95_dinit(m95_number_e num)
-{
- LL_SPI_Disable(M95_SPI);
- GPIO_SET_ANALOG(eeprom_m95s[num].spi->gpios.mosi->port, eeprom_m95s[num].spi->gpios.mosi->pin);
- GPIO_SET_ANALOG(eeprom_m95s[num].spi->gpios.miso->port, eeprom_m95s[num].spi->gpios.miso->pin);
- GPIO_SET_ANALOG(eeprom_m95s[num].spi->gpios.sck->port, eeprom_m95s[num].spi->gpios.sck->pin);
- GPIO_SET_ANALOG(eeprom_m95s[num].spi->gpios.cs->port, eeprom_m95s[num].spi->gpios.cs->pin);
-}
-
-/**
- * @brief M95 EEPROM使能
- * @return {*}
- * @note
- */
-void eeprom_m95_enable(void)
-{
- LL_SPI_Enable(M95_SPI);
-}
-
-/**
- * @brief M95 EEPROM失能
- * @return {*}
- * @note
- */
-void eeprom_m95_disable(void)
-{
- LL_SPI_Disable(M95_SPI);
-}
-
-/**
- * @brief 读取M95 EEPROM内存数据
- * @param num EEPROM模块编号(0或1)
- * @param read_addr 要读取的地址
- * @param data 存储读取数据的缓冲区
- * @param length 要读取的数据长度
- * @return {*}
- */
-void eeprom_m95_read(m95_number_e num, uint32_t read_addr, uint8_t *data, uint16_t length)
-{
- current_m95_number = num;
- spi_t *eeprom_m95_spi = eeprom_m95s[num].spi; // 获取EEPROM模块的SPI配置
- eeprom_m95_spi->gpios.cs->reset(*eeprom_m95_spi->gpios.cs); // 设置CS引脚为低电平,准备开始SPI通信
- eeprom_m95_spi->interface.u.normal.spi_send(eeprom_m95_spi, M95_CMD_READ); // 发送读取命令
- if (eeprom_m95s[num].address_bytes == 2)
- {
- eeprom_m95_spi->interface.u.normal.spi_send(eeprom_m95_spi, read_addr >> 8); // 发送高位地址
- eeprom_m95_spi->interface.u.normal.spi_send(eeprom_m95_spi, read_addr); // 发送低位地址
- }
- else
- {
- eeprom_m95_spi->interface.u.normal.spi_send(eeprom_m95_spi, read_addr >> 16);
- eeprom_m95_spi->interface.u.normal.spi_send(eeprom_m95_spi, read_addr >> 8);
- eeprom_m95_spi->interface.u.normal.spi_send(eeprom_m95_spi, read_addr);
- }
- for (uint16_t i = 0; i < length; i++) // 循环读取数据
- {
- data[i] = eeprom_m95_spi->interface.u.normal.spi_send(eeprom_m95_spi, M95_DUMMY_BYTE); // 发送空字节,读取实际数据
- }
- eeprom_m95_spi->gpios.cs->set(*eeprom_m95_spi->gpios.cs); // 设置CS引脚为高电平,完成SPI通信
-}
-
-/**
- * @brief 向M95 EEPROM内存写入数据
- * @param num EEPROM模块编号(0或1)
- * @param write_addr 要写入的地址
- * @param data 包含要写入数据的缓冲区
- * @param length 要写入的数据长度
- * @return {*}
- */
-void eeprom_m95_write(m95_number_e num, uint32_t write_addr, uint8_t *data, uint16_t length)
-{
- current_m95_number = num;
- spi_t *eeprom_m95_spi = eeprom_m95s[num].spi;
- uint32_t page_size = eeprom_m95s[num].page_size;
- DBG_ASSERT(eeprom_m95_spi != NULL __DBG_LINE);
- write_enable(eeprom_m95_spi); // 写入使能命令
- eeprom_m95_spi->gpios.cs->reset(*eeprom_m95_spi->gpios.cs); // 设置CS引脚为低电平,准备开始SPI通信
- eeprom_m95_spi->interface.u.normal.spi_send(eeprom_m95_spi, M95_CMD_WRITE); // 发送写入命令
-
- if (eeprom_m95s[num].address_bytes == 2)
- {
- eeprom_m95_spi->interface.u.normal.spi_send(eeprom_m95_spi, write_addr >> 8); // 发送高位地址
- eeprom_m95_spi->interface.u.normal.spi_send(eeprom_m95_spi, write_addr); // 发送低位地址
- }
- else
- {
- eeprom_m95_spi->interface.u.normal.spi_send(eeprom_m95_spi, write_addr >> 16);
- eeprom_m95_spi->interface.u.normal.spi_send(eeprom_m95_spi, write_addr >> 8);
- eeprom_m95_spi->interface.u.normal.spi_send(eeprom_m95_spi, write_addr);
- }
-
- while (length--)
- {
- eeprom_m95_spi->interface.u.normal.spi_send(eeprom_m95_spi, *data); // 发送一个字节数据
- data++;
- write_addr++;
- if (((write_addr % page_size) == 0) && (length > 0))
- {
- // 一页写完
- eeprom_m95_spi->gpios.cs->set(*eeprom_m95_spi->gpios.cs); // 设置CS引脚为高电平,完成SPI通信
- eeprom_m95_ready(num);
-
- write_enable(eeprom_m95_spi); // 写入使能命令
- eeprom_m95_spi->gpios.cs->reset(*eeprom_m95_spi->gpios.cs); // 设置CS引脚为低电平,准备开始SPI通信
- eeprom_m95_spi->interface.u.normal.spi_send(eeprom_m95_spi, M95_CMD_WRITE); // 发送写入命令
- if (eeprom_m95s[num].address_bytes == 2)
- {
- eeprom_m95_spi->interface.u.normal.spi_send(eeprom_m95_spi, write_addr >> 8); // 发送高位地址
- eeprom_m95_spi->interface.u.normal.spi_send(eeprom_m95_spi, write_addr); // 发送低位地址
- }
- else
- {
- eeprom_m95_spi->interface.u.normal.spi_send(eeprom_m95_spi, write_addr >> 16);
- eeprom_m95_spi->interface.u.normal.spi_send(eeprom_m95_spi, write_addr >> 8);
- eeprom_m95_spi->interface.u.normal.spi_send(eeprom_m95_spi, write_addr);
- }
- }
- }
- eeprom_m95_spi->gpios.cs->set(*eeprom_m95_spi->gpios.cs); // 设置CS引脚为高电平,完成SPI通信
- eeprom_m95_ready(num);
- write_disable(eeprom_m95_spi);
-}
-
-/**
- * @brief 用于M95 EEPROM测试
- * @param {m95_number_e} num
- * @return {*}
- * @note
- */
-void eeprom_m95_test(m95_number_e num)
-{
-#define TEST_LEN 10
- DBG_ASSERT(eeprom_m95s[num].spi != NULL __DBG_LINE);
- uint16_t test_address = 0;
- uint8_t buf[TEST_LEN];
- buf[0] = 0xA5;
- buf[1] = 0xC8;
- buf[2] = 0x00;
- buf[3] = 0x03;
- buf[4] = num;
- buf[5] = 0xaa;
- buf[6] = 0xbb;
- buf[TEST_LEN - 1] = 0xce;
- eeprom_m95_write(num, test_address, buf, TEST_LEN);
- osel_memset(buf, 0, ARRAY_LEN(buf));
- eeprom_m95_read(num, test_address, buf, TEST_LEN);
-
- __NOP();
-}
-
-/**
- * @brief M95 EEPROM写使能
- * @param {spi_t} *eeprom_m95_spi
- * @return {*}
- * @note
- */
-static void write_enable(spi_t *eeprom_m95_spi)
-{
- eeprom_m95_spi->gpios.cs->reset(*eeprom_m95_spi->gpios.cs);
- eeprom_m95_spi->interface.u.normal.spi_send(eeprom_m95_spi, M95_CMD_WREN);
- eeprom_m95_spi->gpios.cs->set(*eeprom_m95_spi->gpios.cs);
-}
-
-/**
- * @brief M95 EEPROM写保护
- * @param {spi_t} *eeprom_m95_spi
- * @return {*}
- * @note
- */
-static void write_disable(spi_t *eeprom_m95_spi)
-{
- eeprom_m95_spi->gpios.cs->reset(*eeprom_m95_spi->gpios.cs);
- eeprom_m95_spi->interface.u.normal.spi_send(eeprom_m95_spi, M95_CMD_WRDI);
- eeprom_m95_spi->gpios.cs->set(*eeprom_m95_spi->gpios.cs);
-}
-
-/**
- * @brief M95 EEPROM读状态
- * @param {spi_t} *eeprom_m95_spi
- * @return {*}
- * @note
- */
-static uint8_t read_status(spi_t *eeprom_m95_spi)
-{
- uint8_t data;
- eeprom_m95_spi->gpios.cs->reset(*eeprom_m95_spi->gpios.cs);
- eeprom_m95_spi->interface.u.normal.spi_send(eeprom_m95_spi, M95_CMD_RDSR);
- data = eeprom_m95_spi->interface.u.normal.spi_send(eeprom_m95_spi, M95_DUMMY_BYTE);
- eeprom_m95_spi->gpios.cs->set(*eeprom_m95_spi->gpios.cs);
-
- return data;
-}
-
-/**
- * @brief M95 EEPROM等待就绪
- * @param {m95_number_e} num
- * @return {*}
- * @note
- */
-static void eeprom_m95_ready(m95_number_e num)
-{
- spi_t *eeprom_m95_spi = eeprom_m95s[num].spi;
- uint16_t count = 0;
- while (read_status(eeprom_m95_spi) & 0x01)
- {
- if (count++ > 2000)
- {
- __NOP();
- break;
- }
- }
-}
diff --git a/User/board/src/leds.c b/User/board/src/leds.c
deleted file mode 100644
index e420811..0000000
--- a/User/board/src/leds.c
+++ /dev/null
@@ -1,170 +0,0 @@
-#include "leds.h"
-#include "gpios.h"
-
-static gpio_t *leds[LEDS_MAX];
-
-/**
- * @brief 初始化LED
- * @return {*}
- * @note
- */
-void leds_init(void)
-{
- GPIO_SET_OUTPUT(LED1_GPIO_Port, LED1_Pin);
- GPIO_SET_OUTPUT(LED2_GPIO_Port, LED2_Pin);
- GPIO_SET_OUTPUT(LED3_GPIO_Port, LED3_Pin);
- GPIO_SET_OUTPUT(LED4_GPIO_Port, LED4_Pin);
- GPIO_SET_OUTPUT(LED5_GPIO_Port, LED5_Pin);
- for (uint8_t i = 0; i < LEDS_MAX; i++)
- {
- if (leds[i] == NULL)
- {
- switch (i)
- {
- case LEDS_1_RED:
- leds[i] = gpio_create(LED1_GPIO_Port, LED1_Pin);
- break;
- case LEDS_1_GREEN:
- leds[i] = gpio_create(LED2_GPIO_Port, LED2_Pin);
- break;
- case LEDS_1_YELLOW:
- leds[i] = gpio_create(LED3_GPIO_Port, LED3_Pin);
- break;
- case LEDS_2_ORANGE:
- leds[i] = gpio_create(LED4_GPIO_Port, LED4_Pin);
- break;
- case LEDS_2_BLUE:
- leds[i] = gpio_create(LED5_GPIO_Port, LED5_Pin);
- break;
- default:
- break;
- }
- }
- }
-}
-
-/**
- * @brief 反初始化LED
- * @return {*}
- * @note
- */
-void leds_dinit(void)
-{
- GPIO_SET_ANALOG(LED1_GPIO_Port, LED1_Pin);
- GPIO_SET_ANALOG(LED2_GPIO_Port, LED2_Pin);
- GPIO_SET_ANALOG(LED3_GPIO_Port, LED3_Pin);
- GPIO_SET_ANALOG(LED4_GPIO_Port, LED4_Pin);
- GPIO_SET_ANALOG(LED5_GPIO_Port, LED5_Pin);
-}
-
-/**
- * @brief 打开LED
- * @param {leds_e} io
- * @return {*}
- * @note
- */
-void leds_on(leds_e io)
-{
- switch (io)
- {
- case LEDS_1_RED:
- GPIO_SET_OUTPUT(LED1_GPIO_Port, LED1_Pin);
- break;
- case LEDS_1_GREEN:
- GPIO_SET_OUTPUT(LED2_GPIO_Port, LED2_Pin);
- break;
- case LEDS_1_YELLOW:
- GPIO_SET_OUTPUT(LED3_GPIO_Port, LED3_Pin);
- break;
- case LEDS_2_ORANGE:
- GPIO_SET_OUTPUT(LED4_GPIO_Port, LED4_Pin);
- break;
- case LEDS_2_BLUE:
- GPIO_SET_OUTPUT(LED5_GPIO_Port, LED5_Pin);
- break;
- default:
- break;
- }
- if (io < LEDS_MAX)
- {
- leds[(uint8_t)io]->reset(*leds[(uint8_t)io]);
- }
-}
-
-/**
- * @brief 打开所有LED
- * @return {*}
- * @note
- */
-void leds_on_all(void)
-{
- leds_on(LEDS_1_RED);
- leds_on(LEDS_1_GREEN);
- leds_on(LEDS_1_YELLOW);
- leds_on(LEDS_2_ORANGE);
- leds_on(LEDS_2_BLUE);
-}
-
-/**
- * @brief 关闭LED
- * @param {leds_e} io
- * @return {*}
- * @note
- */
-void leds_off(leds_e io)
-{
- if (io < LEDS_MAX)
- {
- leds[(uint8_t)io]->set(*leds[(uint8_t)io]);
- }
-
- // 反初始化其他LED,这里暂时先不做处理,如果电流不够,可以考虑关闭其他LED
- // switch (io)
- // {
- // case LEDS_1_RED:
- // GPIO_SET_ANALOG(LED1_GPIO_Port, LED1_Pin);
- // break;
- // case LEDS_1_GREEN:
- // GPIO_SET_ANALOG(LED2_GPIO_Port, LED2_Pin);
- // break;
- // case LEDS_1_YELLOW:
- // GPIO_SET_ANALOG(LED3_GPIO_Port, LED3_Pin);
- // break;
- // case LEDS_2_ORANGE:
- // GPIO_SET_ANALOG(LED4_GPIO_Port, LED4_Pin);
- // break;
- // case LEDS_2_BLUE:
- // GPIO_SET_ANALOG(LED5_GPIO_Port, LED5_Pin);
- // break;
- // default:
- // break;
- // }
-}
-
-/**
- * @brief 关闭所有LED
- * @return {*}
- * @note
- */
-void leds_off_all(void)
-{
- leds_off(LEDS_1_RED);
- leds_off(LEDS_1_GREEN);
- leds_off(LEDS_1_YELLOW);
- leds_off(LEDS_2_ORANGE);
- leds_off(LEDS_2_BLUE);
-}
-
-/**
- * @brief 翻转LED
- * @param {leds_e} io
- * @return {*}
- * @note
- */
-void leds_toggle(leds_e io)
-{
- if (io < LEDS_MAX)
- {
- leds[(uint8_t)io]->toggle(*leds[(uint8_t)io]);
- }
-}
diff --git a/User/board/src/ntc_3950.c b/User/board/src/ntc_3950.c
deleted file mode 100644
index fe6538b..0000000
--- a/User/board/src/ntc_3950.c
+++ /dev/null
@@ -1,107 +0,0 @@
-/**
- * @file ntc_3950.c
- * @author xxx
- * @date 2023-08-30 08:58:43
- * @brief 用于实现NTC的应用功能
- * @copyright Copyright (c) 2023 by xxx, All Rights Reserved.
- */
-
-#include "ntc_3950.h"
-#define CPU_VREF 2.5
-#define NTC_VREF 3.0
-#define TABLE_SIZE 185
-#define NTC_SERIES_RESISTOR 200000 ///< 200K
-#define BASE_TEMP -55
-
-const uint32_t _table[TABLE_SIZE] = {
- 8989000, 8242680, 7592960, 7021380, 6513750, // -55,-54,-53,-52,-51
- 6059060, 5648680, 5275800, 4935020, 4621990, 4333220, 4065840, 3817520, 3586310, 3370600, // -50,-49,-48,-47,-46,-45,-44,-43,-42,-41
- 3169000, 2980330, 2803600, 2637910, 2482470, 2336580, 2199620, 2071020, 1950230, 1836790, // -40,-39,-38,-37,-36,-35,-34,-33,-32,-31
- 1730230, 1630150, 1536140, 1447840, 1364900, 1287000, 1213820, 1145090, 1080530, 1019890, // -30,-29,-28,-27,-26,-25,-24,-23,-22,-21
- 962912, 909379, 859074, 811797, 767359, 725581, 686296, 649348, 614590, 581883, // -20,-19,-18,-17,-16,-15,-14,-13,-12,-11
- 551100, 522117, 494824, 469113, 444886, 422050, 400518, 380209, 361048, 342963, // -10,-9,-8,-7,-6,-5,-4,-3,-2,-1
- 326560, 309764, 294529, 280131, 266520, 253647, 241470, 229946, 219036, 208706, // 0,1, 2, 3,4,5,6,7,8,9
- 198920, 189647, 180857, 172523, 164618, 157118, 150000, 143243, 136827, 130731, // 10,11 ,12, 13,14,15,16,17,18,19
- 124940, 119435, 114202, 109225, 104491, 100000, 95699, 91617, 87731, 84028, // 20,21, 22, 23,24,25,26,27,28,29
- 80501, 77140, 73936, 70881, 67968, 65188, 62537, 60006, 57590, 55283, // 30,31, 32, 33,34,35,36,37,38,39
- 53080, 50976, 48965, 47044, 45207, 43451, 41771, 40165, 38628, 37157, // 40,41, 42, 43,34,35,36,37,38,39
- 35750, 34402, 33112, 31876, 30692, 29558, 28471, 27429, 26430, 25472, // 50,51, 52, 53,54,55,56,57,58,59
- 24554, 23672, 22827, 22016, 21237, 20489, 19771, 19082, 18420, 17784, // 60,61, 62, 63,64,65,66,67,68,69
- 17172, 16585, 16020, 15477, 14955, 14453, 13970, 13505, 13058, 12628, // 70,71, 72, 73,74,75,76,77,78,79
- 12213, 11815, 11431, 11061, 10705, 10362, 10031, 9712, 9405, 9110, // 80,81, 82, 83,84,85,86,87,88,89
- 8824, 8549, 8284, 8028, 7782, 7544, 7314, 7093, 6879, 6673, // 90,91, 92, 93,94,95,96,97,98,99
- 6474, 6281, 6096, 5916, 5743, 5576, 5415, 5259, 5108, 4963, // 101,102, 103,104,105,106,107,108,109
- 4822, 4687, 4555, 4428, 4306, 4187, 4073, 3962, 3855, 3751, // 111,112, 113,114,115,116,117,118,119
- 3651, 3555, 3461, 3371, 3283, 3199, 3100, 3099, 2899, 2799, // 121,122, 123,124,125,126,127,128,129
-};
-
-/**
- * @brief 温度查表
- * @param {uint32_t} *list
- * @param {uint32_t} rt
- * @return {*}
- * @note
- */
-static uint8_t ntc_lookup(const uint32_t *list, uint32_t rt)
-{
- uint8_t middle = 0;
- uint8_t indexL = 0;
- uint8_t indexR = TABLE_SIZE - 1;
- if (rt >= *(list + 0))
- return 0;
- if (rt <= *(list + TABLE_SIZE - 1))
- return TABLE_SIZE - 1;
-
- while ((indexR - indexL) > 1)
- {
- middle = (indexL + indexR) >> 1;
- if (rt == *(list + middle))
- return middle;
- else if (rt > *(list + middle))
- indexR = middle;
- else if (rt < *(list + middle))
- indexL = middle;
- }
- return indexL;
-}
-
-/**
- * @brief 获取温度值,单位为0.1摄氏度
- * @param {uint16_t} adc采集值
- * @return {float32_u} 温度值
- * @note
- */
-float32_u ntc_get_temp(uint16_t adc)
-{
-
- uint8_t index = 0;
- int16_t data = 0;
- int16_t t = 0;
- int16_t result = 0;
- uint32_t rt = 0;
- const int16_t base = BASE_TEMP * 10;
- float32_u res;
- res.f = BASE_TEMP;
-
- /**
- * ad = (4095*rt)/(rt+10000)
- *
- * rt = (ad*NTC_SERIES_RESISTOR*CPU_VREF)/(NTC_VREF*4095-CPU_VREF*ad)
- */
- rt = (adc * NTC_SERIES_RESISTOR * CPU_VREF) / (NTC_VREF * 4095 - CPU_VREF * adc);
- index = ntc_lookup(_table, rt);
- if (rt >= _table[0])
- return res;
- if (rt <= *(_table + TABLE_SIZE - 1))
- {
- result = (TABLE_SIZE - 1) * 10 + base;
- }
- else
- {
- data = _table[index] - _table[index + 1];
- t = 10 * (_table[index] - rt) / data;
- result = base + index * 10 + t;
- }
- res.f = result / 10.0;
- return res;
-}
diff --git a/User/board/src/rtc_rx8010.c b/User/board/src/rtc_rx8010.c
deleted file mode 100644
index 7953bf1..0000000
--- a/User/board/src/rtc_rx8010.c
+++ /dev/null
@@ -1,513 +0,0 @@
-/**
- * @file rtc_rx8010.c
- * @author xxx
- * @date 2023-08-30 08:58:43
- * @brief 用于实现RTC芯片RX8010的应用功能
- * @copyright Copyright (c) 2023 by xxx, All Rights Reserved.
- */
-
-#include "rtc_rx8010.h"
-#include "i2cs.h"
-#include "delay.h"
-
-#define RTC_RX8010_SDA_PORT RTC_SDA_GPIO_Port
-#define RTC_RX8010_SDA_PIN RTC_SDA_Pin
-#define RTC_RX8010_SCL_PORT RTC_SCL_GPIO_Port
-#define RTC_RX8010_SCL_PIN RTC_SCL_Pin
-
-static i2c_t *rtc;
-
-/* sec, min, hour, week, day, month, year */
-// static uint8_t calendar[7] = {0, 0, 0, 1, 29, 2, 98};
-
-/**
- * @brief 从RTC芯片的指定地址读取一个字节数据
- * @param {uint8_t} *read_buf
- * @param {uint8_t} addr
- * @return {*}
- */
-static BOOL rtc_read_byte(uint8_t *read_buf, uint8_t addr)
-{
- uint8_t *p = read_buf;
-
- /* 发送起始信号 */
- rtc->interface.start(rtc);
-
- /* 发送从机地址 + 读写方向 */
- rtc->interface.write_byte(rtc, RTC_WR_ADDR); /* 此处是写方向,因为要发送读地址 */
- if (rtc->interface.wait_ack(rtc) != TRUE)
- {
- rtc->interface.stop(rtc);
- return FALSE;
- }
-
- /* 发送读地址 */
- rtc->interface.write_byte(rtc, addr);
- if (rtc->interface.wait_ack(rtc) != TRUE)
- {
- rtc->interface.stop(rtc);
- return FALSE;
- }
-
- /* 重新发送起始信号。前面的代码的目的向RTC传送地址,下面开始读取数据 */
- rtc->interface.start(rtc);
-
- /* 发送从机地址 + 读写方向 */
- rtc->interface.write_byte(rtc, RTC_RD_ADDR); /* 此处是读方向,因为要开始读数据了 */
- if (rtc->interface.wait_ack(rtc) != TRUE)
- {
- rtc->interface.stop(rtc);
- return FALSE;
- }
- /* 读取数据 */
- *p = rtc->interface.read_byte(rtc, FALSE); /* 读1个字节 */
-
- /* 命令执行成功,发送I2C总线停止信号 */
- rtc->interface.stop(rtc);
- return TRUE;
-}
-
-/**
- * @brief 从RTC芯片的指定地址读取若干数据
- * @param {uint8_t} *read_buf
- * @param {uint8_t} addr
- * @param {int} size
- * @return {*}
- */
-static BOOL rtc_read_bytes(uint8_t *read_buf, uint8_t addr, int size)
-{
- int i = 0;
-
- /* 发送起始信号 */
- rtc->interface.start(rtc);
-
- /* 发送从机地址 + 读写方向 */
- rtc->interface.write_byte(rtc, RTC_WR_ADDR); /* 此处是写方向,因为要发送读地址 */
- if (rtc->interface.wait_ack(rtc) != TRUE)
- {
- rtc->interface.stop(rtc);
- return FALSE;
- }
-
- /* 发送读地址 */
- rtc->interface.write_byte(rtc, addr);
- if (rtc->interface.wait_ack(rtc) != TRUE)
- {
- rtc->interface.stop(rtc);
- return FALSE;
- }
-
- /* 重新发送起始信号。前面的代码的目的向RTC传送地址,下面开始读取数据 */
- rtc->interface.start(rtc);
-
- /* 发送从机地址 + 读写方向 */
- rtc->interface.write_byte(rtc, RTC_RD_ADDR); /* 此处是读方向,因为要开始读数据了 */
- if (rtc->interface.wait_ack(rtc) != TRUE)
- {
- rtc->interface.stop(rtc);
- return FALSE;
- }
-
- /* 循环读取数据,RTC芯片地址自动自增 */
- for (i = 0; i < size; i++)
- {
- /* 每读完1个字节后,需要发送Ack, 最后一个字节需要发Nack */
- if (i != (size - 1))
- {
- read_buf[i] = rtc->interface.read_byte(rtc, TRUE); /* 读1个字节 */
- }
- else
- {
- read_buf[i] = rtc->interface.read_byte(rtc, FALSE); /* 读1个字节 */
- }
- }
-
- /* 命令执行成功,发送I2C总线停止信号 */
- rtc->interface.stop(rtc);
- return TRUE;
-}
-
-/**
- * @brief 向RTC芯片的指定地址写入一个数据
- * @param {uint8_t} data
- * @param {uint8_t} addr
- * @return {*}
- * @note
- */
-static BOOL rtc_write_byte(uint8_t data, uint8_t addr)
-{
- int retry = 0;
-
- /* 尝试与RTC芯片建立I2C通讯 */
- for (retry = 0; retry < 100; retry++)
- {
- rtc->interface.start(rtc); /* 发送起始信号 */
- rtc->interface.write_byte(rtc, RTC_WR_ADDR); /* 发送从机地址 + 读写方向 */
- if (rtc->interface.wait_ack(rtc) == TRUE)
- {
- break;
- }
- }
- if (retry == 100)
- {
- rtc->interface.stop(rtc);
- return FALSE;
- }
-
- /* 发送起始写地址 */
- rtc->interface.write_byte(rtc, addr);
- if (rtc->interface.wait_ack(rtc) != TRUE)
- {
- rtc->interface.stop(rtc);
- return FALSE;
- }
-
- /* 写入数据 */
- rtc->interface.write_byte(rtc, data);
- if (rtc->interface.wait_ack(rtc) != TRUE)
- {
- rtc->interface.stop(rtc);
- return FALSE;
- }
-
- /* 命令执行成功,发送I2C总线停止信号 */
- rtc->interface.stop(rtc);
- return TRUE;
-}
-
-/**
- * @brief 向RTC芯片的指定地址写入若干数据
- * @param {uint8_t} *write_buf
- * @param {uint8_t} addr
- * @param {int} size
- * @return {*}
- * @note
- */
-static BOOL rtc_write_bytes(uint8_t *write_buf, uint8_t addr, int size)
-{
- int i = 0;
- int retry = 0;
-
- for (i = 0; i < size; i++)
- {
- if (i == 0)
- {
- /* 尝试与RTC芯片建立I2C通讯 */
- for (retry = 0; retry < 100; retry++)
- {
- rtc->interface.start(rtc); /* 发送起始信号 */
- rtc->interface.write_byte(rtc, RTC_WR_ADDR); /* 发送从机地址 + 读写方向 */
- if (rtc->interface.wait_ack(rtc) == TRUE)
- {
- break;
- }
- }
- if (retry == 100)
- {
- rtc->interface.stop(rtc);
- return FALSE;
- }
-
- /* 发送起始写地址 */
- rtc->interface.write_byte(rtc, addr);
- if (rtc->interface.wait_ack(rtc) != TRUE)
- {
- rtc->interface.stop(rtc);
- return FALSE;
- }
- }
-
- /* 循环写入数据,RTC芯片地址自动自增 */
- rtc->interface.write_byte(rtc, write_buf[i]);
- if (rtc->interface.wait_ack(rtc) != TRUE)
- {
- rtc->interface.stop(rtc);
- return FALSE;
- }
- }
-
- /* 命令执行成功,发送I2C总线停止信号 */
- rtc->interface.stop(rtc);
- return TRUE;
-}
-
-/**
- * @brief 假读RTC芯片,任意读地址,不判断RTC响应
- * @return {*}
- * @note
- */
-static void rtc_dummy_read(void)
-{
- rtc->interface.start(rtc);
- rtc->interface.write_byte(rtc, RTC_WR_ADDR);
- rtc->interface.write_byte(rtc, 0x20);
-
- rtc->interface.start(rtc);
- rtc->interface.write_byte(rtc, RTC_RD_ADDR);
- rtc->interface.read_byte(rtc, FALSE);
-
- rtc->interface.stop(rtc);
-}
-
-/**
- * @brief 用于检查VLF,寄存器地址:0x1e bit[1]
- * @return {uint8_t} 0 = VLF位为0,1 = VLF位为1
- * @note
- */
-static uint8_t rtc_check_vlf(void)
-{
- uint8_t flag_register = 1;
- uint8_t vlf = 0;
-
- rtc_read_byte(&flag_register, RTC_FLAG_ADDR);
-
- vlf = (flag_register & 0x02);
- if (vlf == 0)
- {
- return 0;
- }
- else
- {
- return 1;
- }
-}
-
-/**
- * @brief 等待VLF位清除,寄存器地址:0x1e bit[1]
- * @return {uint8_t} 0 = 清零成功,1 = 清零失败,2 = 无需清零
- */
-static uint8_t rtc_wait_vlf_clear(void)
-{
- uint8_t ret = 1;
- uint8_t i = 0;
- uint8_t vlf;
-
- for (i = 0; i < 10; i++)
- {
- vlf = rtc_check_vlf();
-
- if (vlf == 0)
- {
- ret = ((i > 0) ? 0 : 2);
- return ret;
- }
-
- /* 清除VLF */
- rtc_write_byte(0, RTC_FLAG_ADDR);
- }
-
- return ret;
-}
-
-/**
- * @brief 复位
- * @return {BOOL} FALSE = 复位成功,TRUE = 复位失败
- */
-static BOOL rtc_soft_reset(void)
-{
- BOOL ret = FALSE;
-
- ret = rtc_write_byte(0x00, 0x1f);
- ret = rtc_write_byte(0x80, 0x1f);
- ret = rtc_write_byte(0xd3, 0x60);
- ret = rtc_write_byte(0x03, 0x66);
- ret = rtc_write_byte(0x02, 0x6b);
- ret = rtc_write_byte(0x01, 0x6b);
-
- if (ret == 0)
- {
- delay_ms(2);
- }
-
- return ret;
-}
-
-/**
- * @brief 时钟寄存器初始化函数
- * @return {BOOL} TRUE = 初始化成功,FALSE = 初始化失败
- */
-static BOOL rtc_clock_reginit(void)
-{
- BOOL ret = FALSE;
-
- /* set reserve register */
- ret = rtc_write_byte(RTC_REG17_DATA, RTC_REG17_ADDR);
- ret = rtc_write_byte(RTC_REG30_DATA, RTC_REG30_ADDR);
- ret = rtc_write_byte(RTC_REG31_DATA, RTC_REG31_ADDR);
- ret = rtc_write_byte(RTC_IRQ_DATA, RTC_IRQ_ADDR);
- /* write 0x04 to reg_0x1d */
- ret = rtc_write_byte(0x04, 0x1d);
- /* write 0x00 to reg_0x1e */
- ret = rtc_write_byte(0x00, 0x1e);
- /* stop clock */
- ret = rtc_write_byte(0x40, RTC_CONTROL_ADDR);
- /* set the present time */
- // ret = rtc_write_bytes(calendar, RTC_CLOCK_ADDR, sizeof(calendar));
- /* start clock */
- ret = rtc_write_byte(0x00, RTC_CONTROL_ADDR);
-
- return ret;
-}
-
-/**
- * @brief RTC芯片初始化
- * @return {BOOL} TRUE = 成功,FALSE = 失败
- * @note
- */
-BOOL rtc_init(void)
-{
- i2c_gpio_group_t gpios;
- int ret = 1;
- gpios.scl = gpio_create(RTC_RX8010_SCL_PORT, RTC_RX8010_SCL_PIN);
- gpios.sda = gpio_create(RTC_RX8010_SDA_PORT, RTC_RX8010_SDA_PIN);
-
- rtc = i2c_create(gpios, 50);
-
- rtc_dummy_read();
- /* wait for VLF bit clear */
- ret = rtc_wait_vlf_clear();
- if (ret == 0)
- {
- /* software reset */
- ret = rtc_soft_reset();
- if (ret == FALSE)
- {
- return FALSE;
- }
- }
- else if (ret == 1)
- {
- return FALSE;
- }
-
- /* register initialize */
-
- return rtc_clock_reginit();
-}
-
-/**
- * @brief RTC芯片反初始化
- * @return {*}
- * @note
- */
-BOOL rtc_dinit(void)
-{
- GPIO_SET_ANALOG(RTC_RX8010_SCL_PORT, RTC_RX8010_SCL_PIN);
- GPIO_SET_ANALOG(RTC_RX8010_SDA_PORT, RTC_RX8010_SDA_PIN);
- return TRUE;
-}
-
-/**
- * @brief 从RTC芯片读取时间
- * @param {uint8_t} *read_buf - 接收缓存指针,用于接收读取到的数据
- * @return {BOOL} TRUE = 成功,FALSE = 失败
- * @note
- */
-BOOL rtc_get_clock_time(uint8_t *read_buf)
-{
- return rtc_read_bytes(read_buf, RTC_CLOCK_ADDR, 7);
-}
-
-/**
- * @brief 向RTC芯片写入时间
- * @param {rtc_date} *data - 发送缓存指针,用于存储要发送的数据
- * @return {BOOL} TRUE = 成功,FALSE = 失败
- * @note
- */
-BOOL rtc_set_clock_time(rtc_date *data)
-{
- BOOL ret = FALSE;
- uint8_t tmp[7];
- tmp[0] = data->second;
- tmp[1] = data->minute;
- tmp[2] = data->hour;
- tmp[3] = data->weekday;
- tmp[4] = data->day;
- tmp[5] = data->month;
- tmp[6] = data->year;
-
- tmp[3] = (rtc_week_e)tmp[3]; // 改成星期几
-
- /* stop clock */
- ret = rtc_write_byte(0x40, RTC_CONTROL_ADDR);
- /* set the present time */
- ret = rtc_write_bytes(tmp, RTC_CLOCK_ADDR, sizeof(tmp));
- /* start clock */
- ret = rtc_write_byte(0x00, RTC_CONTROL_ADDR);
-
- return ret;
-}
-
-/**
- * @brief 将星期转为星期码
- * @param {uint8_t} *weekday 星期几
- * @return {*}
- * @note
- */
-void rtc_weekday_convert(uint8_t *weekday)
-{
- switch (*weekday)
- {
- case 1:
- *weekday = MON;
- break;
- case 2:
- *weekday = TUE;
- break;
- case 3:
- *weekday = WED;
- break;
- case 4:
- *weekday = THUR;
- break;
- case 5:
- *weekday = FRI;
- break;
- case 6:
- *weekday = SAT;
- break;
- case 7:
- *weekday = SUN;
- break;
- default:
- *weekday = 0;
- break;
- }
-}
-
-/**
- * @brief 将星期码转为星期
- * @param {uint8_t} *weekday 星期码
- * @return {*}
- * @note
- */
-void rtc_weekday_rconvert(uint8_t *weekday)
-{
- switch (*weekday)
- {
- case MON:
- *weekday = 1;
- break;
- case TUE:
- *weekday = 2;
- break;
- case WED:
- *weekday = 3;
- break;
- case THUR:
- *weekday = 4;
- break;
- case FRI:
- *weekday = 5;
- break;
- case SAT:
- *weekday = 6;
- break;
- case SUN:
- *weekday = 7;
- break;
- default:
- *weekday = 0;
- break;
- }
-}
diff --git a/User/entity.h b/User/entity.h
index 45ab396..35aef9b 100644
--- a/User/entity.h
+++ b/User/entity.h
@@ -4,56 +4,116 @@
#include "adcs.h"
#include "pid.h"
#include "params.h"
+#include "hart.h"
#include "pdctrl.h"
#include "mode.h"
+#include "app_hart.h"
+#include "params.h"
-#define CPU_ENCRYPT_ENABLE FALSE // 是否启用加密
-#define H24_BLE_OUTPUT_DBG TRUE // 是否运行蓝牙输出数据到VOFA上位机
-#define LCD_DESIGN FALSE // 是否运行LCD设计,TRUE模式下程序会跳过一些初始化操作,直接进入LCD设计模式
+// 注:1. 板子正常电流在2.5ma左右,在超频时会有所增加,但不会超过4ma,如果超过4ma,说明板子有问题,需要检查是否短路
-// 硬件版本号 1个字节
-#ifdef V4
-#define HW_VER 0x04
-#elif V5
-#define HW_VER 0x05
-#else
-#define HW_VER 0x00
-#endif
-// 软件版本号 1个字节
-#define SW_VER 0x01
-// 固件版本号 1个字节
-#define FW_VER 0x05
+#define DEBUG_ENABLE TRUE ///< 是否启用调试,正式发布时请关闭。使能下:蓝牙发送调试数据
+#define CPU_ENCRYPT_ENABLE FALSE ///< 是否启用加密 !没有验证,暂时不开启
+#define LCD_DESIGN FALSE ///< 是否运行LCD设计,TRUE模式下程序会跳过一些初始化操作,直接进入LCD设计模式
+#define HART_SOFTWARE_TEST_ENABLE TRUE ///< HART软件测试模式,用于中科博微测试
+#define HART_HARDWARE_TEST_ENABLE FALSE ///< HART硬件测试模式,用于中科博微测试
+
+///< 设备版本 1个字节 当前设备基于SMT32L476基础上开发
+#define DW_VER 2
+///< 硬件版本号 1个字节 硬件修订
+#define HW_VER 5
+///< 软件版本号 1个字节 软件修订
+#define SW_VER 22
#define HART_VERSION HART_PROTOCOL_VERSION_7 ///< HART协议版本号
+#define HART_WRITE_MAX_COUNT 3 ///< HART写入最大次数
#define CPU_VREF 2.5f ///< CPU基准电压
+#define CPU_VREF_OFFSET 0.3f ///< CPU基准电压偏差
+#define CPU_VREF_RUN_MIN (CPU_VREF - 0.1f) ///< CPU运行最小电压
+#define CPU_VREF_RUN_MAX (CPU_VREF + 0.1f) ///< CPU运行最大电压
#define CPU_UGAGE_MAX 90.0f ///< CPU使用率最大值
#define MEM_UGAGE_MAX 90.0f ///< 内存使用率最大值
-#define INPUT_CURRENT_MIN 3.8f ///< 输入电流下限3.8mA
-#define BLE_CURRENT_WORK 7.9f ///< 蓝牙工作电流
-#define LOOP_CURRENT_MIN 4.0f ///< 输入电流最小值
-#define LOOP_CURRENT_MAX 20.0f ///< 输入电流最大值
-#define LOOP_CURRENT_WORK_MAX 12.0f ///< 工作输出最大电流下限
-#define LCD_WORK_TEMP_MIN -20 ///< LCD最低工作稳定-20℃
-#define BAROMETER_MAX 10 ///< 气压表最大值
-#define SELF_VCHART_LEN 17 ///< 自定义阀门特性长度
-#define VALVE_SERIAL_NUM_LEN 16 ///< 阀门序列号长度
-#define INST_SERIAL_NUM_LEN 16 ///< 定位器序列号长度
-#define OPERATOR_NAME_LEN 26 ///< 操作员姓名长度
-#define PASSWORD_LEN 4 ///< LCD主菜单页面进入密码长度
+#define POSITION_FEEDBACK_MAX 3500 ///< 位置反馈最大值
+#define POSITION_FEEDBACK_MIN 600 ///< 位置反馈最小值
+#define POSITION_FEEDBACK_CENTER 2048 ///< 位置反馈中心偏移量
+#define POSITION_FEEDBACK_CENTER_OFFSER 100 ///< 位置反馈中心偏移量
+
+#define IP_CURRENT_MAX 2.0f ///< IP电流最大值
+#define IP_VOL_OFFSET 0.5f ///< IP电压偏差(理论输出与实际输出差值)
+#define BOARD_START_CURRENT_MAX 2.0f ///< 板子启动最大电流,可以运行加速
+#define LOOP_CURRENT_MIN 4.0f ///< 输入模拟电流最小值
+#define LOOP_CURRENT_MAX 20.0f ///< 输入模拟电流最大值
+#define LOOP_CURRENT_OFFSET 0.05f ///< 输入模拟电流偏差
+#define INPUT_CURRENT_RUN 3.5f ///< 输入电流运行,达到这个电流程序才启动
+#define SYSTEM_CLOCK_HIGHT_CURRENT_MIN 3.8f ///< 系统高频运行的最低启动电流,瞬间被降低到以下需要能够恢复,外置存储才能加速写入;
+#define INPUT_CURRENT_MIN_UART 3.8f ///< HART UART 输入电流下限3.8mA
+#define FAL_WRITE_CURRENT 3.8f ///< fal写入最小输入电流
+#define GUI_RUN_CURRENT 3.8f ///< gui运行最小输入电流
+#define GUI_HIGHT_CURRENT_MIN 4.0f ///< GUI高频运行的最低电流
+#define BLE_CURRENT_WORK 7.5f ///< 蓝牙启动工作电流
+#define LOOP_TUNE_CURRENT 8.0f ///< 自整定最小输入电流
+
+#define SYSTEM_CLOCK_HIGHT 11059200U ///< 系统高频运行的时钟
+#define SYSTEM_HART_CLOCK 460.8f
+
+#define TEMP_MIN -40.0f ///< 温度最低-40℃
+#define TEMP_MAX 85.0f ///< 温度最高85℃
+#define WORK_HOURS_MAX (24 * 365 * 10) ///< 最大工作时间24小时*365天*10年 = 87600小时
+
+#define PRESS_MAX 400.0f ///< 气源压力上限
+#define PRESS_MIN 200.0f ///< 气源压力下限
+
+#define LCD_WORK_TEMP_MIN -20.0f ///< LCD最低工作稳定
+#define LCD_WORK_TEMP_MAX 70.0f ///< LCD最高工作稳定
+#define BLE_WORK_TEMP_MIN -40.0f ///< 蓝牙最低工作稳定
+#define BLE_WORK_TEMP_MAX 80.0f ///< 蓝牙最高工作稳定
+#define BAROMETER_MAX 10 ///< 气压表最大值
+
+#define DESCRIPTOR "GSDT"
+#define SELF_VCHART_LEN 21 ///< 自定义阀门特性长度
+#define VALVE_SERIAL_NUM_LEN 16 ///< 阀门序列号长度
+#define INST_SERIAL_NUM_LEN 16 ///< 定位器序列号长度(仪表序列号长度)
+#define MAN_SERIAL_NUM_LEN 16 ///< 制造信息序列号
+#define OPERATOR_NAME_LEN HART_PACKED25_LEN ///< 操作员姓名长度
+#define PASSWORD_LEN 4 ///< LCD主菜单页面进入密码长度
+#define PST_PROHIBIT_DETAIL_LEN 6 ///< 部分行程测试故障信息长度
+#define MA_TO_PERCENT (100.0 / (LOOP_CURRENT_MAX - LOOP_CURRENT_MIN)) ///< 1毫安占百分百的比例 6.25%
+#define MA_TO_PERCENT_01 (MA_TO_PERCENT / 10) ///< 0.1毫安占百分百的比例 0.625%
+#define MA_TO_PERCENT_005 (MA_TO_PERCENT / 20) ///< 0.05毫安占百分百的比例 0.3125%
+#define MIN_TARGET_PERCENT -25.0f // 最小目标百分比
+#define MAX_TARGET_PERCENT 125.0f // 最大目标百分比
+
+#define NOINIT_NORESET_FLAG (0x0520) ///< 无初始化标志
+
/**
- * ADC通道定义: 主频4、分频系数16,根据公式 TCONV(转换时间) = (采样时间 + 12.5 个周期)/(主频/ADC分频系数) 计算每个通道单个采集时间
- * ADC_LOOP_CHANNEL: 640.5+12.5=653个周期,653/(4/16)=2612us
- * ADC_PSB_CHANNEL: 47.5+12.5=60个周期,60/(4/16)=240us
- * ADC_BP_CHANNEL: 47.5+12.5=653个周期,60/(4/16)=240us
- * ADC_IPSB_CHANNEL: 47.5+12.5=653个周期,60/(4/16)=240us
- * ADC_NTC_CHANNEL: 640.5+12.5=653个周期,653/(4/16)=2612us
- * ADC_VIP_CHANNEL: 640.5+12.5=653个周期,653/(4/16)=2612us
- * ADC_DCDC_CHANNEL: 640.5+12.5=653个周期,653/(4/16)=2612us
- * ADC_BPA_CHANNEL: 47.5+12.5=653个周期,60/(4/16)=240us
- * ADC_BPB_CHANNEL: 47.5+12.5=653个周期,60/(4/16)=240us
*
- * 通道采集数量为30个,单个采集时间为240us,总共采集时间为30*240=7200us = 7.2ms
+STM32L476xx devices feature up to 1 Mbyte of embedded Flash memory available for
+storing programs and data. The Flash memory is divided into two banks allowing read while-write operations. This feature allows to perform a read operation from one bank while
+an erase or program operation is performed to the other bank. The dual bank boot is also
+supported. Each bank contains 256 pages of 2 Kbyte
+ */
+
+/**
+ * 板卡信息数据管理
+ */
+#define BOARD_DATA_START_ADDRESS (257 * LL_FLASH_PAGE_SIZE)
+#define BOARD_DATA_PAGE_NUM 1
+#define BOARD_DATA_END_ADDRESS (BOARD_DATA_START_ADDRESS + BOARD_DATA_PAGE_NUM * LL_FLASH_PAGE_SIZE) ///< 默认的board存储结束地址
+
+/**
+ * ADC通道定义: 主频4、分频系数8,根据公式 TCONV(转换时间) = (采样时间 + 12.5 个周期)/(主频/ADC分频系数) 计算每个通道单个采集时间
+ * ADC_LOOP_CHANNEL: 12.5+12.5=25个周期,25/(4/8)=50us
+ * ADC_PSB_CHANNEL: 12.5+12.5=105个周期,25/(4/8)=50us
+ * ADC_BP_CHANNEL: 12.5+12.5=25个周期,25/(4/8)=50us
+ * ADC_IPSB_CHANNEL: 12.5+12.5=25个周期,25/(4/8)=50us
+ * ADC_NTC_CHANNEL: 12.5+12.5=25个周期,25/(4/8)=50us
+ * ADC_VIP_CHANNEL: 12.5+12.5=25个周期,25/(4/8)=50us
+ * ADC_DCDC_CHANNEL: 12.5+12.5=25个周期,25/(4/8)=50us
+ * ADC_BPA_CHANNEL: 12.5+12.5=25个周期,25/(4/8)=50us
+ * ADC_BPB_CHANNEL: 12.5+12.5=25个周期,25/(4/8)=50us
+ *
+ * 通道采集数量为30个,单个采集时间为50us,总共采集时间为400*50us = 20000us
*/
typedef enum
{
@@ -66,27 +126,27 @@ typedef enum
ADC_DCDC_CHANNEL, ///< IN12 DCDC检测通道
ADC_BPA_CHANNEL, ///< IN13 A路压力
ADC_BPB_CHANNEL, ///< IN14 B路压力
- ADC_INVREF_CHANNEL, ///< 内部参考电压
+ ADC_VDD_CHANNEL, ///< IN16 VDD电压
ADC_TEMP_CHANNEL, ///< 内部参考温度
+ ADC_INVREF_CHANNEL, ///< 内部参考电压
- // 下面的定义和ADC中的存储没有关系
+ ///< 下面的定义和ADC中的存储没有关系
ADC_FLOW, ///< 流量传感器
ADC1_MAX, ///< ADC1通道最大数量
} adc1_channel_e;
/**
- * ADC2 :慢速通道单采集
- * ADC_LOOP_CHANNEL: 640.5+12.5=653个周期,653/(4/64)= 10448us
- * ADC_PSB_CHANNEL: 640.5+12.5=653个周期,653/(4/64) = 10448us
+ * ADC通道定义: 主频4、分频系数8,根据公式 TCONV(转换时间) = (采样时间 + 12.5 个周期)/(主频/ADC分频系数) 计算每个通道单个采集时间
+ * ADC2_LOOP_CHANNEL: 12.5+12.5=25个周期,25/(4/8)= 50us
+ * ADC2_PSB_CHANNEL: 12.5+12.5=25个周期,25/(4/8)= 50us
+ * 通道采集数量为999个,单个采集时间为50us,总共采集时间为999*50 = 49950us
*/
typedef enum
{
- ADC2_LOOP_CHANNEL = 0, ///< IN5 输入电流ADC通道
- ADC2_PSB_CHANNEL, ///< IN6 阀位反馈ADC通道
- ADC2_MAX, ///< ADC2通道最大数量
+ ADC2_MAX,
} adc2_channel_e;
-// 校准参数信息
+///< 校准参数信息
typedef enum
{
CALIBPARA_LOOP = 0, ///< 4~20mA采集校准参数
@@ -96,343 +156,606 @@ typedef enum
CALIBPARA_PB = 4, ///< B输出压力校准参数
CALIBPARA_IPSB = 5, ///< 小回路校准参数
CALIBPARA_VIP = 6, ///< 4~20mA输出校准参数
- CALIBPARA_NUM = 7, ///< 校准参数数量
+ CALIBPARA_MAX,
} calibration_e;
-// 任务流程状态机
+///< 任务流程状态机
typedef enum
{
FLOW_EVENT_NORMAL, ///< 正常任务流程
FLOW_EVENT_DIAGNOSIS, ///< 诊断任务流程
} flow_event_e;
-#pragma pack(1) // 编译器中提供了#pragma pack(n)来设定变量以n字节对齐方式
-
-/// 时间结构
-typedef union
-{
- uint8_t Byte[6];
-
- struct
- {
- uint8_t Year;
- uint8_t Month;
- uint8_t Day;
- uint8_t Hour;
- uint8_t Minute;
- uint8_t Second;
- } Date;
-} uDateTime_TypeDef;
-
-/// 参数校准
+// 自定义特性表:每个点代表一个行程目标位置,以行程范围的百分比表示;响应的设定点以相对设定值的百分比来表示
typedef struct
{
- BOOL is_calibration; ///< 是否校准
- float32 value[2]; ///< 校准参数
+ uint8_t points;
+ uint16_t setpoint[SELF_VCHART_LEN]; ///< 设定点 计算公式100*(值-2048)/8192
+ uint16_t value[SELF_VCHART_LEN]; // 行程目标位置 计算公式100*(值-2048)/8192
+} custom_property_table_t;
+
+////< 参数校准
+typedef struct
+{
+ BOOL is_calibration; ///< 是否校准
+ int16_t offset; ///< 偏移
+ int16_t span; ///< 跨度
+ uint16_t original_adc_value[2]; ///< ADC值
+ float32 min; ///< 最小值,用作分子
+ float32 max; ///< 最大值,用作分子
+ float32 slope; ///< 斜率
+ uint32_t crc; ///< CRC校验
} calib_param_t;
-/// 设备基础参数
+////< 校准记录
typedef struct
{
- // 定位器序列号
- uint8_t dev_serial_num[INST_SERIAL_NUM_LEN];
- // 定位器版本号
- uint32_t dev_version;
- // 定位器硬件版本号
+ uint32_t operation_time; ///< 时间 4字节
+ uint8_t control_byte; ///< 控制字节
+ uint8_t operator[OPERATOR_NAME_LEN]; ///< 人员 25字节
+} calib_record_t;
+
+////< 设备基础参数
+typedef struct
+{
+ ///< 定位器硬件版本号
uint8_t dev_hw_version;
- // 定位器软件版本号
- uint8_t dev_fw_version;
- // 定位器型号
- uint16_t dev_model;
- // 定位器HART短地址(轮询地址)(作废,从HART模块获取)
- // uint8_t dev_hart_addr;
- // 定位器作用方向:正作用/反作用
- uint8_t dev_driver_dir;
- // 定位器安装方向
- // 0 = 反向安装,磁条反馈ADC值上小下大
- // 1 = 正向安装,磁条反馈ADC值上大下小
- uint8_t dev_install_dir;
- // 定位器工作模式
- // 0 = 自动模式,根据4~20mA控制阀位
- // 1 = 手动模式,根据设定目标值控制阀位
- // 2 = 测试模式,在测试定位器部分功能时,必须在测试模式下进行
- // 3 = 非投用模式,阀门复位,定位器禁用信号控制功能
- // 4 = 待机模式,阀门保持,定位器禁用信号控制功能
- uint8_t dev_work_mode;
- // 定位器算法模式 详见:mode_algorithm_e
+ ///< 定位器软件版本号
+ uint8_t dev_sw_version;
+ ///< 定位器算法模式 详见:mode_algorithm_e
uint8_t dev_algorithm_mode;
- // 定位器控制模式 1 = 位置控制模式,2 = 压力控制模式
- uint8_t dev_ctrl_mode;
- // 执行机构类型
- uint8_t value_type;
- // 执行机构尺寸
+ ///< 执行机构尺寸
uint8_t valve_size;
- // 执行机构行程
+ ///< 执行机构行程
uint8_t value_travel;
- // 自定义执行机构行程
+ ///< 自定义执行机构行程
uint8_t self_value_travel;
- // 执行机构行程类型:直行程/角行程
- uint8_t value_travel_type;
- // 执行机构气动类型:气开/气关
- uint8_t value_action_type;
- // 执行机构作用类型:单作用/双作用
- uint8_t value_relay_type;
- // 阀门特性
- uint8_t valve_chart;
- // 自定义阀门特性
- uint16_t self_value_chart[SELF_VCHART_LEN];
- // 磁条规格
- uint8_t magnet_spec;
- // 写入保护禁用/使能
+ ///< 写入保护禁用/使能
uint8_t write_protect_enable;
- // 压力传感器使能
- uint8_t press_sensor_enable;
- // 增速器禁用/使能
+ ///< 增速器禁用/使能
uint8_t speed_increaser_enable;
- // 快排阀禁用/使能
+ ///< 快排阀禁用/使能
uint8_t quick_exhaust_enable;
- // 无线通讯禁用/使能
+ ///< 无线通讯禁用/使能
uint8_t wireless_enable;
- // PWM输出电流禁用/使能
+ ///< PWM输出电流禁用/使能,外部输出4-20mA电流
uint8_t output_current_enable;
- // 输出开关触发逻辑
- uint8_t swo_logic[2];
- // 输出开关触发位置
- float32 swo_value[2];
- // LCD显示方向:0/180
+ ///< LCD显示方向:0/180
uint8_t display_direction;
- // LCD显示语言
+ ///< LCD显示语言
uint8_t display_language;
- // 行程百分比显示方式
- // 0 = 正向显示,与阀门开度一致
- // 1 = 反向显示,与阀门开度相反
+ ///< 行程百分比显示方式
+ ///< 0 = 正向显示,与阀门开度一致
+ ///< 1 = 反向显示,与阀门开度相反
uint8_t display_travel_mode;
- // 报警处理方式
+ ///< 报警处理方式
uint8_t alarm_handle_mode;
- // 复位处理方式
+ ///< 复位处理方式
uint8_t reset_handle_mode;
- // 温度单位
- uint8_t temperature_unit;
- // 电流单位
- uint8_t current_unit;
- // 行程单位
- uint8_t travel_unit;
- // 压力单位
- uint8_t press_unit;
- // 力学单位(摩擦力/弹簧力)
+ ///< 力学单位(摩擦力/弹簧力)
uint8_t force_unit;
- // 死区(%),表示在目标位置附近设置的可允许偏差。若阀门填料的摩擦力较大,可相应调整并设置此数值,
- // 以防止因摩擦导致循环受限。若死区设置为0.5%,则其对应范围为目标的±0.5%。
- float32 travel_dead; // 0.1~10.0%
- // 模拟输入范围上限,单位:mA
- float32 input_upper;
- // 模拟输入范围下限,单位:mA
- float32 input_lower;
- // 温度范围上限,单位:摄氏度
- float32 temp_upper;
- // 温度范围下限,单位:摄氏度
- float32 temp_lower;
- // 供应压力范围上限,单位:kpa
- float32 supply_upper;
- // 供应压力范围下限,单位:kpa
- float32 supply_lower;
- // 摩擦力范围上限
- float32 friction_upper;
- // 摩擦力范围下限
- float32 friction_lower;
- // 弹簧力范围上限
- float32 elasticity_upper;
- // 弹簧力范围下限
- float32 elasticity_lower;
- // 行程范围上限,单位:百分比
- float32 travel_upper;
- // 行程范围下限,单位:百分比
- float32 travel_lower;
- // 行程报警死区:行程回归超过死区,认为回归正常范围
- float32 travel_alert_dead;
- // 小信号切除禁用/使能
+ ///< 信号切除禁用/使能
uint8_t travel_cut_enable;
- // 小信号上限
- float32 travel_cut_upper;
- // 小信号下限
- float32 travel_cut_lower;
- // 分程控制禁用/使能
+ ///< 分程控制禁用/使能
uint8_t part_travel_enable;
- // 分程控制上限
- float32 part_travel_upper;
- // 分程控制下限
- float32 part_travel_lower;
- // 累计行程上限
- float32 travel_sum_upper;
- // 累计行程死区:行程超过累计行程死区时,计算累计行程
- float32 travel_sum_dead;
- // 动作次数上限
- uint32_t act_sum_upper;
- // 动作次数死区:行程超过动作次数死区时,计算动作次数
- float32 act_sum_dead;
- // 供应压力
- float32 supply_press;
- // 供应压力偏差(百分比)
- float32 supply_error;
- // 供应压力偏差报警等待时间
- uint16_t supply_error_time;
- // 参考电压
- float32 vref;
- // 参考电压偏差
- float32 vref_error;
- // 参考电压偏差报警等待时间
- uint16_t vref_error_time;
- // 行程偏差
- float32 travel_error;
- // 行程偏差报警等待时间(秒)(偏差超出范围的持续时间上限)
- uint16_t travel_error_time;
- // 阀门打开(上行)变化速率 (%/秒),如需在5秒钟左右移动100%行程,请将其设置为 20 [%/sec]
- float32 travel_rate_open;
- // 阀门关闭(下行)变化速率 (%/秒),如需在5秒钟左右移动100%行程,请将其设置为 20 [%/sec]
- float32 travel_rate_close;
- // 阀门全开时间
- uint16_t all_open_time;
- // 阀门全关时间
- uint16_t all_close_time;
- // 阀门0位置行程反馈ADC值
- uint16_t pos0_travel_vol;
- // 阀门100位置行程反馈ADC值
- uint16_t pos100_travel_vol;
- // 阀门0位置小回路反馈ADC值
- uint16_t pos0_minor_vol;
- // 阀门100位置小回路反馈ADC值
- uint16_t pos100_minor_vol;
- // 阀门0位置A路气压反馈ADC值
- uint16_t pos0_press_a_vol;
- // 阀门100位置A路气压反馈ADC值
- uint16_t pos100_press_a_vol;
- // 阀门0位置B路气压反馈ADC值
- uint16_t pos0_press_b_vol;
- // 阀门100位置B路气压反馈ADC值
- uint16_t pos100_press_b_vol;
- // 驱动阀门动作所需上限值
- uint16_t output_max;
- // 驱动阀门动作所需下限值
- uint16_t output_min;
- // 整定标志 0:未整定,1:整定中,2:整定成功,3:整定失败
+ ///< 整定标志 0:未整定,1:整定中,2:整定成功,3:整定失败。这个作为中间变量和FISHER的上一次整定结果做映射关系
uint8_t tuned_flag;
- // PID参数选择,0 = 自适应,1 = 自定义
+ ///< 整定错误码 mode_adjust_error_e,tuned_flag未3时有效
+ uint8_t tuned_err_code;
+ ///< PID参数选择,0 = 自适应,1 = 自定义
uint8_t pid_index;
- // 自适应PID参数
- float32 apid_kp;
- float32 apid_ki;
- float32 apid_kd;
- float32 apid_dead;
- // 自定义PID参数
+ ///< 定位器型号(仪表型号)
+ uint16_t dev_model;
+ ///< 设备授权等级
+ uint16_t dev_usfeatures;
+ ///< 行程偏差报警等待时间(秒)(偏差超出范围的持续时间上限)
+ uint16_t travel_error_time;
+ ///< 阀门全开时间
+ uint16_t all_open_time;
+ ///< 阀门全关时间
+ uint16_t all_close_time;
+ ///< 阀门0位置行程反馈ADC值
+ uint16_t pos0_travel_vol;
+ ///< 阀门100位置行程反馈ADC值
+ uint16_t pos100_travel_vol;
+ ///< 阀门0位置小回路反馈ADC值
+ uint16_t pos0_minor_vol;
+ ///< 阀门100位置小回路反馈ADC值
+ uint16_t pos100_minor_vol;
+ ///< 阀门0位置A路气压反馈ADC值
+ uint16_t pos0_press_a_vol;
+ ///< 阀门100位置A路气压反馈ADC值
+ uint16_t pos100_press_a_vol;
+ ///< 阀门0位置B路气压反馈ADC值
+ uint16_t pos0_press_b_vol;
+ ///< 阀门100位置B路气压反馈ADC值
+ uint16_t pos100_press_b_vol;
+ ///< 驱动阀门动作所需上限值
+ uint16_t output_max;
+ ///< 驱动阀门动作所需下限值
+ uint16_t output_min;
+ // ///< PWM输出电流校验4ma采样值
+ // uint16_t output_4ma_duty;
+ // ///< PWM输出电流标定20ma采样值
+ // uint16_t output_20ma_duty;
+ ///< 输入电流ADC原始值
+ uint16_t input_raw;
+ ///< 气源压力ADC原始值
+ uint16_t press_s_raw;
+ ///< A路压力ADC原始值
+ uint16_t press_a_raw;
+ ///< B路压力ADC原始值
+ uint16_t press_b_raw;
+ ///< 记录存储间隔时间(秒) 实时数据是I2C存储,间隔时间不宜太短,建议大于30秒
+ uint16_t save_cycle;
+ ///< 定位器版本号
+ uint32_t dev_version;
+ ///< 摩擦力范围上限
+ float32 friction_upper;
+ ///< 摩擦力范围下限
+ float32 friction_lower;
+ ///< 弹簧力范围上限
+ float32 elasticity_upper;
+ ///< 弹簧力范围下限
+ float32 elasticity_lower;
+ ///< 行程报警死区:行程回归超过死区,认为回归正常范围
+ float32 travel_alert_dead;
+ ///< 分程控制下限
+ float32 part_travel_lower;
+ ///< 分程控制上限
+ float32 part_travel_upper;
+ ///< 累计行程死区:行程超过累计行程死区时,计算累计行程
+ float32 travel_sum_dead;
+ ///< 动作次数死区:行程超过动作次数死区时,计算动作次数
+ float32 act_sum_dead;
+ ///< 参考电压
+ float32 vref;
+ ///< 阀门打开(上行)变化速率 (%/秒),如需在5秒钟左右移动100%行程,请将其设置为 20 [%/sec]
+ float32 travel_rate_open;
+ ///< 阀门关闭(下行)变化速率 (%/秒),如需在5秒钟左右移动100%行程,请将其设置为 20 [%/sec]
+ float32 travel_rate_close;
+ ///< 自定义PID参数
float32 spid_kp;
float32 spid_ki;
float32 spid_kd;
float32 spid_dead;
- // PWM输出电流校验4ma采样值
- uint16_t output_4ma_duty;
- // PWM输出电流标定20ma采样值
- uint16_t output_20ma_duty;
- // 输入电流ADC原始值
- uint16_t input_raw;
- // 输入电流偏移
- uint16_t input_offset;
- // 输入电流跨度
- uint16_t input_span;
- // 气源压力ADC原始值
- uint16_t press_s_raw;
- // 气源压力偏移
- uint16_t press_s_offset;
- // 气源压力跨度
- uint16_t press_s_span;
- // A路压力ADC原始值
- uint16_t press_a_raw;
- // A路压力偏移
- uint16_t press_a_offset;
- // A路压力跨度
- uint16_t press_a_span;
- // B路压力ADC原始值
- uint16_t press_b_raw;
- // B路压力偏移
- uint16_t press_b_offset;
- // B路压力跨度
- uint16_t press_b_span;
- // 记录存储间隔时间(秒)
- uint16_t save_cycle;
- // 配置时间(时间戳)
- uint32_t operating_time;
- // 配置人员
- uint8_t operator[OPERATOR_NAME_LEN];
- // 行程设定点
- float32 travel_setpoint;
- // LCD主菜单页面进入密码长度
+ ///< 纠正系统误差造成的影响,作用于死区,比如检测出系统偏差为0.2%,则将其设置为0.2%,算法系统内部自动处理
+ float32 deviation;
+ ///< 输出开关触发逻辑
+ uint8_t swo_logic[2];
+ ///< 阀门序列号
+ uint8_t valve_serial_num[VALVE_SERIAL_NUM_LEN];
+ ///< 定位器序列号(仪表序列号)
+ uint8_t dev_serial_num[INST_SERIAL_NUM_LEN];
+ ///< 制造信息序列号
+ uint8_t man_info_serial_num[MAN_SERIAL_NUM_LEN];
+ ///< 制造方案序列号
+ uint8_t man_scheme_serial_num[MAN_SERIAL_NUM_LEN];
+ ///< LCD主菜单页面进入密码长度
uint8_t menus_main_password[PASSWORD_LEN];
-} device_typedef;
+ ///< 输出开关触发位置
+ float32 swo_value[2];
+ ///< 自定义阀门特性
+ custom_property_table_t custom_property_table;
+ /********************************************** 参照Fisher陆续更新 **********************************************/
+ ///< 反馈特性(磁条规格)
+ uint8_t feedback_char; ///< 取值范围 feedback_char_e
+ ///< 电流单位
+ uint8_t input_unit; ///< 取值范围 input_unit_e
+ ///< 行程特性
+ uint8_t travel_char; ///< 取值范围 valve_chart_e
+ ///< 执行机构类型
+ act_style_u act_style; ///< 取值范围 act_style_u
+ ///< 压力单位
+ uint8_t press_unit;
+ ///< 温度单位
+ uint8_t temp_unit;
+ ///< 仪器模式
+ uint8_t inst_mode; ///< 取值范围 inst_mode_e
+ ///< 行程压力选择
+ uint8_t travel_press_select; ///< 取值范围 travel_press_e
+ ///< 上次整定结果
+ uint8_t auto_cal_status; ///< 取值范围 auto_cal_status_e
+ ///< 控制模式
+ uint8_t control_mode; ///< 取值范围 control_mode_e
+ ///< 零功率条件(阀门气开气关类型)
+ uint8_t zero_power_condition; ///< 取值范围 zero_power_e
+ ///< 切除/限位选择
+ uint8_t cutoff_limit_select; ///< 取值范围 cutoff_limit_e
+ ///< 手动/伺服控制
+ uint8_t manual_loader; ///< 取值范围 manual_loader_e
+ ///< 通讯超时时间
+ uint8_t comm_timeout;
+ ///< 反向反馈(定位器安装方向)
+ uint8_t invert_feedback;
+ ///< 积分控制使能
+ uint8_t comp_mode; ///< 取值范围 ui_enable_e
+ ///< 压力传感器使能
+ uint8_t press_sensor_enable;
+ ///< 自动校准按钮
+ uint8_t autocal_btn;
+ ///< 重启仪器模式
+ uint8_t restart_inst_mode; ///< 取值范围 restart_inst_mode_e
+ ///< 重新启动控制模式
+ uint8_t restart_ctrl_mode; ///< 取值范围 restart_ctrl_mode_e
+ ///< 轮询地址
+ uint8_t polling_addr;
+ ///< 警报记录使能
+ uint8_t aer_config;
+ ///< 输出压力限制使能
+ uint8_t output_press_limit_enable;
+ ///< 行程单位
+ uint8_t travel_units;
+ ///< 位置变送器状态
+ uint8_t xmtr_installed_posxmtrstate;
+ ///< 保留位
+ uint16_t reserve_78;
+ ///< 超前滞后上限
+ uint16_t lead_lag_open;
+ ///< 超前滞后下限
+ uint16_t lead_lag_close;
+ ///< 滞后时间
+ uint16_t lvp_filter_selector;
+ ///< 触发灵敏度
+ uint16_t trigger_sensitivity;
+ ///< 位置跨度
+ uint16_t pos_span;
+ ///< 位置偏移
+ uint16_t pos_offset;
+ ///< 变化点(与行程有关)
+ uint16_t crossover_out;
+ ///< 原始驱动
+ uint16_t driver_raw;
+ ///< 伺服输出偏差
+ uint16_t servo_output_bias;
+ ///< 输入电流4ma偏移
+ int16_t input_offset;
+ ///< 输入电流20ma范围
+ int16_t input_span;
+ ///< 输出电流4ma采样值
+ int16_t output_offset;
+ ///< 输出电流20ma范围
+ int16_t output_span;
+ ///< 气源压力偏移
+ uint16_t press_s_offset;
+ ///< 气源压力跨度
+ uint16_t press_s_span;
+ ///< A路压力偏移
+ uint16_t press_a_offset;
+ ///< A路压力跨度
+ uint16_t press_a_span;
+ ///< B路压力偏移
+ uint16_t press_b_offset;
+ ///< B路压力跨度
+ uint16_t press_b_span;
+ ///< 小回路跨度
+ uint16_t minor_loop_span;
+ ///< 动作次数报警设定值
+ uint32_t cycle_count_limit;
+ ///< 累计行程报警设定值
+ uint32_t travel_accum_alert_pt;
+ ///< 压力控制100位置压力值(只用于显示)
+ float32 press_100_percent;
+ ///< 压力控制0位置压力值(只用于显示)
+ float32 press_0_percent;
+ ///< 行程控制100位置行程(只用于显示)
+ float32 travel_100_percent;
+ ///< 行程控制0位置行程(只用于显示)
+ float32 travel_0_percent;
+ ///< 供应压力上限报警设定值
+ float32 high_supply_alert_pt;
+ ///< 供应压力下限报警设定值
+ float32 low_supply_alert_pt;
+ ///< 压力控制偏差报警设定值
+ float32 press_dev_alert_pt;
+ ///< 行程控制偏差报警设定值
+ float32 travel_dev_alert_pt;
+ ///< 行程上限报警设定值
+ float32 travel_hi_alert_pt;
+ ///< 行程下限报警设定值
+ float32 travel_lo_alert_pt;
+ ///< 行程上限过高报警设定值
+ float32 travel_hihi_alert_pt;
+ ///< 行程下限过低报警设定值
+ float32 travel_lolo_alert_pt;
+ ///< 压力范围上限(顶点压力)
+ float32 press_range_hi;
+ ///< 压力范围下限(起点压力)
+ float32 press_range_lo;
+ ///< 温度范围下限
+ float32 min_temp;
+ ///< 温度范围上限
+ float32 max_temp;
+ ///< 切除/限位上限
+ float32 cutoff_limit_hi;
+ ///< 切除/限位下限
+ float32 cutoff_limit_lo;
+ ///< 自定义PID参数
+ float32 travel_kp; ///< 行程比例增益
+ float32 travel_ki; ///< 行程积分增益
+ float32 travel_kv; ///< 行程速度增益
+ float32 travel_kd; ///< 行程微分增益
+ float32 press_kp; ///< 压力比例增益
+ float32 press_ki; ///< 压力积分增益
+ float32 press_rate; ///< 压力速率
+ float32 press_kd; ///< 压力微分增益
+ ///< 积分死区
+ float32 integral_db;
+ ///< 行程/压力偏差跳变点
+ float32 tvl_dev_trip;
+ ///< 行程/压力偏差时间
+ float32 tvl_dev_time;
+ ///< 行程/压力设定点速率上限
+ float32 rate_limit_open;
+ ///< 行程/压力设定点速率下限
+ float32 rate_limit_close;
+ ///< 超前滞后启动
+ float32 lead_lag_boost;
+ ///< A口压力跳变点
+ float32 ps1_trigger_db;
+ ///< B口压力跳变点
+ float32 ps2_trigger_db;
+ ///< 行程偏差报警时间
+ float32 travel_dev_alert_time;
+ ///< 输入电流跳变点
+ float32 current_trigger_db;
+ ///< 压力偏差报警时间
+ float32 press_dev_alert_time;
+ ///< 上限软切割速率
+ float32 soft_cutoff_rate_open_unscaled;
+ ///< 下限软切割速率
+ float32 soft_cutoff_rate_close_unscaled;
+ ///< 积分限位
+ float32 intergal_limit_unscaled;
+ ///< 压力A限制
+ float32 press_a_limit;
+ ///< 所有行程警报死区
+ float32 travel_alert_deadband_unscaled;
+ ///< 周期计数累计死区
+ float32 cycle_count_deadband_unscaled;
+ ///< 输入电流上限
+ float32 input_range_hi;
+ ///< 输入电流下限
+ float32 input_range_lo;
+ ///< 停机自检
+ uint8_t selftest_shutdown[HART_PACKED6_LEN];
+ ///< 校准记录
+ calib_record_t calib_record;
+ ///< 更多状态标志使能/禁用
+ hart_device_specific_status_u more_status_mask_6x;
+ /************** 下面定义的参数只供FISHER指令查询暂时不使用 **********************/
+ ///< 仪表覆盖状态
+ uint8_t sis_override_status; ///< 暂时固定数据 A0
+ ///< 行程报警使能/禁止
+ uint8_t demand_stroke_alert_enable; ///< TRUE = 使能,FALSE = 禁止
+ ///< 位置整定参数
+ uint8_t pos_tuning_set;
+ ///< 压力整定参数
+ uint8_t press_tuning_set;
+ ///< 停机触发
+ uint8_t sis_opt; ///< 取值范围 sis_opt_e
+ ///< 突发模式
+ uint8_t burst_mode; ///< TRUE = 是,FALSE = 否
+ ///< XMTR状态
+ uint8_t xmtr_status; ///< 暂时固定数据 00
+ ///< 部分行程测试延期原因
+ uint8_t pst_deferral_reason; ///< 暂时固定数据 00
+ ///< SVT报警使能/禁用
+ uint8_t svt_alert_enable; ///< TRUE = 使能,FALSE = 禁用
+ ///< 部分行程测试故障信息
+ uint8_t pst_prohibit_detail[PST_PROHIBIT_DETAIL_LEN]; ///< 暂时没有部分行程测试功能
+ ///< 附属标志
+ uint8_t accessory_flags;
+ ///< 自动校准稳定时间
+ uint8_t autocal_settling_time;
+ ///< XMTR模式标志
+ uint8_t xmtr_mode_flag;
+ ///< XMTR使能
+ uint8_t xntr_enable;
+ ///< SVT使能标志
+ uint8_t svt_enable_flag;
+ ///< 辅助输入类型
+ uint8_t aux_input_type;
+ ///< 复位时间报警设定值
+ float32 reset_stroke_time_alert_pt; ///< 暂时固定数据 00 00 00 00
+ ///< 行程时间报警设定值
+ float32 demand_stroke_time_alert_pt; ///< 暂时固定数据 00 00 00 00
+ ///< 启动时间报警设定值
+ float32 breakout_time_alert_pt; ///< 暂时固定数据 00 00 00 00
+ ///< 行程控制小回路增益
+ float32 travel_mlfb_gain;
+ ///< 压力控制小回路增益
+ float32 press_mlfb_gain;
+ ///< SVT跳闸压力报警设定值
+ float32 svt_trip_press_alert_pt;
+ ///< SVT恢复压力报警设定值
+ float32 svt_recovery_press_alert_pt;
+ ///< 默认设置点
+ float32 default_setpoint; ///< 暂时固定数据 1
+ ///< 部分行程测试解电至跳闸
+ float32 loop_pst_ett;
+ ///< 部分行程测试充电至跳闸
+ float32 loop_pst_dett;
+ ///< LCP通讯跳闸警报时间
+ uint16_t lcp_trip_alert_sec;
+ ///< 部分行程测试最小压力
+ float32 min_pst_press;
+ ///< 部分行程测试最小压力时间
+ float32 min_pst_press_time;
+
+ uint32_t crc; // 用于校验
+} udevice_t;
-/// 设备实时参数
typedef struct
{
- __IO uint32_t travel_cnt; // 累计行程
- __IO uint32_t act_cnt; // 动作次数
- __IO uint32_t dev_work_time; // 设备工作时长
- __IO uint32_t power_on_cnt; // 设备上电次数
- uint8_t last_dev_variable; // 上一个设备变量
- uint16_t cfg_update_cnt; // 配置更新次数
- __IO uDateTime_TypeDef real_time; // 实时时间
+ uint8_t last_dev_variable; ///< 上一个设备变量
+ uint8_t work_menu_index; ///< 工作菜单索引
+ int8_t mode_control_stable_temperature; ///< 整定稳定温度值
+ int16_t mode_control_offset; ///< 模式控制偏移量
+ uint16_t hart_run_time_h; ///< 需要将dev_run_time_h/18得到hart_run_time_h 按照1=18小时计算
+ uint16_t dev_run_time_s; ///< 设备工作时长(秒)
+ uint16_t power_on_cnt; ///< 设备上电次数
+ uint16_t reset_cnt; ///< 设备复位次数
+ uint32_t dev_run_time_h; ///< 设备工作时长(小时)
+ uint32_t travel_accum; ///< 累计行程
+ uint32_t cycle_count; ///< 动作次数
+ float32 travel_set_pt; ///< 目标行程设定值
+ float32 press_set_pt; ///< 目标压力设定值
+ date_time_t real_time; ///< 实时时间
+
+ uint32_t crc; ///< CRC校验
} rt_save_param_t;
typedef struct
{
- __IO uint8_t tuned_id; // 整定步骤
- __IO uint16_t ip_output; // IP输出值
- __IO float32 temperature; // 设备温度
- __IO float32 loop_current; // 回路电流
- __IO float32 target_travel; // 目标行程
- __IO float32 actual_travel; // 实际行程
- __IO float32 pressure_s; // 气源压力
- __IO float32 pressure_a; // A路压力
- __IO float32 pressure_b; // B路压力
- __IO float32 friction; // 摩擦力
- __IO float32 elasticity; // 弹簧力
- __IO float32 cpu_percent; // CPU使用率
- __IO float32 cpu_temperature; // CPU温度
- __IO float32 mem_percent; // 内存使用率
- rt_save_param_t save; // 需要保存到FM24的实时参数
+ uint8_t unit; ///< 单位
+ uint16_t min_ad_value; ///< 最小AD值
+ uint16_t max_ad_value; ///< 最大AD值
+ float32 min_set; ///< 最小值
+ float32 max_set; ///< 最大值
+ uint32_t crc; ///< CRC校验
+} pressure_calib_param_t; ///< 压力校准参数
+
+typedef union
+{
+ uint64_t data;
+ struct
+ {
+ uint8_t app_init_over : 1; ///< app初始化完成标志:中断中有部分方法需要应用层全部初始化完成后再执行
+ uint8_t current_low : 1; ///< 低电流标识位,参考SYSTEM_CLOCK_HIGHT_CURRENT_MIN
+ uint8_t lcd_detect : 1; ///< LCD检测,用于标记LCD扩展板是否存在,将反初始化LED和LCD
+ uint8_t small_signal_deal : 1; ///< 小信号处理标志位
+ uint8_t tuning_enter : 1; ///< 校准进入
+ uint8_t auto_tuning_enter : 1; ///< 自动校准进入
+ uint8_t hart_rts_on : 1; ///< 用于测试HART通讯,数据发送完成标志位
+ uint8_t hart_send_test : 2; ///< HART发送测试 0:不发送 1:发送测试0 2:发送测试1
+
+ uint8_t calib_param_storage : 1; ///< 校准参数存储标志位,用于校验一致性
+ uint8_t specification_table_data_storage : 1; ///< 规格表数据存储标志位,用于校验一致性
+ uint8_t mode_params_storage : 1; ///< 算法存储标志位,用于校验一致性
+ uint8_t hart_attribute_storage : 1; ///< HART属性存储标志位,用于校验一致性
+ uint8_t hart_variable_storage : 1; ///< HART变量存储标志位,用于校验一致性
+ uint8_t hart_constant_storage : 1; ///< HART常量存储标志位,用于校验一致性
+ uint8_t hart_standard_variable_storage : 1; ///< HART标准变量存储标志位,用于校验一致性
+ } bits;
+} rt_data_flag_u;
+
+typedef struct
+{
+ rt_data_flag_u flag; ///< 实时数据标志位
+
+ uint8_t record_algorithm_mode; ///< 设备算法模式,用于切到正常模式时恢复
+ uint8_t tuned_id; ///< 整定步骤
+ uint16_t mode_auto_load; ///< 模式自动加载,算法运行周期 ms
+ uint16_t ip_output; ///< IP输出值
+ uint16_t minor_loop_normal; ///< TODO 暂不明确
+ uint16_t crossover_out_u; ///< 磁条反馈原始值
+ uint16_t humidity; ///< 设备湿度
+ uint32_t seconds; ///< 总共秒数 从2000年开始
+ float32 temperature; ///< 设备温度
+ float32 loop_current; ///< 回路电流
+ float32 target_travel; ///< 目标行程/目标位置
+ float32 actual_travel; ///< 实际行程(阀门行程/实际位置)
+ float32 test_target; ///< 测试模式目标
+ float32 servo_feedback; ///< 伺服反馈(和实际行程的值一样)
+ float32 pressure_s; ///< 气源压力
+ float32 pressure_a; ///< A路压力
+ float32 pressure_b; ///< B路压力
+ float32 pressure_s_kpa; ///< 气源压力
+ float32 pressure_a_kpa; ///< A路压力
+ float32 pressure_b_kpa; ///< B路压力
+ float32 pressure_cross_point; ///< 交叉点
+ float32 friction; ///< 摩擦力
+ float32 elasticity; ///< 弹簧力
+ float32 cpu_percent; ///< CPU使用率
+ float32 cpu_temperature; ///< CPU温度
+ float32 cpu_volt; ///< CPU内部电压
+ float32 board_current; ///< 板卡电流
+ float32 dc; ///< DCDC电压
+ float32 vdd; ///< VDD电压
+ float32 mem_percent; ///< 内存使用率
+ float32 driver_signal; ///< 驱动信号(百分比)
+
+ ///< 系统内部参数
+ uint32_t storage_change; ///< 存储变化次数
+ float32 pid_target; // pid控制目标
+ float32 pid_actual; // pid控制实际
+ float32 show_loop;
+ float32 show_target;
+ float32 show_actual;
+ uint32_t cpuid[3]; ///< CPUID
} real_time_data_t;
-/// 驱动使能图标
+typedef struct
+{
+ uint16_t pow_on_cnt_flag; ///< 上电复位标志
+} flash_storage_t;
+
+////< 驱动使能图标
typedef union
{
uint64_t dev;
struct
{
- uint64_t hart : 1; // hart模块
- uint64_t bluetooth : 1; // 蓝牙模块
- uint64_t work_mode : 3; // 工作模式
- uint64_t write_protect : 1; // 写保护
- uint64_t lock : 1; // 锁模块
- } Bits;
+ uint64_t hart : 1; ///< hart模块
+ uint64_t bluetooth : 1; ///< 蓝牙模块
+ uint64_t work_mode : 3; ///< 工作模式
+ uint64_t write_protect : 1; ///< 写保护
+ uint64_t lock : 1; ///< 锁模块
+ } bits;
} driver_icon_enable_u;
-#pragma pack() // 编译器中提供了#pragma pack(n)来设定变量以n字节对齐方式
+typedef union
+{
+ uint8_t data;
+ struct
+ {
+ uint8_t reset_or_power_on : 1; ///< 复位或上电标志 FALSE: 复位 TRUE: 上电
+ } bits;
+} noinit_dat_flag_u;
-extern device_typedef udevice; ///< 设备参数
-extern __IO calib_param_t calib_param[CALIBPARA_NUM]; ///< 校准参数
-extern real_time_data_t rt_data; ///< 实时参数
-extern mode_params_t mode_params; ///< 模式参数
-extern pid_t _pid; ///< PID参数
-extern driver_icon_enable_u driver_icon_enable; ///< 驱动使能图标
-// 模拟量
+// 复位不清除的参数
+typedef struct
+{
+ uint16_t rest_flag; ///< 复位标志
+ noinit_dat_flag_u flag; ///< 复位或上电标志
+
+ uint8_t language; ///< 语言
+ uint8_t inst_mode; ///< 仪表模式
+ uint8_t control_mode; ///< 控制模式
+ uint8_t dev_algorithm_mode; ///< 定位器算法模式
+ uint16_t dev_model; ///< 定位器型号
+ float32 dead_zone; ///< 死区
+ int16_t travel_set_pt; ///< 目标行程设定值
+ uint8_t mode_params[300]; ///< 模式参数
+ calib_param_t loop; ///< 4-20mA校准参数
+ calib_param_t loop_output; ///< 4-20mA输出校准参数
+ calib_param_t pressure_s;
+
+ uint32_t crc; ///< 校验
+} noinit_data_t;
+
+// 重启不会初始化的数据
+extern noinit_data_t noinit_data; ///< 复位不初始化数据
+extern __IO udevice_t udevice; ///< 设备参数
+extern __IO rt_save_param_t rt_save; ///< 实时保存参数
+
+extern __IO calib_param_t calib_param[CALIBPARA_MAX]; ///< 校准参数
+extern __IO real_time_data_t rt_data; ///< 实时参数
+extern pressure_calib_param_t pressure_calib_param[PRESSURE_PARAM_MAX]; ///< 压力校准参数
+extern mode_params_u mode_params; ///< 模式参数
+extern pid_t _pid; ///< PID参数
+extern driver_icon_enable_u driver_icon_enable; ///< 驱动使能图标
+
+///< 模拟量
extern __IO uint16_t adc_raw[ADC1_MAX]; ///< ADC原始值
-extern uint32_t mode_default_autoload; ///< 默认自动加载
-// 数字量
-extern __IO float32 pid_target; ///< pid控制目标
-extern __IO float32 pid_actual; ///< pid控制实际
-extern __IO float32 show_loop; ///< 显示电流
-extern __IO float32 show_target; ///< 显示目标
-extern __IO float32 show_actual; ///< 显示实际
-extern __IO float32 range_percentage; ///< 量程百分比
-extern __IO flow_event_e flow_event; ///< 任务流程状态机
-// 函数
+
+extern __IO flow_event_e flow_event; ///< 任务流程状态机
+
+///< 函数
extern void h24_bluetooth_output_dbg(uint8_t *data, uint16_t len); ///< 蓝牙输出调试
-extern void h24_bluetooth_output(uint8_t *data, uint16_t len); ///< 蓝牙输出
-#endif // __ENTITY_H__
+extern void bluetooth_output(uint8_t *data, uint16_t len); ///< 蓝牙输出
+
+extern void board_data_save(void); ///< 保存板卡参数
+extern void noinit_data_set(void); ///< 复位不清除数据设置
+#endif ///< __ENTITY_H__
diff --git a/User/hart/Makefile b/User/hart/Makefile
new file mode 100644
index 0000000..de037ff
--- /dev/null
+++ b/User/hart/Makefile
@@ -0,0 +1,82 @@
+#指定32位python路径,python版本需要3.8以下
+# C:\Users\xushenghao\AppData\Local\Programs\Python\Python37-32\python.exe
+PYTHON = python
+# 变量BIN: 给定的是我们想要生成的可执行文件的名称
+BIN = hart.dll
+
+
+INC= -I lib/inc -I lib/flow
+# 变量SRC中给的是所有的想要编译的.c源文件,与makefile在同一目录下可直接写(如这里的main.c),否则需要写明相对路径(如这里的其余源文件都在目录src下)。
+# 多文件时,选择用"\"进行分行处理
+SRC = \
+ lib/flow/flow_core.c \
+ lib/src/aes.c \
+ lib/src/cmac.c \
+ lib/src/malloc.c \
+ lib/src/debug.c \
+ lib/src/sqqueue.c \
+ lib/src/lib.c \
+ hart.c \
+ hart_frame.c \
+ hart_cache.c \
+ master/src/hart_master_frame.c \
+ master/src/hart_master_req_user.c \
+ master/src/hart_master_req.c \
+ master/src/hart_master_rsp.c \
+ master/src/hart_master.c \
+ slave/src/hart_slave_frame.c \
+ slave/src/hart_slave_req_user.c \
+ slave/src/hart_slave_req.c \
+ slave/src/hart_slave_frame_mock.c \
+ slave/src/hart_slave.c \
+
+
+TEST = \
+ test/src/run.py
+
+TEST_SIMPLE = \
+ test/src/test_hart_slave_req.py
+
+# 变量CC:给定编译器名gcc
+# 变量CFLAGS:传给编译器的某些编译参数,看需求添加
+CC = gcc
+CFLAGS = -m32 -shared -std=c99 -DMASTER -DSLAVE
+
+# 变量GDB:给定debugger名gdb
+# 变量RM:给定删除文件方式,用于后面删除所有编译所得的.o文件,linux下使用rm -rf
+GDB = gdb
+RM = rm -rf
+# 变量OBJS:将变量SRC中所有的.c文件替换成以.o结尾,即将.c源文件编译成.o文件
+OBJS = $(SRC:%.c=%.o)
+
+all: so test clean
+
+so: $(BIN)
+
+$(BIN): $(OBJS)
+ $(CC) $(CFLAGS) $^ -o $@
+
+# pull in dependencies for .o files
+-include $(OBJS:.o=.d)
+
+
+%.o: %.c
+ $(CC) $(CFLAGS) $(INC) -c $< -o $@
+
+
+.PHONY: so test clean
+
+
+ss: so test_simple clean
+
+dev:
+ $(PYTHON) main.py
+
+test:
+ $(PYTHON) $(TEST)
+
+test_simple:
+ $(PYTHON) $(TEST_SIMPLE)
+
+clean:
+ $(RM) $(BIN) $(OBJS)
diff --git a/User/hart/hart.c b/User/hart/hart.c
new file mode 100644
index 0000000..e33bf13
--- /dev/null
+++ b/User/hart/hart.c
@@ -0,0 +1,448 @@
+/*
+ * @Author:
+ * @Date: 2023-03-20 19:27:00
+ * @LastEditors: xxx
+ * @LastEditTime: 2023-08-29 11:44:01
+ * @FilePath: \hart\hart\hart.c
+ * @Description: hart模块接口
+ * email:
+ * Copyright (c) 2023 by xxx, All Rights Reserved.
+ */
+
+#include "./inc/hart.h"
+#include "./slave/inc/hart_slave_frame.h"
+
+#define HART_INIT_FLAG (0x0520) ///< 初始化标志
+
+static hart_init_t handle;
+static hart_response_t response;
+
+BOOL(*hart_command_ptr_arr[HART_COMMAND_MAX])
+(const hart_command_req_t *const req, hart_response_t *resp);
+
+/**
+ * @brief 获取HART句柄
+ *
+ * 该函数返回HART句柄的指针。
+ *
+ * @return 返回HART句柄的指针
+ */
+hart_init_t *hart_get_handle(void)
+{
+ return &handle;
+}
+
+/**
+ * @brief hart模块初始化
+ * @param {hart_init_t} *init: 初始化参数
+ * @return: TRUE: 初始化成功
+ * FALSE: 初始化失败
+ */
+BOOL hart_init(const hart_init_t *const init)
+{
+ // 将初始数据赋值给handle
+ if (!DBG_ASSERT(init != NULL __DBG_LINE))
+ return FALSE;
+ osel_memcpy((uint8_t *)&handle, (uint8_t *)init, sizeof(hart_init_t));
+
+ // 检查参数
+ if (!DBG_ASSERT((handle.dir == MODULE_MASTER) || (handle.dir == MODULE_SLAVE) __DBG_LINE))
+ return FALSE;
+
+ if (!DBG_ASSERT(handle.interface.response != NULL __DBG_LINE))
+ return FALSE;
+
+ // 缓存消息初始化
+ hart_cache_init();
+#ifdef MASTER
+ if (handle.dir == MODULE_MASTER) // 主机模块初始化
+ {
+ handle.hart_module_u._master.address_bit = handle.master_address_bit;
+ if (handle.hart_module_u._master.address_bit != HART_MASTER)
+ {
+ handle.hart_module_u._master.address_bit = 0;
+ }
+
+ handle.hart_module_u._master.response_call = handle.interface.response;
+ handle.hart_module_u._master.response = &response;
+ if (!DBG_ASSERT(hart_master_init(&handle.hart_module_u._master) == TRUE __DBG_LINE))
+ return FALSE;
+
+#if MOCK == 1
+ mock_master_attribute();
+#endif
+ }
+#endif
+
+#ifdef SLAVE
+ hart_device_attribute.hart_protocol_version = &handle.hart_protocol_version;
+ hart_device_attribute.message_count.ack = 0; // 响应消息计数
+ if (!DBG_ASSERT((hart_get_current_protocol_version() == HART_PROTOCOL_VERSION_5 ||
+ hart_get_current_protocol_version() == HART_PROTOCOL_VERSION_7) __DBG_LINE)) // 校验协议版本号,模块支持协议版本为5,7
+ return FALSE;
+ if (handle.dir == MODULE_SLAVE) // 从机模块初始化
+ {
+
+#ifdef STM32
+ if (!DBG_ASSERT(handle.interface.flash_read != NULL __DBG_LINE)) // 从机模块必须实现flash_read接口
+ return FALSE;
+ if (!DBG_ASSERT(handle.interface.flash_write != NULL __DBG_LINE)) // 从机模块必须实现flash_write接口
+ return FALSE;
+ if (!DBG_ASSERT(handle.interface.flash_read_item != NULL __DBG_LINE)) // 从机模块必须实现flash_read接口
+ return FALSE;
+ if (!DBG_ASSERT(handle.interface.flash_write_item != NULL __DBG_LINE)) // 从机模块必须实现flash_write接口
+ return FALSE;
+ if (!DBG_ASSERT(handle.interface.perform_self_test != NULL __DBG_LINE)) // 从机模块必须实现perform_self_test接口
+ return FALSE;
+ if (!DBG_ASSERT(handle.interface.device_reset != NULL __DBG_LINE)) // 从机模块必须实现device_reset接口
+ return FALSE;
+ if (!DBG_ASSERT(handle.interface.squawk_control != NULL __DBG_LINE)) // 从机模块必须实现squawk_control接口
+ return FALSE;
+ if (!DBG_ASSERT(handle.interface.armed != NULL __DBG_LINE)) // 从机模块必须实现armed接口
+ return FALSE;
+ if (!DBG_ASSERT(handle.interface.user_common_event != NULL __DBG_LINE)) // 从机模块必须实现user_common_event接口
+ return FALSE;
+#endif
+
+ handle.hart_module_u._slave.response_call = handle.interface.response;
+ handle.hart_module_u._slave.response = &response;
+ if (!DBG_ASSERT(hart_slave_init(&handle.hart_module_u._slave) == TRUE __DBG_LINE))
+ return FALSE;
+
+#ifdef STM32
+ hart_slave_device_attribute_init();
+ if (!DBG_ASSERT(handle.interface.set_dynamics != NULL __DBG_LINE)) // 从机模块必须动态数据接口
+ return FALSE;
+ BOOL ret = FALSE;
+ BOOL ret2 = FALSE;
+ BOOL ret3 = FALSE;
+
+ // 从flash中读取设备属性
+ ret = handle.interface.flash_read(HART_STORAGE_PARAMS, (uint8_t *)&hart_device_attribute.flash_variable);
+
+ if (ret == TRUE)
+ {
+ if (hart_device_attribute.flash_variable.init_flag != HART_INIT_FLAG)
+ {
+ ret = FALSE;
+ }
+ }
+
+ if (ret == FALSE)
+ {
+ INIT:
+ if (!DBG_ASSERT(handle.interface.attribute_init != NULL __DBG_LINE))
+ return FALSE;
+ handle.interface.attribute_init();
+ handle.interface.variable_init();
+ }
+ else
+ {
+ ret = handle.interface.flash_read(HART_STORAGE_VARIABLE, (uint8_t *)&hart_device_attribute.device_variable);
+ if (ret == TRUE)
+ {
+ ret2 = handle.interface.flash_read(HART_STORAGE_CONSTANT, (uint8_t *)&hart_device_attribute.device_constant);
+ }
+
+ if (ret2 == TRUE)
+ {
+ ret3 = handle.interface.flash_read(HART_STORAGE_STANDARD_VARIABLE, (uint8_t *)&hart_device_attribute.device_standard_variable);
+ }
+
+ // 注:hart_device_attribute.device_variable[0].code != DIN_ANALOG_INPUT 这个判断是为了解决没有读到数据的情况,flash_variable可以设置crc32,这个变量是数组无法设定,用第一个和第二个变量判断
+ if (ret == FALSE || ret2 == FALSE || ret3 == FALSE ||
+ hart_device_attribute.device_variable[0].code != DIN_ANALOG_INPUT || hart_device_attribute.device_variable[1].code != DIN_INTERNAL_TEMPERATURE)
+ {
+ goto INIT;
+ }
+ }
+
+ // 动态属性
+ handle.interface.set_dynamics(&hart_device_attribute.dynamics);
+
+ hart_device_attribute.hart_protocol_version = &handle.hart_protocol_version;
+ hart_device_attribute.message_count.ack = 0; // 响应消息计数
+#else
+ mock_data();
+#endif
+ }
+#endif
+
+ return TRUE;
+}
+
+/**
+ * @brief hart模块数据处理函数
+ * @param {uint8_t} uart_index: 串口索引
+ * @param {uint8_t} uart_error: 串口错误
+ * @param {uint8_t} *rxBuf: 接收到的数据
+ * @param {uint16_t} len: 接收到的数据长度
+ * @return: TRUE: 处理成功
+ * FALSE: 处理失败
+ */
+BOOL hart_handle(uint8_t uart_index, uint8_t *rxBuf, uint16_t len)
+{
+ if (!DBG_ASSERT(rxBuf != NULL __DBG_LINE))
+ return FALSE;
+ if (!DBG_ASSERT(len != 0 __DBG_LINE))
+ return FALSE;
+
+ if (!DBG_ASSERT((handle.dir == MODULE_MASTER) || (handle.dir == MODULE_SLAVE) __DBG_LINE))
+ return FALSE;
+
+ // 根据模块工作模式将数据分发给对应的主机或从机处理
+#ifdef MASTER
+ if (handle.dir == MODULE_MASTER)
+ {
+ return hart_master_handle(rxBuf, len);
+ }
+#endif
+
+#ifdef SLAVE
+ if (handle.dir == MODULE_SLAVE)
+ {
+ return hart_slave_handle(uart_index, rxBuf, len);
+ }
+#endif
+ return FALSE;
+}
+
+void hart_cache_data_send(uint64_t uuid)
+{
+ hart_cache_t *p;
+ p = hart_cache_get(uuid);
+ if (NULL != p)
+ {
+ LOG_PRINT("%d", p->uuid);
+#ifdef SLAVE
+ hart_slave_device_send(p);
+#endif
+ }
+}
+
+/**
+ * @brief 获取指定UART接口的错误计数
+ *
+ * 该函数用于获取指定UART接口的错误计数。
+ *
+ * @param uart_index UART接口的索引
+ *
+ * @return 返回指定UART接口的错误计数
+ */
+uint16_t hart_uart_error_count(uint8_t uart_index)
+{
+ return handle.interface.uart_error_count(uart_index);
+}
+
+/**
+ * @brief 处理UART错误
+ *
+ * 该函数用于处理指定UART接口的错误。
+ *
+ * @param uart_index UART接口的索引
+ * @param errors 用于存储错误信息的指针
+ */
+void hart_uart_errors(uint8_t uart_index, hart_uart_error_t *errors)
+{
+ handle.interface.uart_errors(uart_index, errors);
+}
+
+/**
+ * @brief 开始解析帧数据的计时
+ *
+ * 该函数用于启动帧数据解析的计时器。
+ *
+ * @param timer_period 计时器周期
+ */
+void frame_data_parse_time_start(uint16_t timer_period)
+{
+ handle.interface.frame_data_parse_time_start(timer_period);
+}
+
+/**
+ * @brief 获取时间戳
+ * @return {*}
+ * @note
+ */
+uint32_t hart_get_timestamp(void)
+{
+ return handle.interface.get_timestamp();
+}
+
+/**
+ * @brief flash写入 hart内部使用
+ * @param {uint32_t} addr
+ * @param {uint8_t} *data
+ * @return {*}
+ */
+BOOL hart_storage_write(hart_storage_e index, uint8_t *data)
+{
+ return handle.interface.flash_write(index, data);
+}
+/**
+ * @brief falsh读取 hart内部使用
+ * @param {uint32_t} addr
+ * @param {uint8_t} *dat
+ * @return {*}
+ */
+BOOL hart_storage_read(hart_storage_e index, uint8_t *data)
+{
+ return handle.interface.flash_read(index, data);
+}
+
+BOOL hart_storage_write_item(hart_storage_e index, uint8_t item, uint8_t *data)
+{
+ return handle.interface.flash_write_item(index, item, data);
+}
+BOOL hart_storage_read_item(hart_storage_e index, uint8_t item, uint8_t *data)
+{
+ return handle.interface.flash_read_item(index, item, data);
+}
+/**
+ * @brief 自检
+ * @return {*}
+ */
+void hart_perform_self_test(void)
+{
+#ifdef SLAVE
+ hart_device_attribute.device_status.busy = TRUE;
+ handle.interface.perform_self_test();
+#endif
+}
+
+/**
+ * @brief 自检完成
+ * @return {*}
+ */
+void perform_self_test_finish(void)
+{
+#ifdef SLAVE
+ hart_device_attribute.device_status.busy = FALSE;
+#endif
+}
+
+/**
+ * @brief 设备复位
+ * @return {*}
+ */
+void hart_device_reset(void)
+{
+ hart_device_attribute.device_status.reset = TRUE;
+ handle.interface.device_reset(); // 这里的接口不是真复位,而是在LCD上显示复位信息
+}
+
+/**
+ * @brief 呼叫
+ * @param {BOOL} open
+ * @param {uint8_t} second
+ * @return {*}
+ */
+void hart_squawk_control(BOOL open, uint8_t second)
+{
+ handle.interface.squawk_control(open, second);
+}
+
+/**
+ * @brief 技术人员按下一个特殊的按钮或按钮组合,指示从机应响应command74
+ * @return {*}
+ */
+BOOL hart_armed(void)
+{
+ return handle.interface.armed();
+}
+
+/**
+ * @brief 设置实时时钟
+ * @param {uint8_t} year
+ * @param {uint8_t} month
+ * @param {uint8_t} day
+ * @param {uint8_t} hour
+ * @param {uint8_t} min
+ * @param {uint8_t} sec
+ * @return {*}
+ * @note
+ */
+void hart_set_real_time_clock(uint8_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t min, uint8_t sec)
+{
+ if (handle.interface.set_real_time_clock == NULL)
+ return;
+
+ handle.interface.set_real_time_clock(year, month, day, hour, min, sec);
+}
+
+/**
+ * @brief 获取实时时钟
+ * @param {uint8_t} *year
+ * @param {uint8_t} *month
+ * @param {uint8_t} *day
+ * @param {uint8_t} *hour
+ * @param {uint8_t} *min
+ * @param {uint8_t} *sec
+ * @return {*}
+ * @note
+ */
+void hart_get_real_time_clock(uint8_t *year, uint8_t *month, uint8_t *day, uint8_t *hour, uint8_t *min, uint8_t *sec)
+{
+ if (handle.interface.get_real_time_clock == NULL)
+ return;
+
+ handle.interface.get_real_time_clock(year, month, day, hour, min, sec);
+}
+
+BOOL hart_user_common_event(hart_interface_user_event_e event, const void *const data)
+{
+#ifdef STM32
+ if (handle.interface.user_common_event == NULL)
+ return FALSE;
+ return handle.interface.user_common_event(event, data);
+#else
+ return TRUE;
+#endif
+}
+
+BOOL get_device_lock(void)
+{
+ return hart_device_attribute.flash_variable.lock_code == LOCK_DEVICE_CODE_0 ? FALSE : TRUE;
+}
+
+/**
+ * @brief 定时器中断回调函数
+ *
+ * 当定时器触发中断时,该函数会被调用。
+ * 该函数为空实现,用户可以根据具体需求进行扩展。
+ */
+void hart_timer_interupt_cb(void)
+{
+ if (hart_get_handle()->hart_timer.counter > 0)
+ {
+ hart_get_handle()->hart_timer.counter--;
+ }
+}
+
+/**
+ * @brief 启动HART定时器
+ *
+ * 设置HART定时器的周期,并启动定时器。
+ *
+ * @param timer_period 定时器周期(单位:毫秒)
+ */
+void hart_timer_start(uint16_t timer_period)
+{
+ hart_get_handle()->hart_timer.counter = timer_period / hart_get_handle()->hart_timer.timer_cycle;
+}
+
+/**
+ * 1. 每个字节间隔超过10毫秒就丢弃这组数据
+ * 2. 数据处理的时间,257毫秒,丢包
+ */
+BOOL hart_timeout_compare(void)
+{
+ if (hart_get_handle()->hart_timer.counter == 0)
+ {
+ return FALSE;
+ }
+ else
+ {
+ return TRUE;
+ }
+}
diff --git a/User/hart/hart_cache.c b/User/hart/hart_cache.c
new file mode 100644
index 0000000..0f688a2
--- /dev/null
+++ b/User/hart/hart_cache.c
@@ -0,0 +1,133 @@
+/*
+ * @Author:
+ * @Date: 2023-08-03 22:36:49
+ * @LastEditors: xxx
+ * @LastEditTime: 2023-08-06 16:13:52
+ * @Description: 缓存消息模块,处理设备操作需要时间暂时不回复消息的情况
+ * email:
+ * Copyright (c) 2023 by xxx, All Rights Reserved.
+ */
+
+#include "./inc/hart_frame.h"
+#include
+#include
+
+#define HART_CACHE_LEN 1U
+sqqueue_ctrl_t cache;
+
+#ifndef STM32
+static uint32_t sys_millis(void)
+{
+ return 0;
+}
+#else
+#include "delay.h"
+#endif
+
+// 缓存消息初始化
+void hart_cache_init(void)
+{
+ // srand((unsigned)time(NULL)); // 初始化随机数种子
+
+ sqqueue_ctrl_init(&cache, sizeof(hart_cache_t), HART_CACHE_LEN); // 初始化队列
+}
+
+// 向缓存中添加数据
+void hart_cache_add(hart_cache_t data)
+{
+ hart_cache_t *e;
+ if (cache.get_len(&cache) >= HART_CACHE_LEN)
+ {
+ return; // 缓存已满
+ }
+
+ e = (hart_cache_t *)osel_mem_alloc(sizeof(hart_cache_t)); // 申请内存
+
+ osel_memcpy((uint8_t *)e, (uint8_t *)&data, sizeof(hart_cache_t)); // 拷贝数据
+
+ if (data.uuid == 0)
+ {
+ // data.uuid = rand(); // 生成随机数
+ return;
+ }
+
+ e->uuid = data.uuid;
+ cache.enter(&cache, (void *)e); // 入队
+}
+
+// 释放缓存数据
+void hart_cache_free(hart_cache_t *data)
+{
+ if (data != NULL)
+ {
+ osel_mem_free(data);
+ }
+}
+
+// 从缓存中获取数据
+hart_cache_t *hart_cache_get(uint64_t uuid)
+{
+ hart_cache_t *e;
+ uint16_t len = cache.get_len(&cache);
+
+ if (len == 0)
+ {
+ return NULL; // 缓存为空
+ }
+ for (uint8_t i = 0; i < len; i++)
+ {
+ e = ((hart_cache_t *)cache.del(&cache));
+ if (e->uuid == uuid)
+ {
+ return e;
+ }
+ else
+ {
+ cache.enter(&cache, e);
+ }
+ }
+ return NULL;
+}
+
+/**
+ * @brief 将指定的uuid对应的数据从缓存区移除
+ * @param {uint64_t} uuid
+ * @return {*}
+ * @note
+ */
+void hart_cache_remove(uint64_t uuid)
+{
+ hart_cache_get(uuid);
+}
+
+/**
+ * @brief 检查HART缓存区是否存活
+ * @return {*}
+ * @note
+ */
+void hart_cache_detection(void)
+{
+ hart_cache_t *e;
+ uint16_t len = cache.get_len(&cache);
+
+ if (len == 0)
+ {
+ return; // 缓存为空
+ }
+ for (uint8_t i = 0; i < len; i++)
+ {
+ e = ((hart_cache_t *)cache.del(&cache));
+
+ uint32_t now = sys_millis();
+
+ if (now <= e->hart_cache_time) // 存活
+ {
+ cache.enter(&cache, e);
+ continue;
+ }
+ else // 死亡
+ {
+ continue;
+ }
+ }
+}
diff --git a/User/hart/hart_frame.c b/User/hart/hart_frame.c
new file mode 100644
index 0000000..26abf1b
--- /dev/null
+++ b/User/hart/hart_frame.c
@@ -0,0 +1,387 @@
+/*
+ * @Author:
+ * @Date: 2023-03-20 19:27:47
+ * @LastEditors: wangxujie-laptop 390834610@qq.com
+ * @LastEditTime: 2024-09-11 10:51:36
+ * @FilePath: \hart\hart\hart_frame.c
+ * @Description:
+ * email:
+ * Copyright (c) 2023 by xxx, All Rights Reserved.
+ */
+
+#include "./inc/hart_frame.h"
+#include "../slave/inc/hart_slave_frame.h"
+static uint8_t *hart_frame_data_length_p; // 帧数据长度位置
+static uint8_t *hart_frame_response_code_p; // 帧响应码位置
+
+/**
+ * @brief 在处理请求开始时记录帧响应码起始位置
+ * @param {uint8_t} *
+ * @return {*}
+ */
+void hart_frame_response_code_start(uint8_t **data_p)
+{
+ hart_frame_response_code_p = *data_p;
+}
+
+/**
+ * @brief 响应码第一个字节为通信有关的信息
+ * @param {uint8_t} code
+ * @return {*}
+ * 1. 第7位如果是1,则剩余的位包含了有关通信错误的信息 response_error_communication_code_e
+ * 2. 第7位如果是0,则剩余的位包含了有关通信正常的信息 response_communication_code_e
+ */
+void hart_frame_response_communication_code(uint8_t code)
+{
+ *hart_frame_response_code_p = code;
+}
+
+/**
+ * @brief 响应码第二个字节为设备的操作状态有关的信息
+ * 如在第一个字节中最高位置1,则该字节无意义
+ * @param {uint8_t} code
+ * @return {*}
+ */
+void hart_frame_slave_response_operate_code(hart_device_attribute_t *hart_device_attribute)
+{
+ /**
+ * 判断当前设备状态的crc和device_status_crc是否一致
+ * Note:
+ Masters will issue this command whenever More Status Available (Bit 4 of the device status byte) issetAs a result, the Field Device must carefully define and contro the events and status information inthis command that affect these two device status bits. f the More Status Available bit is alwaysasserted. then communication bandwidth is effectively cut in half.
+ */
+ uint16_t crc = crc16_compute((uint8_t *)&hart_device_attribute->device_status.additional_device_status, sizeof(additional_device_status_t));
+ if (hart_device_attribute->device_status.additional_device_status_crc != crc)
+ {
+ hart_device_status_set_operational_state(DEVICE_OPERATIONAL_STATE_5);
+ }
+ else
+ {
+ hart_device_status_clr_operational_state(DEVICE_OPERATIONAL_STATE_5);
+ }
+
+ *(hart_frame_response_code_p + 1) = hart_device_attribute->device_status.operational_state;
+}
+
+/**
+ * @brief 响应码第二个字节为设备的操作状态有关的信息,主机默认回复0x00
+ * @return {*}
+ */
+void hart_frame_master_response_operate_code(void)
+{
+ *(hart_frame_response_code_p + 1) = 0x00;
+}
+
+/**
+ * @brief在处理请求开始时记录帧数据域长度起始位置
+ * @param {uint8_t} *data_p
+ * @return {*}
+ */
+void hart_frame_data_length_start(uint8_t **data_p)
+{
+ DBG_ASSERT(data_p != NULL __DBG_LINE);
+ DBG_ASSERT(*data_p != NULL __DBG_LINE);
+
+ hart_frame_data_length_p = *data_p;
+}
+/**
+ * @brief在处理请求结束时记录帧数据长度位置
+ * @param {uint8_t} *data_p
+ * @return {*}
+ */
+void hart_frame_data_length_end(uint8_t *data_p)
+{
+ *hart_frame_data_length_p = data_p - hart_frame_data_length_p - 1; // 计算数据个数
+ // LOG_PRINT("%d", *hart_frame_data_length_p);
+}
+
+// 判断指令是否是写
+BOOL hart_is_write_command(uint16_t command)
+{
+ // 先判断是否在用户自定义的指令中
+ uint16_t user_version[] = {HART_COMMAND_130, HART_COMMAND_131, HART_COMMAND_135, HART_COMMAND_143, HART_COMMAND_149, HART_COMMAND_154,
+ HART_COMMAND_162, HART_COMMAND_165, HART_COMMAND_167};
+ if (is_in_array(user_version, ARRAY_LEN(user_version), command))
+ {
+ return TRUE;
+ }
+
+ uint16_t cmd[] = {HART_COMMAND_6, HART_COMMAND_17, HART_COMMAND_18, HART_COMMAND_19, HART_COMMAND_22,/* HART_COMMAND_38,//ZKBW*/
+ HART_COMMAND_34, HART_COMMAND_35, HART_COMMAND_36, HART_COMMAND_37, HART_COMMAND_39, HART_COMMAND_40, HART_COMMAND_43,
+ HART_COMMAND_44, HART_COMMAND_45, HART_COMMAND_46, HART_COMMAND_47, HART_COMMAND_49, HART_COMMAND_51, HART_COMMAND_52,
+ HART_COMMAND_53, HART_COMMAND_55, HART_COMMAND_56, HART_COMMAND_58, HART_COMMAND_59, HART_COMMAND_64, HART_COMMAND_65,
+ HART_COMMAND_66, HART_COMMAND_67, HART_COMMAND_68, HART_COMMAND_69, HART_COMMAND_79, HART_COMMAND_82, HART_COMMAND_83,
+ HART_COMMAND_87, HART_COMMAND_88, HART_COMMAND_92, HART_COMMAND_97, HART_COMMAND_99, HART_COMMAND_100, HART_COMMAND_102,
+ HART_COMMAND_103, HART_COMMAND_104, HART_COMMAND_107, HART_COMMAND_108, HART_COMMAND_109, HART_COMMAND_112,
+ HART_COMMAND_116, HART_COMMAND_117, HART_COMMAND_118, HART_COMMAND_513, HART_COMMAND_517, HART_COMMAND_519,
+ HART_COMMAND_521, HART_COMMAND_522, HART_COMMAND_524, HART_COMMAND_525, HART_COMMAND_526, HART_COMMAND_535,
+ HART_COMMAND_539, HART_COMMAND_540};
+ return is_in_array(cmd, ARRAY_LEN(cmd), command);
+}
+
+// 判断版本是否支持当前指令
+BOOL hart_is_support_command(uint16_t command)
+{
+ if (HART_PROTOCOL_VERSION_SUPPORT_COMMAND == 0)
+ {
+ return TRUE;
+ }
+
+ // 先判断是否在用户自定义的指令中
+ uint16_t user_version[] = {/*HART_COMMAND_31, HART_COMMAND_109, */ HART_COMMAND_129, HART_COMMAND_130, HART_COMMAND_131, HART_COMMAND_132,
+ HART_COMMAND_133, HART_COMMAND_134, HART_COMMAND_135, HART_COMMAND_136, HART_COMMAND_138, HART_COMMAND_140,
+ HART_COMMAND_141, HART_COMMAND_142, HART_COMMAND_143, HART_COMMAND_144,
+ HART_COMMAND_145, HART_COMMAND_146, HART_COMMAND_147, HART_COMMAND_149, HART_COMMAND_150, HART_COMMAND_151, HART_COMMAND_153,
+ HART_COMMAND_154, HART_COMMAND_155, HART_COMMAND_156, HART_COMMAND_157, HART_COMMAND_158, HART_COMMAND_162, HART_COMMAND_164, HART_COMMAND_165,
+ HART_COMMAND_167, HART_COMMAND_168, HART_COMMAND_170, HART_COMMAND_187, HART_COMMAND_200};
+ if (is_in_array(user_version, ARRAY_LEN(user_version), command))
+ {
+ return TRUE;
+ }
+
+ if (hart_get_current_protocol_version() == HART_PROTOCOL_VERSION_5)
+ {
+ uint16_t version[] = {HART_COMMAND_0, HART_COMMAND_1, HART_COMMAND_2, HART_COMMAND_6, HART_COMMAND_11, HART_COMMAND_12,
+ HART_COMMAND_13, HART_COMMAND_14, HART_COMMAND_15, HART_COMMAND_16, HART_COMMAND_17, HART_COMMAND_18, HART_COMMAND_19,
+ HART_COMMAND_33, HART_COMMAND_34, HART_COMMAND_35, HART_COMMAND_36, HART_COMMAND_37, HART_COMMAND_38, HART_COMMAND_39,
+ HART_COMMAND_40, HART_COMMAND_41, HART_COMMAND_42, HART_COMMAND_43, HART_COMMAND_44, HART_COMMAND_45, HART_COMMAND_46,
+ HART_COMMAND_47, HART_COMMAND_48, HART_COMMAND_49, HART_COMMAND_50, HART_COMMAND_51, HART_COMMAND_52, HART_COMMAND_53,
+ HART_COMMAND_54, HART_COMMAND_55, HART_COMMAND_56, HART_COMMAND_57, HART_COMMAND_58, HART_COMMAND_59, HART_COMMAND_60,
+ HART_COMMAND_61, HART_COMMAND_62, HART_COMMAND_63, HART_COMMAND_64, HART_COMMAND_65, HART_COMMAND_66, HART_COMMAND_67,
+ HART_COMMAND_68, HART_COMMAND_69, HART_COMMAND_70, HART_COMMAND_107, HART_COMMAND_109, HART_COMMAND_110};
+ if (is_in_array(version, ARRAY_LEN(version), command))
+ {
+ return TRUE;
+ }
+ }
+
+ if (hart_get_current_protocol_version() == HART_PROTOCOL_VERSION_7)
+ {
+ uint16_t version[] = {/*Universal Command */ HART_COMMAND_0, HART_COMMAND_1, HART_COMMAND_2, HART_COMMAND_3, HART_COMMAND_6, HART_COMMAND_7,
+ HART_COMMAND_8, HART_COMMAND_9, HART_COMMAND_11, HART_COMMAND_12, HART_COMMAND_13, HART_COMMAND_14, HART_COMMAND_15,
+ HART_COMMAND_16, HART_COMMAND_17, HART_COMMAND_18, HART_COMMAND_19, HART_COMMAND_20, HART_COMMAND_21, HART_COMMAND_22,
+ HART_COMMAND_38, HART_COMMAND_48, /*Common Command */ HART_COMMAND_33, HART_COMMAND_35, HART_COMMAND_44, HART_COMMAND_50,
+ HART_COMMAND_51, HART_COMMAND_52, HART_COMMAND_53, HART_COMMAND_54, HART_COMMAND_59};
+ if (is_in_array(version, ARRAY_LEN(version), command))
+ {
+ return TRUE;
+ }
+ }
+ LOG_ERR("command %d is not support", command);
+ return FALSE;
+}
+
+/**
+ * @brief 检查数据长度是否符合规定
+ * @param {uint8_t} data_length
+ * @param {uint8_t} data_structure_length 原始的数据结构长度
+ * @return {*}
+ * @note
+ */
+BOOL hart_frame_data_length_check(uint8_t data_length, uint8_t data_structure_length, uint8_t *resp_code)
+{
+ if (data_length != data_structure_length)
+ {
+ if (data_length < data_structure_length)
+ {
+ *resp_code = RESPONSE_COMMUNICATION_CODE_5;
+ return FALSE;
+ }
+ else
+ {
+ *resp_code = RESPONSE_COMMUNICATION_CODE_3;
+ return FALSE;
+ }
+ }
+ else
+ {
+ return TRUE;
+ }
+}
+
+// 日期检测,年月日
+BOOL check_date(rtc_date_t *date)
+{
+ if (date->year > 99)
+ {
+ return FALSE;
+ }
+ if (date->month < 1 || date->month > 12)
+ {
+ return FALSE;
+ }
+ if (date->day < 1 || date->day > 31)
+ {
+ return FALSE;
+ }
+ return TRUE;
+}
+
+// 判断是否是广播地址
+BOOL is_broadcast_address(uint8_t *address, uint8_t len)
+{
+ for (uint8_t i = 0; i < len; i++)
+ {
+ if (*(address + i) != 0x00)
+ {
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+// uint32转小时:分钟:秒:毫秒
+void timestamp_to_hmsms(uint32_t timestamp, uint8_t *hmsms)
+{
+ uint32_t ms = timestamp % 1000;
+ uint32_t s = timestamp / 1000;
+ uint32_t m = s / 60;
+ uint32_t h = m / 60;
+ hmsms[0] = h;
+ hmsms[1] = m % 60;
+ hmsms[2] = s % 60;
+ hmsms[3] = ms;
+}
+
+// assic转十六进制(assic-6)
+void encode_ascii_6(const uint8_t *input, uint16_t input_length, uint8_t *output)
+{
+ uint8_t adjusted_input[input_length];
+ uint16_t i = 0;
+
+ osel_memset(adjusted_input, 0, input_length);
+
+ for (i = 0; i < input_length; i++)
+ {
+ if (input[i] == 0x00)
+ {
+ adjusted_input[i] = 0x20;
+ continue;
+ }
+
+ adjusted_input[i] = input[i] >= 0x40 ? input[i] - 0x40 : input[i];
+ }
+
+ uint16_t acs8_len = i + 1;
+ uint16_t acs6_len = acs8_len * 6 / 8;
+ for (i = 0; i < acs6_len; i++)
+ {
+ uint8_t pos = i * 8 / 6;
+ uint8_t val = adjusted_input[pos] & 0x3f;
+ uint8_t valNext = pos + 1 < acs8_len ? (adjusted_input[pos + 1] & 0x3f) : 0x20;
+ uint8_t newVal = 0;
+ switch (i % 3)
+ {
+ case 0:
+ newVal = val << 2;
+ newVal += valNext >> 4;
+ break;
+ case 1:
+ newVal = val << 4;
+ newVal += valNext >> 2;
+ break;
+ case 2:
+ newVal = val << 6;
+ newVal += valNext;
+ break;
+ }
+ output[i] = newVal;
+ }
+}
+
+// assic-6 转 assic的十六进制
+void decode_ascii_6(const uint8_t *input, uint16_t input_length, uint8_t *output)
+{
+ uint16_t acs8_len = input_length * 8 / 6;
+
+ for (uint16_t i = 0; i < acs8_len; i++)
+ {
+ uint8_t pos = i * 6 / 8;
+ uint8_t val = input[pos];
+ uint8_t valNext = pos + 1 < input_length ? input[pos + 1] : 0;
+ uint8_t newVal = 0;
+ switch (i % 4)
+ {
+ case 0:
+ newVal = (val & 0xfc) >> 2;
+ break;
+ case 1:
+ newVal = (val & 3) << 4;
+ newVal += (valNext & 240) >> 4;
+ break;
+ case 2:
+ newVal = (val & 15) << 2;
+ newVal += (valNext & 192) >> 6;
+ break;
+ case 3:
+ newVal = val & 0x3f;
+ break;
+ }
+ if (newVal < 0x20)
+ newVal += 64;
+ if (newVal == 0x20)
+ newVal = 0;
+ output[i] = newVal;
+ }
+}
+
+// Time由一个无符号的32位二进制整数组成,最低有效位表示1/32毫秒(即0.03125毫秒)。
+void convert_time(uint32_t t, uint8_t *h, uint8_t *m, uint8_t *s)
+{
+ t = (t / 32);
+ t = t / 1000;
+ *h = t / 3600;
+ *m = (t - (*h) * 3600) / 60;
+ *s = t - (*h) * 3600 - (*m) * 60;
+}
+
+// Time由一个无符号的32位二进制整数组成,最低有效位表示1/32毫秒(即0.03125毫秒)。
+void convert_timestrap(uint32_t *t, uint8_t h, uint8_t m, uint8_t s, uint16_t ms)
+{
+ *t = (h * 3600 + m * 60 + s) * 1000 + ms;
+ *t = (*t) * 32;
+}
+
+// 年份转换,HART的年份是从1900年开始的,如果要转换到标准的年份,需要加上1900。另外,HART的年份是一个字节,所以最大只能表示到2155年。
+void covert_year_rtc(uint8_t *year)
+{
+ uint8_t y = *year;
+ *year = y - 100;
+}
+
+// 将RTC的年份转换为HART的年份
+void covert_rtc_year(uint8_t *year)
+{
+ uint8_t y = *year;
+ *year = y + 100;
+}
+
+// 将RTC的年份转换成标准的年份
+void covert_rtc_year_to_standard(uint16_t *year)
+{
+ uint16_t y = *year;
+ *year = y + 2000;
+}
+
+float32 covert_float(user_param_type_e data_type, void *data_p)
+{
+ float32 f = 0;
+ switch (data_type)
+ {
+ case USER_BYTE:
+ f = *(uint8_t *)data_p;
+ break;
+ case USER_WORD:
+ f = *(uint16_t *)data_p;
+ break;
+ case USER_UINT32:
+ f = *(uint32_t *)data_p;
+ break;
+ case USER_FLOAT:
+ f = *(float32 *)data_p;
+ break;
+ default:
+ break;
+ }
+ return f;
+}
diff --git a/User/hart/inc/hart.h b/User/hart/inc/hart.h
new file mode 100644
index 0000000..a324582
--- /dev/null
+++ b/User/hart/inc/hart.h
@@ -0,0 +1,71 @@
+/**
+ * @file hart.h
+ * @author: xxx
+ * @date: 2023-08-25 00:14:59
+ * @brief
+ * @copyright: Copyright (c) 2023 by xxx, All Rights Reserved.
+ */
+
+#ifndef _HART_H_
+#define _HART_H_
+#include "lib.h"
+#include "flow.h"
+#include "./hart_frame.h"
+#include "hart_storage.h"
+#define HART_INIT_FLAG (0x0520) ///< 初始化标志
+#ifdef MASTER
+#include "../master/inc/hart_master.h"
+#endif
+
+#ifdef SLAVE
+#include "../slave/inc/hart_slave.h"
+#endif
+
+typedef enum
+{
+ MODULE_MASTER = 1,
+ MODULE_SLAVE = 2,
+} modul_e; // 模块工作模式
+
+#pragma pack(1)
+
+typedef struct
+{
+ float32 timer_cycle;
+ // 计数器
+ uint16_t counter;
+} hart_timer_interupt_t;
+
+typedef struct
+{
+ uint8_t hart_protocol_version; // hart协议版本号,传入模块初始化参数
+ uint8_t dir; // 1:master 2:slave; 模块工作模式,传入模块初始化参数
+
+ uint8_t master_address_bit; // 主机参数,为1时表示基本主设备,为0时表示副主设备,传入模块初始化参数
+ hart_interface_t interface; // 模块接口
+ hart_timer_interupt_t hart_timer; // 定时器周期计数器 ,用于HART测试
+ // 模块初始化参数,存放全局变量
+ union
+ {
+#ifdef MASTER
+ hart_master_init_t _master;
+#endif
+
+#ifdef SLAVE
+ hart_slave_init_t _slave;
+#endif
+ } hart_module_u;
+
+} hart_init_t; // 模块初始化参数结构:hart_init
+
+#pragma pack()
+
+extern BOOL hart_init(const hart_init_t *const init); // 模块初始化接口
+extern hart_init_t *hart_get_handle(void); // 获取模块初始化参数
+extern BOOL hart_handle(uint8_t uart_index, uint8_t *rxBuf, uint16_t len); // 模块数据处理接口
+extern void perform_self_test_finish(void); // 自检完成
+extern void hart_cache_data_send(uint64_t uuid); // 缓存数据发送
+extern void ble_send_cmd(uint8_t *cmd); // 发送蓝牙指令
+extern BOOL get_device_lock(void); // 是否锁定装置
+
+#endif
diff --git a/User/hart/inc/hart_common_tables_specification.h b/User/hart/inc/hart_common_tables_specification.h
new file mode 100644
index 0000000..1c00756
--- /dev/null
+++ b/User/hart/inc/hart_common_tables_specification.h
@@ -0,0 +1,1745 @@
+/***
+ * @Author:
+ * @Date: 2023-05-06 09:32:57
+ * @LastEditors: xxx
+ * @LastEditTime: 2023-05-06 09:34:41
+ * @Description:常用表定义
+ * @email:
+ * @Copyright (c) 2023 by xxx, All Rights Reserved.
+ */
+#ifndef __HART_COMMON_TABLES_SPECIFICATION_H__
+#define __HART_COMMON_TABLES_SPECIFICATION_H__
+#include "lib.h"
+
+#define HART_PACKED3_LEN 3U
+#define HART_PACKED4_LEN 4U
+#define HART_PACKED6_LEN 6U
+#define HART_PACKED8_LEN 8U
+#define HART_PACKED10_LEN 10U
+#define HART_PACKED12_LEN 12U
+#define HART_PACKED16_LEN 16U
+#define HART_PACKED21_LEN 21U
+#define HART_PACKED24_LEN 24U
+#define HART_PACKED25_LEN 25U
+#define HART_PACKED26_LEN 26U
+#define HART_PACKED30_LEN 30U
+#define HART_PACKED32_LEN 32U
+#define HART_PACKED40_LEN 40U
+#define HART_PACKED128_LEN 128U
+#define HART_DATE_LEN 3U
+
+// hart命令码定义
+/**
+ * 命令编号分区
+ * 0-30,38,48 普通命令
+ * 31 扩展标志
+ * 32-121、512-767 通用命令
+ * 122-126 仅在现场设备建造期间供工厂使用
+ * 128-253 设备特定
+ * 127、254-511 保留
+ * 768-1023 无线HART
+ * 1024-33791 设备系列
+ * 33,792-64383 保留
+ * 64,384-64511 Discrete
+ * 64512-64765 无线设备
+ * 64768-65023 附加装置
+ * 65024-65535 保留
+ */
+typedef enum
+{
+ HART_COMMAND_0 = 0, // 读取唯一标识命令
+ HART_COMMAND_1 = 1, // 读取主变量
+ HART_COMMAND_2 = 2, // 读取回路电流和量程百分比
+ HART_COMMAND_3 = 3, // 读取动态变量和回路电流
+ HART_COMMAND_4 = 4, // 保留
+ HART_COMMAND_5 = 5, // 保留
+ HART_COMMAND_6 = 6, // 写入轮训地址
+ HART_COMMAND_7 = 7, // 读取循环配置
+ HART_COMMAND_8 = 8, // 读取动态变量分类
+ HART_COMMAND_9 = 9, // 读取具有状态的设备变量
+ HART_COMMAND_11 = 11, // 读取与标签关联的唯一标识符
+ HART_COMMAND_12 = 12, // 读取消息
+ HART_COMMAND_13 = 13, // 读取标签、描述符、日期
+ HART_COMMAND_14 = 14, // 读取主变量传感器信息
+ HART_COMMAND_15 = 15, // 读取设备信息
+ HART_COMMAND_16 = 16, // 读取最终汇编编号
+ HART_COMMAND_17 = 17, // 写入消息
+ HART_COMMAND_18 = 18, // 写标签、描述符、日期
+ HART_COMMAND_19 = 19, // 编写最终汇编号
+ HART_COMMAND_20 = 20, // 读取长标签
+ HART_COMMAND_21 = 21, // 读取与长标签关联的唯一标识符
+ HART_COMMAND_22 = 22, // 写长标签
+ HART_COMMAND_38 = 38, // 重置配置更改标志
+ HART_COMMAND_48 = 48, // 读取其他设备状态
+
+ // 扩展指令
+ HART_COMMAND_31 = 31, // 扩展标志
+
+ // 通用指令
+ HART_COMMAND_33 = 33, // 读取设备变量
+ HART_COMMAND_34 = 34, // 写入主变量阻尼值
+ HART_COMMAND_35 = 35, // 写入主变量范围值
+ HART_COMMAND_36 = 36, // 设置主变量上限值
+ HART_COMMAND_37 = 37, // 设置主变量下限值
+ HART_COMMAND_39 = 39, // EEPROM控制
+ HART_COMMAND_40 = 40, // 进入/退出固定电流模式
+ HART_COMMAND_41 = 41, // 执行自检
+ HART_COMMAND_42 = 42, // 执行设备重置
+ HART_COMMAND_43 = 43, // 设置主变量零
+ HART_COMMAND_44 = 44, // 编写主变量单元
+ HART_COMMAND_45 = 45, // 微调回路电流归零
+ HART_COMMAND_46 = 46, // 微调回路电流增益
+ HART_COMMAND_47 = 47, // 编写主变量传递函数
+ HART_COMMAND_49 = 49, // 写入主变量传感器序列号
+ HART_COMMAND_50 = 50, // 读取动态变量赋值
+ HART_COMMAND_51 = 51, // 编写动态变量赋值
+ HART_COMMAND_52 = 52, // 设置设备变量零
+ HART_COMMAND_53 = 53, // 写入设备变量单元
+ HART_COMMAND_54 = 54, // 读取设备变量信息
+ HART_COMMAND_55 = 55, // 写入设备可变阻尼值
+ HART_COMMAND_56 = 56, // 写入设备可变传感器序列号
+ HART_COMMAND_57 = 57, // 读取单位标签、描述符、日期
+ HART_COMMAND_58 = 58, // 编写单位标签、描述符、日期
+ HART_COMMAND_59 = 59, // 写入响应序码数
+ HART_COMMAND_60 = 60, // 读取模拟通道和范围百分比
+ HART_COMMAND_61 = 61, // 读取动态变量和主变量模拟通道
+ HART_COMMAND_62 = 62, // 读取模拟通道
+ HART_COMMAND_63 = 63, // 读取模拟通道信息
+ HART_COMMAND_64 = 64, // 写入模拟通道附加阻尼值
+ HART_COMMAND_65 = 65, // 写入模拟通道范围值
+ HART_COMMAND_66 = 66, // 进入/退出固定模拟通道模式
+ HART_COMMAND_67 = 67, // 调整模拟通道零
+ HART_COMMAND_68 = 68, // 微调模拟通道增益
+ HART_COMMAND_69 = 69, // 写入模拟通道传递函数
+ HART_COMMAND_70 = 70, // 读取模拟通道端点值
+ HART_COMMAND_71 = 71, // 锁定装置
+ HART_COMMAND_72 = 72, // 呼叫
+ HART_COMMAND_73 = 73, // 查找设备
+ HART_COMMAND_74 = 74, // 读取I/O系统功能
+ HART_COMMAND_75 = 75, // 轮询子设备
+ HART_COMMAND_76 = 76, // 读锁定设备状态
+ HART_COMMAND_77 = 77, // 向子设备发送命令
+ HART_COMMAND_78 = 78, // 读取聚合命令
+ HART_COMMAND_79 = 79, // 写入设备变量
+ HART_COMMAND_80 = 80, // 读取设备可变微调点
+ HART_COMMAND_81 = 81, // 读取设备变量调整指南
+ HART_COMMAND_82 = 82, // 写入设备可变微调点
+ HART_COMMAND_83 = 83, // 重置设备变量调整
+ HART_COMMAND_84 = 84, // 读取子设备标识摘要
+ HART_COMMAND_85 = 85, // 读取I/O通道统计信息
+ HART_COMMAND_86 = 86, // 读取子设备统计信息
+ HART_COMMAND_87 = 87, // 写入I/O系统主模式
+ HART_COMMAND_88 = 88, // 写入I/O系统重试计数
+ HART_COMMAND_89 = 89, // 设置实时时钟
+ HART_COMMAND_90 = 90, // 读取实时时钟
+ HART_COMMAND_91 = 91, // 读取趋势配置
+ HART_COMMAND_92 = 92, // 写入趋势配置
+ HART_COMMAND_93 = 93, // 读取趋势
+ HART_COMMAND_94 = 94, // 读取I/O系统客户端通信统计信息
+ HART_COMMAND_95 = 95, // 读取设备通信统计信息
+ HART_COMMAND_96 = 96, // 读取同步操作
+ HART_COMMAND_97 = 97, // 配置同步操作
+ HART_COMMAND_98 = 98, // 读取命令操作
+ HART_COMMAND_99 = 99, // 配置命令操作
+ HART_COMMAND_100 = 100, // 写入主变量报警码
+ HART_COMMAND_101 = 101, // 读取子设备到突发消息映射
+ HART_COMMAND_102 = 102, // 将子设备映射到突发信息
+ HART_COMMAND_103 = 103, // 写入突发周期
+ HART_COMMAND_104 = 104, // 写入突发触发器
+ HART_COMMAND_105 = 105, // 读取突发模式配置
+ HART_COMMAND_106 = 106, // 刷新延迟响应
+ HART_COMMAND_107 = 107, // 写入突发设备变量
+ HART_COMMAND_108 = 108, // 写入突发模式命令编号
+ HART_COMMAND_109 = 109, // 突发模式控制
+ HART_COMMAND_110 = 110, // 读取所有动态变量
+ HART_COMMAND_111 = 111, // 转移服务控制
+ HART_COMMAND_112 = 112, // 传输服务
+ HART_COMMAND_113 = 113, // 捕获设备变量
+ HART_COMMAND_114 = 114, // 读取捕获的设备变量
+ HART_COMMAND_115 = 115, // 读取事件通知摘要
+ HART_COMMAND_116 = 116, // 写入事件通知位掩码
+ HART_COMMAND_117 = 117, // 写入事件通知时序
+ HART_COMMAND_118 = 118, // 事件通知控制
+ HART_COMMAND_119 = 119, // 确认事件通知
+
+ // 128-253 设备特定
+ HART_COMMAND_129 = 129, // 用户自定义读取参数
+ HART_COMMAND_130 = 130, // 用户自定义设置参数
+ HART_COMMAND_131 = 131, // 写入整定参数
+ HART_COMMAND_132 = 132, // 读取整定参数类型
+ HART_COMMAND_133 = 133, // 获取打开的文件信息
+ HART_COMMAND_134 = 134, // 读取文件内容
+ HART_COMMAND_135 = 135, // 写入文件内容
+ HART_COMMAND_136 = 136, // 读取/解除/写入EEPROM
+ HART_COMMAND_138 = 138, // 读取其他状态
+ HART_COMMAND_140 = 140, // 读取触发器定义的内容
+ HART_COMMAND_141 = 141, // 写保护
+ HART_COMMAND_142 = 142, // 自整定
+ HART_COMMAND_143 = 143, // 设置阀门序列号
+ HART_COMMAND_144 = 144, // 读取阀门序列号
+ HART_COMMAND_145 = 145, // 读取仪器序列号
+ HART_COMMAND_146 = 146, // 读取标准跨度信息
+ HART_COMMAND_147 = 147, // 读取设备等级
+ HART_COMMAND_149 = 149, // 设置仪器时间
+ HART_COMMAND_150 = 150, // 读取仪器时间
+ HART_COMMAND_151 = 151, // 读取版本信息
+ HART_COMMAND_153 = 153, // 读取校准记录
+ HART_COMMAND_154 = 154, // 设置仪器序列号
+ HART_COMMAND_155 = 155, // 执行诊断
+ HART_COMMAND_156 = 156, // 读取诊断状态
+ HART_COMMAND_157 = 157, // 停止诊断
+ HART_COMMAND_158 = 158, // 在线诊断测试
+ HART_COMMAND_162 = 162, // 设置气源气压/A口/B口
+ HART_COMMAND_164 = 164, // 读取规格表数据
+ HART_COMMAND_165 = 165, // 写入规格表数据
+ HART_COMMAND_167 = 167, // 写入操作日期和用户
+ HART_COMMAND_168 = 168, // 读取部分行程警报
+ HART_COMMAND_170 = 170, // 读取制造信息序列号
+ HART_COMMAND_187 = 187, // 在测试 写保护、置位更多状态、CAL036、CAL037等脚本时,需要通过发送自定义命令实现
+ HART_COMMAND_200 = 200, // 读取NVM非易失性存储器数据
+
+ // 大号指令,command31扩展指令
+ HART_COMMAND_512 = 512, // 读取国家代码
+ HART_COMMAND_513 = 513, // 编写国家代码
+ HART_COMMAND_514 = 514, // 注册事件管理器
+ HART_COMMAND_515 = 515, // 读取事件管理器注册状态
+ HART_COMMAND_516 = 516, // 读取设备位置
+ HART_COMMAND_517 = 517, // 写入设备位置
+ HART_COMMAND_518 = 518, // 读取位置说明
+ HART_COMMAND_519 = 519, // 写入位置说明
+ HART_COMMAND_520 = 520, // 读取进程单元标签
+ HART_COMMAND_521 = 521, // 写入进程单元标记
+ HART_COMMAND_522 = 522, // 写入体积流分类
+ HART_COMMAND_523 = 523, // 读取精简状态映射数组
+ HART_COMMAND_524 = 524, // 写入精简状态映射
+ HART_COMMAND_525 = 525, // 重置精简状态图
+ HART_COMMAND_526 = 526, // 写入状态模拟模式
+ HART_COMMAND_527 = 527, // 模拟状态位
+ HART_COMMAND_528 = 528, // 读取子设备分配列表信息
+ HART_COMMAND_529 = 529, // 读取子设备分配
+ HART_COMMAND_530 = 530, // 写入子设备分配
+ HART_COMMAND_531 = 531, // 将实时列表传输到分配列表
+ HART_COMMAND_532 = 532, // 读取客户端订阅摘要
+ HART_COMMAND_533 = 533, // 写入客户端订阅标志
+ HART_COMMAND_534 = 534, // 读取设备变量命令代码
+ HART_COMMAND_535 = 535, // 写入模拟通道端点值
+ HART_COMMAND_536 = 536, // 写入应用时间操作
+ HART_COMMAND_537 = 537, // 读取应用时间操作
+ HART_COMMAND_538 = 538, // 读取HART-IP服务器端口
+ HART_COMMAND_539 = 539, // 写入HART-IP UDP端口
+ HART_COMMAND_540 = 540, // 写入HART-IP TCP端口
+ HART_COMMAND_541 = 541, // 写入客户端PAKE密码
+ HART_COMMAND_542 = 542, // 写入客户端预共享密钥
+ HART_COMMAND_543 = 543, // 读取系统日志服务器主机名和端口
+ HART_COMMAND_544 = 544, // 写入系统日志端口
+ HART_COMMAND_545 = 545, // 写入系统日志服务器主机名
+ HART_COMMAND_546 = 546, // 写入系统日志服务器预共享密钥
+ HART_COMMAND_547 = 547, // 写入系统日志服务器PAKE密码
+ HART_COMMAND_MAX,
+} hart_command_e;
+// 结束:hart命令码定义
+
+// 5.0响应代码定义
+typedef enum
+{
+ // No Command-Specific Errors 成功
+ RESPONSE_COMMUNICATION_CODE_0 = 0x00,
+ // Undefined 目前尚未定义。该代码用于协议的早期版本,不得用于任何现场设备。
+ RESPONSE_COMMUNICATION_CODE_1 = 0x01,
+ // Invalid Selection 此代码表示未执行该命令。现场设备未返回响应数据。
+ RESPONSE_COMMUNICATION_CODE_2 = 0x02,
+ // Passed Parameter Too Large 传递的参数太长
+ RESPONSE_COMMUNICATION_CODE_3 = 0x03,
+ // Passed Parameter Too Small 传递的参数太短
+ RESPONSE_COMMUNICATION_CODE_4 = 0x04,
+ // Too Few Data Bytes Received 接收的数据长度不足
+ RESPONSE_COMMUNICATION_CODE_5 = 0x05,
+ // Device-specific Command Error 设备特定命令错误,未定义的
+ RESPONSE_COMMUNICATION_CODE_6 = 0x06,
+ // In Write Protect Mode 处于写保护模式
+ RESPONSE_COMMUNICATION_CODE_7 = 0x07,
+ /**
+ * 1.Update Failure 更新失败
+ 2.Update Times Adjusted 更新时间已调整
+ 3.Update Period Increased 更新周期已增加
+ 4.Set to Nearest Possible Value 设置为最接近的可能值
+ 5.All but running delayed responses flushed 所有但运行延迟响应已刷新
+ */
+ RESPONSE_COMMUNICATION_CODE_8 = 0x08,
+ /**
+ * 1.Lower Range Value Too High 下限值高于传感器上限或超出其他物理设备限制
+ 2.Applied Process Too High 应用于现场设备的过程过高
+ 3.Invalid Burst Message 字段不支持突发消息编号
+ 4.Configuration Change Counter Mismatch 配置更改计数器值与当前设备值不匹配
+ 5.Insufficient bandwidth 没有足够的带宽来启用指定的突发消息
+ 6.Not In Proper Current Mode 现场设备未处于固定电流模式或电流未设置为正确值
+ */
+ RESPONSE_COMMUNICATION_CODE_9 = 0x09,
+ /**
+ * 1.Lower Range Value Too Low 下限值低于传感器下限或超出某些其他物理设备限制
+ 2.Applied Process Too Low 应用于现场设备的过程过低
+ 3.Invalid Local Panel Lock Code 本地面板密码无效
+ */
+ RESPONSE_COMMUNICATION_CODE_10 = 0x0A,
+ /**
+ * 1.Upper Range Value Too High 上限值高于传感器上限
+ 2.In Multi-drop Mode 设备处于多点状态,因此无法执行命令
+ 3.Invalid Device Variable Code 请求的命令或操作不支持此设备变量。换句话说,设备变量是有效的,但您不能将其与此命令一起使用
+ 4.Invalid Device Variable Classification 写入命令中包含的设备变量分类代码对该设备变量无效
+ 5.Trim Error,Excess Correction Attempted 测量值和实际值之间的差异太大,以至于现场设备无法在计算中校正该值
+ 6.Cannot Lock Panel 现场设备处于不允许锁定本地面板的模式(例如,操作员已经在使用本地面板)
+ */
+ RESPONSE_COMMUNICATION_CODE_11 = 0x0B,
+ /**
+ * 1.Upper Range Value Too Low 上限值低于传感器下限
+ 2.Invalid Units Code 在该命令、设备变量或动态变量的上下文中不支持请求的单位代码
+ 3.Invalid SOLT Number 用于捕获动态变量或设备变量的请求插槽代码对于指定的命令号无效
+ 4.Invalid Mode Selection 请求的(例如,回路电流)模式无效
+ */
+ RESPONSE_COMMUNICATION_CODE_12 = 0x0C,
+ /**
+ * 1.Invalid Transfer Function Code 此模拟通道或动态变量不支持请求的传递函数
+ 2.Upper and Lower Range Values Out Of Limits 上限和下限范围值超出传感器限制或超出了其他一些物理设备限制。
+ 3.Computation Error 当现场设备试图在主机应用程序的命令请求中应用新值时,遇到了一个算术错误。
+ 4.Command Number Not Supported 此现场设备不支持所请求的要捕获的命令号。
+ */
+ RESPONSE_COMMUNICATION_CODE_13 = 0x0D,
+ /**
+ * 1.Span Too Small 跨度,由"上范围值”和"下范围值”确定。小于最小跨度
+ 2.Dynamic Variables Returned for Device Variables 现场设备不公开任何设备变量。在指令9中,为代码0-3返回动态变量。
+ 3.Update Rate Uncertain 当设备未加入Wireless HART网络时,它还不知道是否有足够的容量来满足所需的通知参数。
+ 4.New Lower Range Value Pushed Upper Range Value Over Transducer Limit 现场设备使用了要求的较低范围值,并进行了修改相应的上限值。不幸的是,上范围值已饱和,跨度未保持。
+ */
+ RESPONSE_COMMUNICATION_CODE_14 = 0x0E,
+ // Invalid Analog Channel Code Number 该现场设备中不存在模拟通道代码编号
+ RESPONSE_COMMUNICATION_CODE_15 = 0x0F,
+ // Access Restricted 设备在当前操作模式下不允许使用该命令。例如,设备被锁定(参见命令71)
+ RESPONSE_COMMUNICATION_CODE_16 = 0x10,
+ // Invalid Device Variable Index 请求的设备变量在此现场设备中不存在
+ RESPONSE_COMMUNICATION_CODE_17 = 0x11,
+ // Invalid Units Code 请求的单位代码在此命令、设备变量或动态变量的上下文中不受支持
+ RESPONSE_COMMUNICATION_CODE_18 = 0x12,
+ // Device Variable Index Not Allowed 请求的命令或操作不支持此设备变量。换句话说,设备变量是有效的但不能将它与此命令一起使用
+ RESPONSE_COMMUNICATION_CODE_19 = 0x13,
+ // Invalid Extended Command Number 扩展命令编号少于512
+ RESPONSE_COMMUNICATION_CODE_20 = 0x14,
+ // Invalid I/O card number I/O系统在命令的请求数据字节中指定的 (逻辑)插槽中没有I/O卡
+ RESPONSE_COMMUNICATION_CODE_21 = 0x15,
+ // Invalid Channel number 无效频道号码I/O卡没有在命令的请求数据字节中指定的通道
+ RESPONSE_COMMUNICATION_CODE_22 = 0x16,
+ // Sub-device Response Too Long 子设备响应太I/O系统从子设备接收到的响应包含的字节数超过了I/O系统在单个响长的 应数据包中可以转发的字节数。
+ RESPONSE_COMMUNICATION_CODE_23 = 0x17,
+
+ // 24-27 保留供高级别委员会今后确定。这些代码不能被任何制造商使用。
+
+ // Invalid Range Units Code 无效的距离单位代码此模拟通道或动态变量的字段设备不支持命令中包含的单位代码。
+ RESPONSE_COMMUNICATION_CODE_28 = 0x1C,
+ // Undefined(自定义) 此响应代码的确切含义因命令而异。有关确切含义,请参见命令规范。制造商在设备特定命令使用时,可以定义此代码的另一个含义,只要只适用于给定的命令。使用此代码表示未执行该命令。没有从现场设备返回响应数据字节。目前没有具体定义
+ RESPONSE_COMMUNICATION_CODE_29 = 0x1D,
+ // Command Response Truncated 设备无法按要求重新设置为多个设备变量。这通常是由于命令缓冲区长度有限造成的。
+ RESPONSE_COMMUNICATION_CODE_30 = 0x1E,
+ // Undefined(自定义) 此响应代码的确切含义因命令而异。有关实际含义,请参阅命令规范。当制造商的设备特定命令使用此代码时,只要只有一种含义适用于给定的命令,制造商就可以确定此代码的另一种含义。使用这些代码表明该命令已执行,但需要偏离主机应用程序请求才能成功完成该命令。实际使用的值在现场设备的响应数据字节定义中重新使用
+ RESPONSE_COMMUNICATION_CODE_31 = 0x1F,
+ // Busy 此代码可能由以下两种情况之一引起: ()设备正于执行不能被此命令中断的功能:或2)所请求的命令需要延迟响应机制。不幸的是,所有延迟响应缓冲区都被使用了。在这两种情况下,主机应用程序都应该多次重试其请求(例如超过30次),直到现场设备可以执行命令。
+ RESPONSE_COMMUNICATION_CODE_32 = 0x20,
+ // Delayed Response Initiated 无法在数据链路层指定的时间内处理该命令。启动了延迟响应。主机应用程序应该在延迟一段时间后重试完全相同的请求(例如,延迟几秒钟后)。当通过多路复用器进行通信时,这种延迟可能只有半秒
+ RESPONSE_COMMUNICATION_CODE_33 = 0x21,
+ // Delayed Response Running 延迟响应的执行尚未完成。进程仍在现场设备中运行。
+ RESPONSE_COMMUNICATION_CODE_34 = 0x22,
+ // Delayed Response Dead 此响应仅对智能桥接设备有效。此代码表示现场设备没有响应请求。
+ RESPONSE_COMMUNICATION_CODE_35 = 0x23,
+ // Delayed Response Conflict 请求的命令将导致与现场设备中当前执行的延迟响应发生冲突。
+ RESPONSE_COMMUNICATION_CODE_36 = 0x24,
+
+ // 37-59 保留将来定义。任何制造商都不得使用这些代码
+ // Tag Mismatch Error 请求中的标记与设备和传输层不匹配已设置“已确认”位
+ RESPONSE_COMMUNICATION_CODE_38 = 0x26,
+
+ // Payload Too Long 命令有效负载不适合 Wireless HART PDU
+ RESPONSE_COMMUNICATION_CODE_60 = 0x3C,
+ // No Buffers Available 该设备没有可用于接受Wireless HART DLPDU 的缓冲区
+ RESPONSE_COMMUNICATION_CODE_61 = 0x3D,
+ // No Alarm/Event Buffers Available 设备没有可用于接受Wireless HART DLPDU的报警/事件缓冲区
+ RESPONSE_COMMUNICATION_CODE_62 = 0x3E,
+ // Priority Too Low DLPDU的优先级太低,设备无法接受Wireless HART DLPDU
+ RESPONSE_COMMUNICATION_CODE_63 = 0x3F,
+ // Command Not Implemented 请求的命令没有实现。此响应对通用命令无效。对于任何其他命令,该代码可能由现场设备返回,即使命令规范本身没有定义响应代码#64。
+ RESPONSE_COMMUNICATION_CODE_64 = 0x40,
+ /**
+ * 1.Declined.Operator overridden. 已拒绝。操作员已撤销。
+ 2.Force Join Declined 强制加入已拒绝
+ 3.Invalid Network ID 无效的网络ID
+ 4.Invalid timer type 计时器类型无效
+ 5.Invalid Time-to-Live 无效的生存时间
+ 6.Invalid Join Priority 无效的加入优先级
+ 7.Unknown Nickname 未知昵称
+ 8.Invalid Nickname 昵称无效
+ 9.Service Request denied 服务请求被拒绝
+ 10.Link not found 未找到链接
+ 11.No more entries available 没有更多可用的条目
+ 12.Entry not found 未找到条目
+ 13.Illegal frequency channel bits 非法频道位
+ 14.Unknown Unique ID Key change failed 未知的唯一IDKey更改失败
+ 15.Session with given peer device does not exist 与给定对等设备的会话不存在
+ 16.Invalid suspend time 无效地挂起时间
+ */
+ RESPONSE_COMMUNICATION_CODE_65 = 0x41,
+ /**
+ * 1.Invalid number of slots 插槽数量无效
+ 2.Session type invalid 会话类型无效
+ 3.Invalid execution time 执行时间无效
+ 4.Unknown Notification Flag 未知通知标志
+ 5.Device List Conflict 设备列表冲突
+ 6.Invalid neighbor property 邻居属性无效
+ 7.Invalid Service Id 服务Id无效
+ 8.Invalid Graph Id 图形Id无效
+ 9.Invalid resume time 恢复时间无效
+ 10.Link already exists 链接已存在
+ 11.Invalid Reason Code 原因代码无效
+ 12.Unknown service flag 未知服务标志
+ 13.Invalid timer interval 计时器间隔无效
+ */
+ RESPONSE_COMMUNICATION_CODE_66 = 0x42,
+ /**
+ * 1.Invalid Graph Id 无效的图形Id
+ 2.Unknown Superframe ID 未知超帧ID
+ 3.Invalid Superframe mode 无效的超帧模式
+ 4.Reason Code rejected,Service not deleted 原因代码被拒绝,服务未删除
+ 5.Unknown application domain 未知的应用程序域
+ */
+ RESPONSE_COMMUNICATION_CODE_67 = 0x43,
+ /**
+ * 1.Unknown nickname 未知昵称
+ 2.Invalid execution time 无效的执行时间
+ 3.Invalid slot number 插槽编号无效
+ */
+ RESPONSE_COMMUNICATION_CODE_68 = 0x44,
+ // Unknown link options 未知链接选项
+ RESPONSE_COMMUNICATION_CODE_69 = 0x45,
+ // Invalid channel offset 无效通道偏移
+ RESPONSE_COMMUNICATION_CODE_70 = 0x46,
+ // Invalid link type 无效的链接类型
+ RESPONSE_COMMUNICATION_CODE_71 = 0x47,
+
+ // 72-95 此响应代码的确切含义因命令而异。有关实际含义,请参阅命令规范。当制造商的设备特定命令使用此代码时,制造商可以为其定义另一种含义,只要只有一种含义适用于给定的命令。使用这些代码表示该命令未执行。没有从现场设备返回响应数据字节目前没有特定的定义
+
+ // 96-111 保留将来定义。任何制造商都不得使用这些代码
+
+ // 112-127 此响应代码的确切含义因命令而异。有关实际含义,请参阅命令规范。当制造商的设备特定命令使用此代码时,只要只有一种含义适用于给定的命令,制造商就可以定义此代码的另一种含义。使用这些代码表示命令已执行,但需要偏离主机应用程序的要求才能成功完成命令。实际使用的值在现场设备中返回响应数据字节
+ RESPONSE_COMMUNICATION_CODE_126 = 0x7E, // 指令中的设备变量只被部分支持
+ RESPONSE_COMMUNICATION_CODE_127 = 0x7F, // 不回复消息,缓存上一条消息
+} response_communication_code_e; // 通信正常的信息
+
+typedef enum
+{
+ RESPONSE_ERROR_COMMUNICATION_CODE_0 = BIT0,
+ // 缓冲区溢出-消息对于设备的接收缓冲区来说太长
+ RESPONSE_ERROR_COMMUNICATION_CODE_1 = BIT1,
+ // 通讯故障-与现场设备或子设备的通信不成功。设备可能已断开连接。该位应该由主数据链路和I/O系统设置,以指示与现场设备的通信失败
+ RESPONSE_ERROR_COMMUNICATION_CODE_2 = BIT2,
+ // 奇偶校验误差-设备计算的奇偶校验与消息末尾的校验字节不匹配
+ RESPONSE_ERROR_COMMUNICATION_CODE_3 = BIT3,
+ // 帧错误-UART没有检测到设备接收到的一个或多个字节的停止位(当应该出现停止位时,没有检测到标记或1)
+ RESPONSE_ERROR_COMMUNICATION_CODE_4 = BIT4,
+ // 溢出错误-UART的接收缓冲区中至少有一个字节的数据在读取之前被覆盖(从服务器处理传入字节的速度不够快)
+ RESPONSE_ERROR_COMMUNICATION_CODE_5 = BIT5,
+ // 垂直奇偶校验错误-设备接收到的一个或多个字节的奇偶性不是奇数。
+ RESPONSE_ERROR_COMMUNICATION_CODE_6 = BIT6,
+ // 高位置一
+ RESPONSE_ERROR_COMMUNICATION_CODE_7 = BIT7,
+} response_error_communication_code_e; // 通信错误的信息
+
+typedef enum
+{
+ // 主变量超越极限PV已经超出了它的运行极限
+ RESPONSE_DEVICE_OPERATION_STATUS_CODE_1 = BIT0,
+ // 非主变量超越极限-A未映射到PV的设备变量超出其操作限制
+ RESPONSE_DEVICE_OPERATION_STATUS_CODE_2 = BIT1,
+ // 环路电流饱和-回路电流已达到其上(或下) 端点限制,不能再增加(或减少)
+ RESPONSE_DEVICE_OPERATION_STATUS_CODE_3 = BIT2,
+ // 环路电流固定1-环电流保持在一个固定的值,并没有响应进程的变化
+ RESPONSE_DEVICE_OPERATION_STATUS_CODE_4 = BIT3,
+ // 更多状态可用-更多的状态信息可通过Command 48,读取额外的状态信息
+ RESPONSE_DEVICE_OPERATION_STATUS_CODE_5 = BIT4,
+ // 冷启动-发生电源故障或设备重置
+ RESPONSE_DEVICE_OPERATION_STATUS_CODE_6 = BIT5,
+ // 配置已更改-执行的操作更改了设备的配置
+ RESPONSE_DEVICE_OPERATION_STATUS_CODE_7 = BIT6,
+ // 设备故障-设备检测到严重错误或故障,危及设备运行
+ RESPONSE_DEVICE_OPERATION_STATUS_CODE_8 = BIT7,
+} response_device_operation_status_code_e; // 设备的操作状态有关的信息
+
+// 5.1 扩展设备类型
+typedef enum
+{
+ // EXTENDED_DEVICE_TYPE_GSDT = 0x1309,
+ EXTENDED_DEVICE_TYPE_GSDT_GPS2000 = 0xE63F, // 0xE63F = 58943
+ EXTENDED_DEVICE_TYPE_GSDT_GPS3000 = 0xE640, // 0xE640 = 58944
+} extended_device_type_e;
+
+// 5.2 单位代码
+typedef enum
+{
+ // 温度单位代码
+ UNITS_CODE_TEMPERATURE_CELSIUS = 32, // 摄氏度
+ UNITS_CODE_TEMPERATURE_FAHRENHEIT = 33, // 华氏度
+ UNITS_CODE_TEMPERATURE_RANKINE = 34, // 兰氏度
+ UNITS_CODE_TEMPERATURE_KELVIN = 35, // 开氏度
+
+ // 压力单位代码
+ UNITS_CODE_PRESSURE_INH20 = 1, // 英寸水柱
+ UNITS_CODE_PRESSURE_INHG = 2, // 英寸汞柱
+ UNITS_CODE_PRESSURE_FTH20 = 3, // 英尺水柱
+ UNITS_CODE_PRESSURE_MMH20 = 4, // 毫米水柱
+ UNITS_CODE_PRESSURE_MMHG = 5, // 毫米汞柱
+ UNITS_CODE_PRESSURE_PSI = 6, // 磅力/平方英寸
+ UNITS_CODE_PRESSURE_BAR = 7, // 巴
+ UNITS_CODE_PRESSURE_MBAR = 8, // 毫巴
+ UNITS_CODE_PRESSURE_GCM2 = 9, // 克/平方厘米
+ UNITS_CODE_PRESSURE_KGCM2 = 10, // 千克/平方厘米
+ UNITS_CODE_PRESSURE_PA = 11, // 帕斯卡
+ UNITS_CODE_PRESSURE_KPA = 12, // 千帕
+ UNITS_CODE_PRESSURE_TORR = 13, // 托
+ UNITS_CODE_PRESSURE_ATM = 14, // 标准大气压
+ UNITS_CODE_PRESSURE_INH20_60F = 145, // 英寸水柱(60°F)
+ UNITS_CODE_PRESSURE_CMH20_4C = 170, // 厘米水柱(4°C)
+ UNITS_CODE_PRESSURE_MH20_4C = 171, // 米水柱(4°C)
+ UNITS_CODE_PRESSURE_CMHG = 172, // 厘米汞柱
+ UNITS_CODE_PRESSURE_LBFT2 = 173, // 磅/平方英尺
+ UNITS_CODE_PRESSURE_HPA = 174, // 百帕
+ UNITS_CODE_PRESSURE_PSIA = 175, // 磅力/平方英寸绝对
+ UNITS_CODE_PRESSURE_KGM2 = 176, // 千克/平方米
+ UNITS_CODE_PRESSURE_FTH20_4C = 177, // 英尺水柱(4°C)
+ UNITS_CODE_PRESSURE_FTH20_60F = 178, // 英尺水柱(60°F)
+ UNITS_CODE_PRESSURE_MHG = 179, // 米汞柱
+ UNITS_CODE_PRESSURE_MPSI = 180, // 兆磅力/平方英寸
+ UNITS_CODE_PRESSURE_OZIN2 = 181, // 盎司/平方英寸
+ UNITS_CODE_PRESSURE_MPA = 237, // 兆帕
+ UNITS_CODE_PRESSURE_INH20_4C = 238, // 英寸水柱(4°C)
+ UNITS_CODE_PRESSURE_MMH20_4C = 239, // 毫米水柱(4°C)
+
+ // 体积流量单位代码
+ UNITS_CODE_VOLUMETRIC_FLOW_RATE_FT3MIN = 15, // 英尺立方/分钟
+ UNITS_CODE_VOLUMETRIC_FLOW_RATE_GALMIN = 16, // 加仑/分钟
+ UNITS_CODE_VOLUMETRIC_FLOW_RATE_IMIN = 17, // 英制加仑/分钟
+ UNITS_CODE_VOLUMETRIC_FLOW_RATE_GALUKMIN = 18, // 英国加仑/分钟
+ UNITS_CODE_VOLUMETRIC_FLOW_RATE_M3H = 19, // 立方米/小时
+ UNITS_CODE_VOLUMETRIC_FLOW_RATE_GALS = 22, // 加仑/秒
+ UNITS_CODE_VOLUMETRIC_FLOW_RATE_MGALD = 23, // 百万加仑/天
+ UNITS_CODE_VOLUMETRIC_FLOW_RATE_IS = 24, // 英制加仑/秒
+ UNITS_CODE_VOLUMETRIC_FLOW_RATE_MID = 25, // 百万英里/天
+ UNITS_CODE_VOLUMETRIC_FLOW_RATE_FT3S = 26, // 英尺立方/秒
+ UNITS_CODE_VOLUMETRIC_FLOW_RATE_FT3D = 27, // 英尺立方/天
+ UNITS_CODE_VOLUMETRIC_FLOW_RATE_M3S = 28, // 立方米/秒
+ UNITS_CODE_VOLUMETRIC_FLOW_RATE_M3D = 29, // 立方米/天
+ UNITS_CODE_VOLUMETRIC_FLOW_RATE_GALUKH = 30, // 英国加仑/小时
+ UNITS_CODE_VOLUMETRIC_FLOW_RATE_GALUKD = 31, // 英国加仑/天
+ UNITS_CODE_VOLUMETRIC_FLOW_RATE_NM3H = 121, // 标准立方米/小时
+ UNITS_CODE_VOLUMETRIC_FLOW_RATE_NIH = 122, // 标准升/小时
+ UNITS_CODE_VOLUMETRIC_FLOW_RATE_SCFMIN = 123, // 标准立方英尺/分钟
+ UNITS_CODE_VOLUMETRIC_FLOW_RATE_FT3H = 130, // 英尺立方/小时
+ UNITS_CODE_VOLUMETRIC_FLOW_RATE_M3MIN = 131, // 立方米/分钟
+ UNITS_CODE_VOLUMETRIC_FLOW_RATE_BBLS = 132, // 桶/秒
+ UNITS_CODE_VOLUMETRIC_FLOW_RATE_BBLMIN = 133, // 桶/分钟
+ UNITS_CODE_VOLUMETRIC_FLOW_RATE_BBLH = 134, // 桶/小时
+ UNITS_CODE_VOLUMETRIC_FLOW_RATE_BBLD = 135, // 桶/天
+ UNITS_CODE_VOLUMETRIC_FLOW_RATE_GALH = 136, // 加仑/小时
+ UNITS_CODE_VOLUMETRIC_FLOW_RATE_GALUKS = 137, // 英国加仑/秒
+ UNITS_CODE_VOLUMETRIC_FLOW_RATE_IH = 138, // 英制加仑/小时
+ UNITS_CODE_VOLUMETRIC_FLOW_RATE_BBLBEERS = 170, // 啤酒桶/秒
+ UNITS_CODE_VOLUMETRIC_FLOW_RATE_BBLBEERMIN = 171, // 啤酒桶/分钟
+ UNITS_CODE_VOLUMETRIC_FLOW_RATE_BBLBEERH = 172, // 啤酒桶/小时
+ UNITS_CODE_VOLUMETRIC_FLOW_RATE_BBLBEERD = 173, // 啤酒桶/天
+ UNITS_CODE_VOLUMETRIC_FLOW_RATE_NID = 174, // 标准升/天
+ UNITS_CODE_VOLUMETRIC_FLOW_RATE_NIMIN = 175, // 标准升/分钟
+ UNITS_CODE_VOLUMETRIC_FLOW_RATE_NIS = 176, // 标准升/秒
+ UNITS_CODE_VOLUMETRIC_FLOW_RATE_SID = 177, // 立方米/天
+ UNITS_CODE_VOLUMETRIC_FLOW_RATE_SIH = 178, // 立方米/小时
+ UNITS_CODE_VOLUMETRIC_FLOW_RATE_SIMIN = 179, // 立方米/分钟
+ UNITS_CODE_VOLUMETRIC_FLOW_RATE_SIS = 180, // 立方米/秒
+ UNITS_CODE_VOLUMETRIC_FLOW_RATE_NM3D = 181, // 标准立方米/天
+ UNITS_CODE_VOLUMETRIC_FLOW_RATE_NM3MIN = 182, // 标准立方米/分钟
+ UNITS_CODE_VOLUMETRIC_FLOW_RATE_NM3S = 183, // 标准立方米/秒
+ UNITS_CODE_VOLUMETRIC_FLOW_RATE_SCFD = 184, // 标准立方英尺/天
+ UNITS_CODE_VOLUMETRIC_FLOW_RATE_SCFH = 185, // 标准立方英尺/小时
+ UNITS_CODE_VOLUMETRIC_FLOW_RATE_SCFS = 186, // 标准立方英尺/秒
+ UNITS_CODE_VOLUMETRIC_FLOW_RATE_SM3D = 187, // 立方米/天
+ UNITS_CODE_VOLUMETRIC_FLOW_RATE_SM3H = 188, // 立方米/小时
+ UNITS_CODE_VOLUMETRIC_FLOW_RATE_SM3MIN = 189, // 立方米/分钟
+ UNITS_CODE_VOLUMETRIC_FLOW_RATE_SM3S = 190, // 立方米/秒
+ UNITS_CODE_VOLUMETRIC_FLOW_RATE_GALD = 235, // 加仑/天
+
+ // 速度单位代码
+ UNITS_CODE_SPEED_FTS = 20, // 英尺/秒
+ UNITS_CODE_SPEED_MS = 21, // 米/秒
+ UNITS_CODE_SPEED_INS = 114, // 英寸/秒
+ UNITS_CODE_SPEED_INMIN = 115, // 英寸/分钟
+ UNITS_CODE_SPEED_FTMIN = 116, // 英尺/分钟
+ UNITS_CODE_SPEED_MH = 120, // 米/小时
+ UNITS_CODE_SPEED_MMS = 170, // 毫米/秒
+
+ // 卷单位代码
+ UNITS_CODE_VOLUME_GAL = 40, // 加仑
+ UNITS_CODE_VOLUME_L = 41, // 升
+ UNITS_CODE_VOLUME_GALUK = 42, // 英国加仑
+ UNITS_CODE_VOLUME_M3 = 43, // 立方米
+ UNITS_CODE_VOLUME_BBL = 46, // 桶
+ UNITS_CODE_VOLUME_BU = 110, // 蒲式耳
+ UNITS_CODE_VOLUME_YD3 = 111, // 立方码
+ UNITS_CODE_VOLUME_FT3 = 112, // 英尺立方
+ UNITS_CODE_VOLUME_IN3 = 113, // 立方英寸
+ UNITS_CODE_VOLUME_BBLUS = 124, // 美国桶
+ UNITS_CODE_VOLUME_NM3 = 166, // 标准立方米
+ UNITS_CODE_VOLUME_NL = 167, // 标准升
+ UNITS_CODE_VOLUME_SCF = 168, // 标准立方英尺
+ UNITS_CODE_VOLUME_BBLBEER = 170, // 啤酒桶
+ UNITS_CODE_VOLUME_SL = 171, // 立方米/秒
+ UNITS_CODE_VOLUME_SM3 = 172, // 立方米
+ UNITS_CODE_VOLUME_MGAL = 173, // 百万加仑
+ UNITS_CODE_VOLUME_HL = 236, // 公石
+
+ // 长度单位代码
+ UNITS_CODE_LENGTH_FT = 44, // 英尺
+ UNITS_CODE_LENGTH_M = 45, // 米
+ UNITS_CODE_LENGTH_IN = 47, // 英寸
+ UNITS_CODE_LENGTH_CM = 48, // 厘米
+ UNITS_CODE_LENGTH_MM = 49, // 毫米
+ UNITS_CODE_LENGTH_FT16 = 151, // 英尺-16
+ UNITS_CODE_LENGTH_UM = 170, // 微米
+ UNITS_CODE_LENGTH_UIN = 171, // 微英寸
+ UNITS_CODE_LENGTH_NM = 172, // 纳米
+
+ // 时间单位代码
+ UNITS_CODE_TIME_MIN = 50, // 分钟
+ UNITS_CODE_TIME_S = 51, // 秒
+ UNITS_CODE_TIME_H = 52, // 小时
+ UNITS_CODE_TIME_D = 53, // 天
+ UNITS_CODE_TIME_MS = 170, // 毫秒
+ UNITS_CODE_TIME_US = 171, // 微秒
+ UNITS_CODE_TIME_NS = 172, // 纳秒
+
+ // 质量单位代码
+ UNITS_CODE_QUALITY_G = 60, // 克
+ UNITS_CODE_QUALITY_KG = 61, // 千克
+ UNITS_CODE_QUALITY_T = 62, // 吨
+ UNITS_CODE_QUALITY_LB = 63, // 磅
+ UNITS_CODE_QUALITY_TON = 64, // 短吨
+ UNITS_CODE_QUALITY_TONUK = 65, // 长吨
+ UNITS_CODE_QUALITY_OZ = 125, // 盎司
+
+ // 质量流量单位代码
+ UNITS_CODE_MASS_FLOW_GS = 70, // 克/秒
+ UNITS_CODE_MASS_FLOW_GMIN = 71, // 克/分钟
+ UNITS_CODE_MASS_FLOW_GH = 72, // 克/小时
+ UNITS_CODE_MASS_FLOW_KGS = 73, // 千克/秒
+ UNITS_CODE_MASS_FLOW_KGMIN = 74, // 千克/分钟
+ UNITS_CODE_MASS_FLOW_KGH = 75, // 千克/小时
+ UNITS_CODE_MASS_FLOW_KGD = 76, // 千克/天
+ UNITS_CODE_MASS_FLOW_TMIN = 77, // 吨/分钟
+ UNITS_CODE_MASS_FLOW_TH = 78, // 吨/小时
+ UNITS_CODE_MASS_FLOW_TD = 79, // 吨/天
+ UNITS_CODE_MASS_FLOW_LBS = 80, // 磅/秒
+ UNITS_CODE_MASS_FLOW_LBMIN = 81, // 磅/分钟
+ UNITS_CODE_MASS_FLOW_LBH = 82, // 磅/小时
+ UNITS_CODE_MASS_FLOW_LBD = 83, // 磅/天
+ UNITS_CODE_MASS_FLOW_TONMIN = 84, // 短吨/分钟
+ UNITS_CODE_MASS_FLOW_TONH = 85, // 短吨/小时
+ UNITS_CODE_MASS_FLOW_TOND = 86, // 短吨/天
+ UNITS_CODE_MASS_FLOW_TONUKH = 87, // 长吨/小时
+ UNITS_CODE_MASS_FLOW_TONUKD = 88, // 长吨/天
+
+ // 单位体积质量单位代码
+ UNITS_CODE_MASS_PER_UNIT_VOLUME_SG = 90, // 比重
+ UNITS_CODE_MASS_PER_UNIT_VOLUME_GM3 = 91, // 克/立方米
+ UNITS_CODE_MASS_PER_UNIT_VOLUME_KGM3 = 92, // 千克/立方米
+ UNITS_CODE_MASS_PER_UNIT_VOLUME_LBGAL = 93, // 磅/加仑
+ UNITS_CODE_MASS_PER_UNIT_VOLUME_LBFT3 = 94, // 磅/立方英尺
+ UNITS_CODE_MASS_PER_UNIT_VOLUME_GML = 95, // 克/毫升
+ UNITS_CODE_MASS_PER_UNIT_VOLUME_KGL = 96, // 千克/升
+ UNITS_CODE_MASS_PER_UNIT_VOLUME_GL = 97, // 克/升
+ UNITS_CODE_MASS_PER_UNIT_VOLUME_LBIN3 = 98, // 磅/立方英寸
+ UNITS_CODE_MASS_PER_UNIT_VOLUME_TONYD3 = 99, // 吨/立方码
+ UNITS_CODE_MASS_PER_UNIT_VOLUME_OTW = 100, // 盐度
+ UNITS_CODE_MASS_PER_UNIT_VOLUME_BO = 102, // 油比重
+ UNITS_CODE_MASS_PER_UNIT_VOLUME_BLIGHT = 103, // B°(轻质油)
+ UNITS_CODE_MASS_PER_UNIT_VOLUME_DEGAPI = 104, // API度
+ UNITS_CODE_MASS_PER_UNIT_VOLUME_UGL = 146, // 微克/升
+ UNITS_CODE_MASS_PER_UNIT_VOLUME_UGM3 = 147, // 微克/立方米
+ UNITS_CODE_MASS_PER_UNIT_VOLUME_PERCENT = 148, // 百分比
+ UNITS_CODE_MASS_PER_UNIT_VOLUME_MGL = 170, // 毫克/升
+ UNITS_CODE_MASS_PER_UNIT_VOLUME_MGM3 = 171, // 毫克/立方米
+ UNITS_CODE_MASS_PER_UNIT_VOLUME_TM3 = 172, // 吨/立方米
+
+ // 粘度单位代码
+ UNITS_CODE_VISCOSITY_CST = 54, // 厘斯
+ UNITS_CODE_VISCOSITY_CP = 55, // 毫帕秒
+ UNITS_CODE_VISCOSITY_PAS = 170, // 帕斯卡秒
+
+ // 角速度单位代码
+ UNITS_CODE_ANGULAR_VELOCITY_OSPS = 117, // 角度/秒
+ UNITS_CODE_ANGULAR_VELOCITY_RPS = 118, // 每秒转数
+ UNITS_CODE_ANGULAR_VELOCITY_RPM = 119, // 每分钟转数
+
+ // 能源(功)单位代码
+ UNITS_CODE_ENERGY_J = 69, // 焦耳
+ UNITS_CODE_ENERGY_DTH = 89, // 热力单位
+ UNITS_CODE_ENERGY_FTLBF = 126, // 英尺-磅
+ UNITS_CODE_ENERGY_KWH = 128, // 千瓦时
+ UNITS_CODE_ENERGY_MCALTH = 162, // 兆卡(热)
+ UNITS_CODE_ENERGY_MJ = 164, // 兆焦
+ UNITS_CODE_ENERGY_BTU = 165, // 英热单位
+ UNITS_CODE_ENERGY_KVAH = 170, // 千伏安时
+ UNITS_CODE_ENERGY_KVARH = 171, // 千乏时
+ UNITS_CODE_ENERGY_MBTU = 172, // 百万英热单位
+
+ // 力单位代码
+ UNITS_CODE_POWER_N = 68, // 牛
+ UNITS_CODE_POWER_KN = 170, // 千牛
+
+ // 动力单位代码
+ UNITS_CODE_DYNAMIC_KW = 127, // 千瓦
+ UNITS_CODE_DYNAMIC_HP = 129, // 马力
+ UNITS_CODE_DYNAMIC_MCALTHH = 140, // 兆卡(热)/小时
+ UNITS_CODE_DYNAMIC_MJH = 141, // 兆焦/小时
+ UNITS_CODE_DYNAMIC_BTUH = 142, // 英热单位/小时
+ UNITS_CODE_DYNAMIC_MJS = 170, // 兆焦/秒
+ UNITS_CODE_DYNAMIC_MW = 170, // 兆瓦
+ UNITS_CODE_DYNAMIC_MJD = 171, // 兆焦/天
+ UNITS_CODE_DYNAMIC_MMBTUS = 172, // 百万英热单位/秒
+ UNITS_CODE_DYNAMIC_MMBTUH = 173, // 百万英热单位/小时
+ UNITS_CODE_DYNAMIC_MMBTUD = 174, // 百万英热单位/天
+ UNITS_CODE_DYNAMIC_VA = 175, // 伏安
+ UNITS_CODE_DYNAMIC_KVA = 176, // 千伏安
+ UNITS_CODE_DYNAMIC_KVAR = 177, // 千乏
+ UNITS_CODE_DYNAMIC_BTUD = 178, // 英热单位/天
+ UNITS_CODE_DYNAMIC_BTUMIN = 179, // 英热单位/分钟
+ UNITS_CODE_DYNAMIC_MJMIN = 180, // 兆焦/分钟
+ UNITS_CODE_DYNAMIC_BTUS = 181, // 英热单位/秒
+ UNITS_CODE_DYNAMIC_MBTUS = 182, // 百万英热单位/秒
+ UNITS_CODE_DYNAMIC_MBTUM = 183, // 百万英热单位/分钟
+ UNITS_CODE_DYNAMIC_MBTUH = 184, // 百万英热单位/小时
+ UNITS_CODE_DYNAMIC_MBTUD = 185, // 百万英热单位/天
+
+ // 频率单位代码
+ UNITS_CODE_FREQUENCY_HZ = 38, // 赫兹
+
+ // 分析单位代码
+ UNITS_CODE_ANALYSIS_PERCENT = 57, // 百分比
+ UNITS_CODE_ANALYSIS_PH = 59, // 酸碱度
+ UNITS_CODE_ANALYSIS_STEAM_QUALITY = 150, // 蒸汽质量
+ UNITS_CODE_ANALYSIS_PLATO = 160, // 普拉托度
+ UNITS_CODE_ANALYSIS_PERCENT_LOWER_EXPLOSION_LEVEL = 161, // 下限爆炸浓度百分比
+ UNITS_CODE_ANALYSIS_MM_PER_YEAR = 170, // 毫米/年
+ UNITS_CODE_ANALYSIS_MILS_PER_YEAR = 171, // 千分英寸/年
+ UNITS_CODE_ANALYSIS_PPM_M = 172, // 百万分之一/米
+ UNITS_CODE_ANALYSIS_PERCENT_LOWER_EXPLOSION_LEVEL_M = 173, // 下限爆炸浓度百分比/米
+
+ // 电容单位代码
+ UNITS_CODE_CAPACITANCE_PF = 153, // 153皮法
+
+ // 电势的电磁单位
+ UNITS_CODE_ELECTROMOTANCE_MILLIVOLTS = 36, // 毫伏
+ UNITS_CODE_ELECTROMOTANCE_VOLTS = 58, // 伏
+
+ // 电流单位代码
+ UNITS_CODE_CURRENT_MA = 39, // 毫安
+ UNITS_CODE_CURRENT_NA = 170, // 纳安
+ UNITS_CODE_CURRENT_UA = 171, // 微安
+ UNITS_CODE_CURRENT_A = 172, // 安
+
+ // 电阻单位代码
+ UNITS_CODE_RESISTANCE_OHMS = 37, // 欧姆
+ UNITS_CODE_RESISTANCE_KILOOHMS = 163, // 千欧
+ UNITS_CODE_RESISTANCE_MEGAOHMS = 170, // 兆欧
+ UNITS_CODE_RESISTANCE_QCM = 171, // 欧姆厘米
+ UNITS_CODE_RESISTANCE_KQ_CM = 172, // 千欧厘米
+ UNITS_CODE_RESISTANCE_MQ_CM = 173, // 兆欧厘米
+ UNITS_CODE_RESISTANCE_MILLIOHMS = 174, // 毫欧
+
+ // 角度单位代码
+ UNITS_CODE_ANGLE_DEGREES = 143, // 度
+ UNITS_CODE_ANGLE_RADIANS = 144, // 弧度
+
+ // 电导单位代码
+ UNITS_CODE_CONDUCTION_MICROSIEMENS = 56, // 微西门子
+ UNITS_CODE_CONDUCTION_MILLISIEMENS_PER_CM = 66, // 毫西门子每厘米
+ UNITS_CODE_CONDUCTION_MICROSIEMENS_PER_CM = 67, // 微西门子每厘米
+
+ // 卷单位代码
+ UNITS_CODE_VOLUME_PERCENT = 149, // 体积百分比
+ UNITS_CODE_VOLUME_MILLILITERS_PER_LITER = 154, // 毫升每升
+ UNITS_CODE_VOLUME_MICROLITERS_PER_LITER = 155, // 微升每升
+
+ // 单位质量代码
+ UNITS_CODE_QUALITY_DEGREES_BALLING = 107, // 波林度
+ UNITS_CODE_QUALITY_CUBIC_FEET_PER_POUND = 152, // 立方英尺每磅
+
+ // 浓度单位代码
+ UNITS_CODE_CONCENTRATION_PERCENT = 57, // 百分比
+ UNITS_CODE_CONCENTRATION_DEGREES_BRIX = 101, // 布氏度
+ UNITS_CODE_CONCENTRATION_PERCENT_SOLIDS_PER_WEIGHT = 105, // 固体质量百分比
+ UNITS_CODE_CONCENTRATION_PERCENT_SOLIDS_PER_VOLUME = 106, // 固体体积百分比
+ UNITS_CODE_CONCENTRATION_PROOF_PER_VOLUME = 108, // 酒精度(体积百分比)
+ UNITS_CODE_CONCENTRATION_PROOF_PER_MASS = 109, // 酒精度(质量百分比)
+ UNITS_CODE_CONCENTRATION_PARTS_PER_MILLION = 139, // 百万分之一
+ UNITS_CODE_CONCENTRATION_PARTS_PER_BILLION = 169, // 十亿分之一
+ UNITS_CODE_CONCENTRATION_PARTS_PER_THOUSAND = 170, // 千分之一
+
+ // 加速度单位代码
+ UNITS_CODE_ACCELERATION_GRAVITATIONAL_ACCELERATION = 170, // 重力加速度
+ UNITS_CODE_ACCELERATION_FEET_PER_SECOND_SQUARED = 171, // 英尺每秒平方
+ UNITS_CODE_ACCELERATION_METER_PER_SECOND_SQUARED = 172, // 米每秒平方
+
+ // 浊度单位代码
+ UNITS_CODE_TURBIDITY_FORMAZIN_NEPHELOMETRIC_UNITS = 170, // 甲醛胶凝法浊度单位
+ UNITS_CODE_TURBIDITY_FORMAZIN_TURBIDITY_UNIT = 171, // 甲醛浊度单位
+ UNITS_CODE_TURBIDITY_NEPHELOMETRIC_TURBIDITY_UNIT = 172, // 比浊度单位
+
+ // 每秒体积气体流量
+ UNITS_CODE_STANDARD_CUBIC_FEET_PER_SECOND = 186, // 标准立方英尺每秒
+ UNITS_CODE_NORMAL_LITER_PER_SECOND = 176, // 标准升每秒
+ UNITS_CODE_STANDARD_LITER_PER_SECOND = 180, // 标准立方米每秒
+ UNITS_CODE_NORMAL_CUBIC_METER_PER_SECOND = 183, // 标准立方米每秒
+ UNITS_CODE_STANDARD_CUBIC_METER_PER_SECOND = 190, // 标准立方米每秒
+
+ // 每分钟体积气体流量
+ UNITS_CODE_STANDARD_CUBIC_FEET_PER_MINUTE = 123, // 标准立方英尺每分钟
+ UNITS_CODE_NORMAL_LITER_PER_MINUTE = 175, // 标准升每分钟
+ UNITS_CODE_STANDARD_LITER_PER_MINUTE = 179, // 标准立方米每分钟
+ UNITS_CODE_NORMAL_CUBIC_METER_PER_MINUTE = 182, // 标准立方米每分钟
+ UNITS_CODE_STANDARD_CUBIC_METER_PER_MINUTE = 189, // 标准立方米每分钟
+
+ // 每小时体积气体流量
+ UNITS_CODE_STANDARD_CUBIC_FEET_PER_HOUR = 185, // 标准立方英尺每小时
+ UNITS_CODE_NORMAL_LITER_PER_HOUR = 122, // 标准升每小时
+ UNITS_CODE_STANDARD_LITER_PER_HOUR = 178, // 标准立方米每小时
+ UNITS_CODE_NORMAL_CUBIC_METER_PER_HOUR = 121, // 标准立方米每小时
+ UNITS_CODE_STANDARD_CUBIC_METER_PER_HOUR = 188, // 标准立方米每小时
+
+ // 每天体积气体流量
+ UNITS_CODE_STANDARD_CUBIC_FEET_PER_DAY = 184, // 标准立方英尺每天
+ UNITS_CODE_NORMAL_LITER_PER_DAY = 174, // 标准升每天
+ UNITS_CODE_STANDARD_LITER_PER_DAY = 177, // 标准立方米每天
+ UNITS_CODE_NORMAL_CUBIC_METER_PER_DAY = 181, // 标准立方米每天
+ UNITS_CODE_STANDARD_CUBIC_METER_PER_DAY = 187, // 标准立方米每天
+
+ // 每秒体积液体流量
+ UNITS_CODE_IMPERIAL_FLUID_OUNCES_PER_SECOND = 174, // 英制液体盎司每秒
+ UNITS_CODE_US_FLUID_OUNCES_PER_SECOND = 175, // 美制液体盎司每秒
+ UNITS_CODE_MILLILITER_PER_SECOND = 176, // 毫升每秒
+ UNITS_CODE_LITERS_PER_SECOND = 24, // 升每秒
+ UNITS_CODE_HECTOLITER_PER_SECOND = 178, // 公石每秒
+ UNITS_CODE_CUBIC_METER_PER_SECOND = 28, // 立方米每秒
+ UNITS_CODE_MILLION_LITERS_PER_SECOND = 180, // 百万升每秒
+ UNITS_CODE_US_GALLONS_PER_SECOND = 22, // 美制加仑每秒
+ UNITS_CODE_US_KILOGALLON_PER_SECOND = 182, // 美制千加仑每秒
+ UNITS_CODE_US_MILLION_GALLONS_PER_SECOND = 183, // 美制百万加仑每秒
+ UNITS_CODE_IMPERIAL_GALLONS_PER_SECOND = 137, // 英制加仑每秒
+ UNITS_CODE_IMPERIAL_MILLION_GALLONS_PER_SECOND = 185, // 英制百万加仑每秒
+ UNITS_CODE_CUBIC_FEET_PER_SECOND = 26, // 立方英尺每秒
+ UNITS_CODE_ACRE_FEET_PER_SECOND = 187, // 英亩英尺每秒
+ UNITS_CODE_US_DRUM_PER_SECOND = 188, // 美制桶每秒
+ UNITS_CODE_US_LIQUID_BARREL_PER_SECOND = 189, // 美制液体桶每秒
+ UNITS_CODE_US_BEER_BARREL_PER_SECOND = 170, // 美制啤酒桶每秒
+ UNITS_CODE_OIL_BARRELS_PER_SECOND = 132, // 油桶每秒
+ UNITS_CODE_UK_BEER_BARREL_PER_SECOND = 192, // 英制啤酒桶每秒
+
+ // 每分钟体积液体流量
+ UNITS_CODE_IMPERIAL_FLUID_OUNCES_PER_MINUTE = 174, // 英制液体盎司每分钟
+ UNITS_CODE_US_FLUID_OUNCES_PER_MINUTE = 175, // 美制液体盎司每分钟
+ UNITS_CODE_MILLILITER_PER_MINUTE = 176, // 毫升每分钟
+ UNITS_CODE_LITERS_PER_MINUTE = 17, // 升每分钟
+ UNITS_CODE_HECTOLITER_PER_MINUTE = 178, // 公石每分钟
+ UNITS_CODE_CUBIC_METER_PER_MINUTE = 131, // 立方米每分钟
+ UNITS_CODE_MILLION_LITERS_PER_MINUTE = 180, // 百万升每分钟
+ UNITS_CODE_US_GALLONS_PER_MINUTE = 16, // 美制加仑每分钟
+ UNITS_CODE_US_KILOGALLON_PER_MINUTE = 182, // 美制千加仑每分钟
+ UNITS_CODE_US_MILLION_GALLONS_PER_MINUTE = 183, // 美制百万加仑每分钟
+ UNITS_CODE_IMPERIAL_GALLONS_PER_MINUTE = 18, // 英制加仑每分钟
+ UNITS_CODE_IMPERIAL_MILLION_GALLONS_PER_MINUTE = 185, // 英制百万加仑每分钟
+ UNITS_CODE_CUBIC_FEET_PER_MINUTE = 15, // 立方英尺每分钟
+ UNITS_CODE_ACRE_FEET_PER_MINUTE = 187, // 英亩英尺每分钟
+ UNITS_CODE_US_DRUM_PER_MINUTE = 188, // 美制桶每分钟
+ UNITS_CODE_US_LIQUID_BARREL_PER_MINUTE = 189, // 美制液体桶每分钟
+ UNITS_CODE_US_BEER_BARREL_PER_MINUTE = 171, // 美制啤酒桶每分钟
+ UNITS_CODE_OIL_BARRELS_PER_MINUTE = 133, // 油桶每分钟
+ UNITS_CODE_UK_BEER_BARREL_PER_MINUTE = 192, // 英制啤酒桶每分钟
+
+ // 每小时体积液体流量
+ UNITS_CODE_IMPERIAL_FLUID_OUNCES_PER_HOUR = 174, // 英制液体盎司每小时
+ UNITS_CODE_US_FLUID_OUNCES_PER_HOUR = 175, // 美制液体盎司每小时
+ UNITS_CODE_MILLILITER_PER_HOUR = 176, // 毫升每小时
+ UNITS_CODE_LITERS_PER_HOUR = 138, // 升每小时
+ UNITS_CODE_HECTOLITER_PER_HOUR = 178, // 公石每小时
+ UNITS_CODE_CUBIC_METER_PER_HOUR = 19, // 立方米每小时
+ UNITS_CODE_MILLION_LITERS_PER_HOUR = 180, // 百万升每小时
+ UNITS_CODE_US_GALLONS_PER_HOUR = 136, // 美制加仑每小时
+ UNITS_CODE_US_KILOGALLON_PER_HOUR = 182, // 美制千加仑每小时
+ UNITS_CODE_US_MILLION_GALLONS_PER_HOUR = 183, // 美制百万加仑每小时
+ UNITS_CODE_IMPERIAL_GALLONS_PER_HOUR = 30, // 英制加仑每小时
+ UNITS_CODE_IMPERIAL_MILLION_GALLONS_PER_HOUR = 185, // 英制百万加仑每小时
+ UNITS_CODE_CUBIC_FEET_PER_HOUR = 130, // 立方英尺每小时
+ UNITS_CODE_ACRE_FEET_PER_HOUR = 187, // 英亩英尺每小时
+ UNITS_CODE_US_DRUM_PER_HOUR = 188, // 美制桶每小时
+ UNITS_CODE_US_LIQUID_BARREL_PER_HOUR = 189, // 美制液体桶每小时
+ UNITS_CODE_US_BEER_BARREL_PER_HOUR = 172, // 美制啤酒桶每小时
+ UNITS_CODE_OIL_BARRELS_PER_HOUR = 134, // 油桶每小时
+ UNITS_CODE_UK_BEER_BARREL_PER_HOUR = 192, // 英制啤酒桶每小时
+
+ // 每天体积液体流量
+ UNITS_CODE_IMPERIAL_FLUID_OUNCES_PER_DAY = 174, // 英制液体盎司每天
+ UNITS_CODE_US_FLUID_OUNCES_PER_DAY = 175, // 美制液体盎司每天
+ UNITS_CODE_MILLILITER_PER_DAY = 176, // 毫升每天
+ UNITS_CODE_LITERS_PER_DAY = 177, // 升每天
+ UNITS_CODE_HECTOLITER_PER_DAY = 178, // 公石每天
+ UNITS_CODE_CUBIC_METER_PER_DAY = 29, // 立方米每天
+ UNITS_CODE_MILLION_LITERS_PER_DAY = 25, // 百万升每天
+ UNITS_CODE_US_GALLONS_PER_DAY = 235, // 美制加仑每天
+ UNITS_CODE_US_KILOGALLON_PER_DAY = 182, // 美制千加仑每天
+ UNITS_CODE_US_MILLION_GALLONS_PER_DAY = 23, // 美制百万加仑每天
+ UNITS_CODE_IMPERIAL_GALLONS_PER_DAY = 31, // 英制加仑每天
+ UNITS_CODE_IMPERIAL_MILLION_GALLONS_PER_DAY = 185, // 英制百万加仑每天
+ UNITS_CODE_CUBIC_FEET_PER_DAY = 27, // 立方英尺每天
+ UNITS_CODE_ACRE_FEET_PER_DAY = 187, // 英亩英尺每天
+ UNITS_CODE_US_DRUM_PER_DAY = 188, // 美制桶每天
+ UNITS_CODE_US_LIQUID_BARREL_PER_DAY = 189, // 美制液体桶每天
+ UNITS_CODE_US_BEER_BARREL_PER_DAY = 173, // 美制啤酒桶每天
+ UNITS_CODE_OIL_BARRELS_PER_DAY = 135, // 油桶每天
+ UNITS_CODE_UK_BEER_BARREL_PER_DAY = 192, // 英制啤酒桶每天
+
+ // 热膨胀代码
+ UNITS_CODE_CELSIUS = 170, // 摄氏度
+ UNITS_CODE_FAHRENHEIT = 171, // 华氏度
+
+ // 体积能量密度代码
+ UNITS_CODE_KILOJOULES_PER_LITER = 170, // 千焦每升
+ UNITS_CODE_BRITISH_THERMAL_UNITS_PER_CUBIC_FOOT = 171, // 英热单位每立方英尺
+
+ // 质量能量密度单位代码
+ UNITS_CODE_MEGAJOULES_PER_KILOGRAM = 170, // 兆焦每千克
+ UNITS_CODE_BRITISH_THERMAL_UNITS_PER_POUND = 171, // 英热单位每磅
+
+ // 扭矩单位代码
+ UNITS_CODE_NEWTON_METER = 170, // 牛·米
+ UNITS_CODE_KILO_NEWTON_METER = 171, // 千牛·米
+ UNITS_CODE_POUND_FORCE_FEET = 172, // 磅力·英尺
+ UNITS_CODE_POUND_FORCE_INCH = 173, // 磅力·英寸
+ UNITS_CODE_MILLI_NEWTON_METER = 174, // 毫牛·米
+
+ // 其他单位代码
+ UNITS_CODE_OTHER_PERCENT = 57, // 57% 百分比
+ UNITS_CODE_OTHER_DECIBEL = 156, // 156 分贝
+ UNITS_CODE_OTHER_GRAMS_PER_MOL = 170, // 170 克每摩尔
+
+ // 扭转刚度单位代码
+ UNITS_CODE_KILO_NEWTON_METER_PER_DEGREE = 170, // 170 千牛顿·米每度
+ UNITS_CODE_NEWTON_METER_PER_DEGREE = 171, // 171 牛顿·米每度
+ UNITS_CODE_POUND_FORCE_FEET_PER_DEGREE = 172, // 172 磅力·英尺每度
+ UNITS_CODE_POUND_FORCE_INCH_PER_DEGREE = 173, // 173 磅力·英寸每度
+ UNITS_CODE_KILO_NEWTON_METER_PER_RADIAN = 174, // 174 千牛顿·米每弧度
+ UNITS_CODE_NEWTON_METER_PER_RADIAN = 175, // 175 牛顿·米每弧度
+ UNITS_CODE_POUND_FORCE_FEET_PER_RADIAN = 176, // 176 磅力·英尺每弧度
+ UNITS_CODE_POUND_FORCE_INCH_PER_RADIAN = 177, // 177 磅力·英寸每弧度
+
+ // 线性刚度单位代码
+ UNITS_CODE_KILO_NEWTON_PER_METER = 170, // 170 千牛顿每米
+ UNITS_CODE_NEWTON_PER_METER = 171, // 171 牛顿每米
+ UNITS_CODE_POUND_FORCE_PER_FOOT = 172, // 172 磅力每英尺
+ UNITS_CODE_POUND_FORCE_PER_INCH = 173, // 173 磅力每英寸
+
+ // 未使用
+ UNITS_CODE_UNDEFINE = 250, // 未使用
+} units_code_e;
+
+// 5.3 传输功能代码
+typedef enum
+{
+ TRANSMISSION_FUNCTION_CODE_LINEAR = 0, // 线性的
+ TRANSMISSION_FUNCTION_CODE_SQUARE_ROOT = 1, // 平方根
+ TRANSMISSION_FUNCTION_CODE_SQUARE_ROOT_CUBIC = 2, // 平方根三次方
+ TRANSMISSION_FUNCTION_CODE_SQUARE_ROOT_FIFTH = 3, // 平方根的五次方
+ TRANSMISSION_FUNCTION_CODE_SPECIAL_CURVE = 4, // 特殊曲线
+ TRANSMISSION_FUNCTION_CODE_SQUARE = 5, // Square
+ TRANSMISSION_FUNCTION_CODE_SQUARE_ROOT_TRUNCATED = 6, // 平方根与截断。包括基于差压的流量测量截止阀
+ TRANSMISSION_FUNCTION_CODE_EQUAL_PERCENT_1_25 = 10, // 相等百分比1:25
+ TRANSMISSION_FUNCTION_CODE_EQUAL_PERCENT_1_33 = 11, // 相等百分比1:33
+ TRANSMISSION_FUNCTION_CODE_EQUAL_PERCENT_1_50 = 12, // 相等百分比1:50
+ TRANSMISSION_FUNCTION_CODE_FAST_OPEN_1_25 = 15, // 快速打开1:25
+ TRANSMISSION_FUNCTION_CODE_FAST_OPEN_1_33 = 16, // 快速打开1:33
+ TRANSMISSION_FUNCTION_CODE_FAST_OPEN_1_50 = 17, // 快速打开1:50
+ TRANSMISSION_FUNCTION_CODE_HYPERBOLIC_SHAPE_FACTOR_0_10 = 30, // 双曲线:形状因子=0.10
+ TRANSMISSION_FUNCTION_CODE_HYPERBOLIC_SHAPE_FACTOR_0_20 = 31, // 双曲线形状因子=0.20
+ TRANSMISSION_FUNCTION_CODE_HYPERBOLIC_SHAPE_FACTOR_0_30 = 32, // 双曲线:形状因子=0.30
+ TRANSMISSION_FUNCTION_CODE_HYPERBOLIC_SHAPE_FACTOR_0_50 = 34, // 双曲线:形状因子=0.50
+ TRANSMISSION_FUNCTION_CODE_HYPERBOLIC_SHAPE_FACTOR_0_70 = 37, // 双曲线:形状因子=0.70
+ TRANSMISSION_FUNCTION_CODE_HYPERBOLIC_SHAPE_FACTOR_1_00 = 40, // 双曲线:形状因子=1.00
+ TRANSMISSION_FUNCTION_CODE_HYPERBOLIC_SHAPE_FACTOR_1_50 = 41, // 双曲线:形状因子=1.50
+ TRANSMISSION_FUNCTION_CODE_HYPERBOLIC_SHAPE_FACTOR_2_00 = 42, // 双曲线:形状因子=2.00
+ TRANSMISSION_FUNCTION_CODE_HYPERBOLIC_SHAPE_FACTOR_3_00 = 43, // 双曲线形状因子=3.00
+ TRANSMISSION_FUNCTION_CODE_HYPERBOLIC_SHAPE_FACTOR_4_00 = 44, // 双曲线:形状因子=4.00
+ TRANSMISSION_FUNCTION_CODE_HYPERBOLIC_SHAPE_FACTOR_5_00 = 45, // 双曲线:形状因子=5.00
+ TRANSMISSION_FUNCTION_CODE_FLAT_BOTTOM_TANK = 100, // 平底罐
+ TRANSMISSION_FUNCTION_CODE_CONICAL_OR_PYRAMIDAL_BOTTOM_TANK = 101, // 圆锥形或金字塔形底槽
+ TRANSMISSION_FUNCTION_CODE_PARABOLIC_BOTTOM_TANK = 102, // 抛物线底槽
+ TRANSMISSION_FUNCTION_CODE_SPHERICAL_BOTTOM_TANK = 103, // 球底储罐
+ TRANSMISSION_FUNCTION_CODE_SLOPING_BOTTOM_TANK = 104, // 倾斜底槽
+ TRANSMISSION_FUNCTION_CODE_FLAT_END_CYLINDRICAL_TANK = 105, // 平端圆筒油箱
+ TRANSMISSION_FUNCTION_CODE_PARABOLIC_END_CYLINDRICAL_TANK = 106, // 抛物线形端圆筒形储罐
+ TRANSMISSION_FUNCTION_CODE_SPHERICAL_TANK = 107, // 球罐
+ TRANSMISSION_FUNCTION_CODE_DISCRETE_SWITCH = 230, // 分立式(开关)
+ TRANSMISSION_FUNCTION_CODE_SQUARE_ROOT_PLUS_SPECIAL_CURVE = 231, // 平方根加上特殊曲线
+ TRANSMISSION_FUNCTION_CODE_SQUARE_ROOT_CUBIC_PLUS_SPECIAL_CURVE = 232, // 平方根三次幂加特殊曲线
+ TRANSMISSION_FUNCTION_CODE_SQUARE_ROOT_FIFTH_PLUS_SPECIAL_CURVE = 233, // 平方根五次幂加特殊曲线
+ TRANSMISSION_FUNCTION_CODE_NOT_USED = 250, // 未使用
+ TRANSMISSION_FUNCTION_CODE_NONE = 251, // 无
+ TRANSMISSION_FUNCTION_CODE_UNKNOWN = 252, // 未知
+ TRANSMISSION_FUNCTION_CODE_SPECIAL = 253 // 特殊的
+ // 210-229 枚举可用于制造商特定定义
+ // 234-249 枚举可用于制造商特定定义
+} transmission_function_code_e;
+
+// 5.6 报警选择代码
+typedef enum
+{
+ ALARM_CODE_HIGH = 0, // 高的
+ ALARM_CODE_LOW = 1, // 低的
+ // 239 保持最后输出值
+ ALARM_CODE_239 = 239,
+ // 240-249 枚举可用于制造商特定定义
+
+ // 250 Not Used
+ ALARM_CODE_NOT_USED = 250,
+ // 251 None
+ ALARM_CODE_NONE = 251,
+ // 252 Unknown
+ ALARM_CODE_UNKNOWN = 252,
+ // 253 特殊的
+ ALARM_CODE_SPECIAL = 253
+} alarms_code_e;
+
+// 5.7 写保护代码
+typedef enum
+{
+
+ WRITE_PROTECT_CODE_NOT_WRITE_PROTECT = 0, // 否-不写保护
+ WRITE_PROTECT_CODE_WRITE_PROTECT = 1, // 是-写保护
+ // 240-249 枚举可用于制造商特定定义
+
+ // 250 Not Used
+ WRITE_PROTECT_CODE_NOT_USED = 250,
+ // 251 None
+ WRITE_PROTECT_CODE_NONE = 251,
+ // 252 Unknown
+ WRITE_PROTECT_CODE_UNKNOWN = 252,
+ // 253 特殊的
+ WRITE_PROTECT_CODE_SPECIAL = 253
+} write_protect_code_e;
+
+// 5.8 制造商识别码
+typedef enum
+{
+ MANUFACTURER_IDENTIFIER_GSDT = 0x6196,
+} manufacturer_identifier_e;
+
+// 5.9 突发模式控制码
+typedef enum
+{
+ BURST_MODE_CONTROL_CODE_0 = 0, // 离开
+ BURST_MODE_CONTROL_CODE_1 = 1, // 仅在令牌传递数据链路层上启用突发
+ BURST_MODE_CONTROL_CODE_2 = 2, // 仅在TDMA数据链路层启用突发
+ BURST_MODE_CONTROL_CODE_3 = 3, // 在TDMA和令牌传递数据链路层上启用突发
+ BURST_MODE_CONTROL_CODE_4 = 4, // 在HART-IP连接上启用突发
+ BURST_MODE_CONTROL_CODE_250 = 250, // 保留的
+ BURST_MODE_CONTROL_CODE_251 = 251, // 保留的
+ BURST_MODE_CONTROL_CODE_252 = 252, // 保留的
+ BURST_MODE_CONTROL_CODE_253 = 253, // 保留的
+} burst_mode_control_code_e;
+
+// 5.10 物理信号
+typedef enum
+{
+ // Bell 202 Current
+ PHYSICAL_SIGNALS_0 = 0x00,
+ // Bell 202 Voltage
+ PHYSICAL_SIGNALS_1 = 0x01,
+ // RS-485
+ PHYSICAL_SIGNALS_2 = 0x02,
+ // RS-232
+ PHYSICAL_SIGNALS_3 = 0x03,
+ // Wireless
+ PHYSICAL_SIGNALS_4 = 0x04,
+ // Special(includes,for example, Ethernet,TCP/IP,WiFi,etc.)
+ PHYSICAL_SIGNALS_5 = 0x05,
+} physical_signals_e;
+
+// 5.14 操作模式代码
+typedef enum
+{
+ OPERATING_MODE_CODES_0 = 0,
+} operating_mode_codes_e;
+
+// 5.15 模拟通道代码
+typedef enum
+{
+ ANALOG_CHANNEL_NUMBER_CODES_0 = 0, // Analog Channel0(PV)
+ ANALOG_CHANNEL_NUMBER_CODES_1 = 1, // Analog Channel1(SV)
+ ANALOG_CHANNEL_NUMBER_CODES_2 = 2, // Analog Channel2(TV)
+ ANALOG_CHANNEL_NUMBER_CODES_3 = 3, // Analog Channel3(QV)
+ ANALOG_CHANNEL_NUMBER_CODES_4 = 4, // Analog Channel 4
+ ANALOG_CHANNEL_NUMBER_CODES_MAX,
+} analog_channel_number_codes_e;
+
+// 5.16 回路电流模式
+typedef enum
+{
+ // 关闭
+ LOOP_CURRENT_MODE_0 = 0x00,
+ // 使能
+ LOOP_CURRENT_MODE_1 = 0x01,
+} loop_current_mode_e;
+
+// 5.17 扩展现场设备状态
+typedef enum
+{
+ // 正常
+ EXTENDED_DEVICE_STATUS_0 = 0x00,
+ // 需要维护。[浓缩状态]此位设置用于指示设备未发生故障时,现场设备需要维护。支持此位的设备应支持压缩状态命令(请参阅通用操作命令规范)
+ EXTENDED_DEVICE_STATUS_1 = BIT0,
+ // 设备变量警报,如果任何设备变量处于警报或警告状态,则设置此位。主机应使用设备变量状态指示器识别导致设置的设备变量
+ EXTENDED_DEVICE_STATUS_2 = BIT1,
+ // 关键电源故障。适用于可以通过存储电源进行操作的设备。该位是在功率变得极低时设置的。例如,一个清除电源的设备失去电源就会设置这个位。设备必须能够从该位开始维持其网络连接至少15分钟。如果设备的功率水平下降得太低,则设备可能会开始正常断开与网络的连接
+ EXTENDED_DEVICE_STATUS_3 = BIT2,
+ // 故障。压缩状态当设置此位时,由于现场设备或其外围设备的故障,一个或多个设备变量(例如测量或控制值)无效。支持此位的设备必须支持浓缩状态命令(请参阅通用规程命令规范)
+ EXTENDED_DEVICE_STATUS_4 = BIT3,
+ // 超出规格。设置时处于浓缩状态。该位表示已检测到与允许环境或工艺条件的偏差,这可能会影响测量或控制精度(即,在给定当前操作条件的情况下,设备性能可能会降低)。支持此位的设备必须支持精简状态命令(请参阅通用规程命令规范)。
+ EXTENDED_DEVICE_STATUS_5 = BIT4,
+ // 功能检查。压缩状态如果一个或多个设备变量由于设备上正在进行的工作而暂时无效(例如冻结),则设置此位。支持该位的设备必须支持浓缩状态命令(见通用规程命令规范)
+ EXTENDED_DEVICE_STATUS_6 = BIT5,
+} extended_device_status_e;
+
+// 5.18 锁定设备代码
+typedef enum
+{
+ // 解锁
+ LOCK_DEVICE_CODE_0 = 0x00,
+ // 锁-临时(即设备复位或断电释放锁定)。只有锁定主机才能解锁
+ LOCK_DEVICE_CODE_1 = 0x01,
+ // 锁定-永久(即设备复位或断电不影响锁定)。只有锁定主机才能解锁
+ LOCK_DEVICE_CODE_2 = 0x02,
+ // 全部锁定-任何主机都不允许对设备的配置进行更改。此外,设备复位或电源丢失不影响Lock24。任何主机都可以解锁。
+ LOCK_DEVICE_CODE_3 = 0x03,
+ LOCK_DEVICE_CODE_MAX,
+} lock_device_code_e;
+
+// 5.19 写设备变量代码
+typedef enum
+{
+ WRITE_DEVICE_VARIABLE_COMMAND_CODE_0 = 0x00, // 正常(设备计算的值不是模拟的)
+ WRITE_DEVICE_VARIABLE_COMMAND_CODE_1 = 0x01, // 固定值(模拟设备计算的值)
+} write_device_variable_command_code_e;
+
+// 5.20 设备变量系列代码
+typedef enum
+{
+ // 0-3 保留的。不得使用
+ // 温度
+ DEVICE_VARIABLE_FAMILY_CODE_4 = 0x04,
+ // 压力
+ DEVICE_VARIABLE_FAMILY_CODE_5 = 0x05,
+ // 阀门/执行器
+ DEVICE_VARIABLE_FAMILY_CODE_6 = 0x06,
+ // 简单PID控制
+ DEVICE_VARIABLE_FAMILY_CODE_7 = 0x07,
+ // ph值
+ DEVICE_VARIABLE_FAMILY_CODE_8 = 0x08,
+ // 传导性
+ DEVICE_VARIABLE_FAMILY_CODE_9 = 0x09,
+ // 累加器
+ DEVICE_VARIABLE_FAMILY_CODE_10 = 0x0A,
+ // 等级
+ DEVICE_VARIABLE_FAMILY_CODE_11 = 0x0B,
+ // 涡流
+ DEVICE_VARIABLE_FAMILY_CODE_12 = 0x0C,
+ // 马赫流量
+ DEVICE_VARIABLE_FAMILY_CODE_13 = 0x0D,
+ // 科氏流
+ DEVICE_VARIABLE_FAMILY_CODE_14 = 0x0E,
+ // 调制最终控制
+ DEVICE_VARIABLE_FAMILY_CODE_15 = 0x0F,
+ // 132-249 保留的。不得使用
+ // 250 未使用
+ DEVICE_VARIABLE_FAMILY_CODE_250 = 0xFA,
+} device_variable_family_code_e;
+
+// 5.21 设备变量分类代码
+typedef enum
+{
+ // 设备变量未分类
+ DEVICE_VARIABLE_CLASSIFICATION_CODE_0 = 0x00,
+ // 1-63 保留的
+ // 温度
+ DEVICE_VARIABLE_CLASSIFICATION_CODE_64 = 0x40,
+ // 压力
+ DEVICE_VARIABLE_CLASSIFICATION_CODE_65 = 0x41,
+ // 体积流量
+ DEVICE_VARIABLE_CLASSIFICATION_CODE_66 = 0x42,
+ // 速度
+ DEVICE_VARIABLE_CLASSIFICATION_CODE_67 = 0x43,
+ // 体积
+ DEVICE_VARIABLE_CLASSIFICATION_CODE_68 = 0x44,
+ // 长度
+ DEVICE_VARIABLE_CLASSIFICATION_CODE_69 = 0x45,
+ // 时间
+ DEVICE_VARIABLE_CLASSIFICATION_CODE_70 = 0x46,
+ // 块
+ DEVICE_VARIABLE_CLASSIFICATION_CODE_71 = 0x47,
+ // 质量流量
+ DEVICE_VARIABLE_CLASSIFICATION_CODE_72 = 0x48,
+ // 每体积质量
+ DEVICE_VARIABLE_CLASSIFICATION_CODE_73 = 0x49,
+ // 粘度
+ DEVICE_VARIABLE_CLASSIFICATION_CODE_74 = 0x4A,
+ // 角速度
+ DEVICE_VARIABLE_CLASSIFICATION_CODE_75 = 0x4B,
+ // 区域
+ DEVICE_VARIABLE_CLASSIFICATION_CODE_76 = 0x4C,
+ // 能源(工作)
+ DEVICE_VARIABLE_CLASSIFICATION_CODE_77 = 0x4D,
+ // 力
+ DEVICE_VARIABLE_CLASSIFICATION_CODE_78 = 0x4E,
+ // 力量
+ DEVICE_VARIABLE_CLASSIFICATION_CODE_79 = 0x4F,
+ // 频率
+ DEVICE_VARIABLE_CLASSIFICATION_CODE_80 = 0x50,
+ // 分析的
+ DEVICE_VARIABLE_CLASSIFICATION_CODE_81 = 0x51,
+ // 电容
+ DEVICE_VARIABLE_CLASSIFICATION_CODE_82 = 0x52,
+ // 电动势/电势
+ DEVICE_VARIABLE_CLASSIFICATION_CODE_83 = 0x53,
+ // 电流
+ DEVICE_VARIABLE_CLASSIFICATION_CODE_84 = 0x54,
+ // 抵抗
+ DEVICE_VARIABLE_CLASSIFICATION_CODE_85 = 0x55,
+ // 角
+ DEVICE_VARIABLE_CLASSIFICATION_CODE_86 = 0x56,
+ // 电导
+ DEVICE_VARIABLE_CLASSIFICATION_CODE_87 = 0x57,
+ // 每卷
+ DEVICE_VARIABLE_CLASSIFICATION_CODE_88 = 0x58,
+ // 每质量体积
+ DEVICE_VARIABLE_CLASSIFICATION_CODE_89 = 0x59,
+ // 浓度
+ DEVICE_VARIABLE_CLASSIFICATION_CODE_90 = 0x5A,
+ // 保留的
+ DEVICE_VARIABLE_CLASSIFICATION_CODE_91 = 0x5B,
+ // 保留的
+ DEVICE_VARIABLE_CLASSIFICATION_CODE_92 = 0x5C,
+ // 保留的
+ DEVICE_VARIABLE_CLASSIFICATION_CODE_93 = 0x5D,
+ // 保留的
+ DEVICE_VARIABLE_CLASSIFICATION_CODE_94 = 0x5E,
+ // 保留的
+ DEVICE_VARIABLE_CLASSIFICATION_CODE_95 = 0x5F,
+ // 加速
+ DEVICE_VARIABLE_CLASSIFICATION_CODE_96 = 0x60,
+ // 浊度
+ DEVICE_VARIABLE_CLASSIFICATION_CODE_97 = 0x61,
+ // 温差
+ DEVICE_VARIABLE_CLASSIFICATION_CODE_98 = 0x62,
+ // 气体体积流量(每秒)
+ DEVICE_VARIABLE_CLASSIFICATION_CODE_99 = 0x63,
+ // 气体体积流量(每分钟)
+ DEVICE_VARIABLE_CLASSIFICATION_CODE_100 = 0x64,
+ // 气体体积流量(每小时)
+ DEVICE_VARIABLE_CLASSIFICATION_CODE_101 = 0x65,
+ // 气体体积流量(每天)
+ DEVICE_VARIABLE_CLASSIFICATION_CODE_102 = 0x66,
+ // 体积液体流量(每秒)
+ DEVICE_VARIABLE_CLASSIFICATION_CODE_103 = 0x67,
+ // 体积液体流量(每分钟)
+ DEVICE_VARIABLE_CLASSIFICATION_CODE_104 = 0x68,
+ // 容积液体流量(每小时)
+ DEVICE_VARIABLE_CLASSIFICATION_CODE_105 = 0x69,
+ // 容积液体流量(每天)
+ DEVICE_VARIABLE_CLASSIFICATION_CODE_106 = 0x6A,
+ // 热胀
+ DEVICE_VARIABLE_CLASSIFICATION_CODE_107 = 0x6B,
+ // 体积能量密度
+ DEVICE_VARIABLE_CLASSIFICATION_CODE_108 = 0x6C,
+ // 质量能量密度
+ DEVICE_VARIABLE_CLASSIFICATION_CODE_109 = 0x6D,
+ // 转矩
+ DEVICE_VARIABLE_CLASSIFICATION_CODE_110 = 0x6E,
+ // 杂项
+ DEVICE_VARIABLE_CLASSIFICATION_CODE_111 = 0x6F,
+ // 扭转刚度
+ DEVICE_VARIABLE_CLASSIFICATION_CODE_112 = 0x70,
+ // 线性刚度
+ DEVICE_VARIABLE_CLASSIFICATION_CODE_113 = 0x71,
+} device_variable_classification_code_e;
+
+// 5.22 微调代码
+typedef enum
+{
+ TRIM_POINTS_0 = 0, // 不支持修剪点
+ TRIM_POINTS_1 = 1, // 支持下调整点
+ TRIM_POINTS_2 = 2, // 支撑上调整点
+ TRIM_POINTS_3 = 3, // 支持下和上调整点
+} trim_points_e;
+
+// 5.26 模拟通道标志
+typedef enum
+{
+ ANALOG_CHANNEL_CODE_0 = 0, // 任何未涵盖的位都是“未定义”,必须设置为零
+ ANALOG_CHANNEL_CODE_1 = 1, // 设置时,此模拟通道是场设备模拟输入通道。换句话说,在设置此位时,现场设备有一个与此信道连接的ADC当重置为零时,模拟通道是模拟输出(ADC连接到通道)
+} analog_channel_code_e;
+
+// 5.27 模拟通道饱和
+typedef enum
+{
+ ANALOG_CHANNEL_SATURATED_0 = 0,
+ ANALOG_CHANNEL_SATURATED_1 = BIT0, // 次级模拟通道饱和
+ ANALOG_CHANNEL_SATURATED_2 = BIT1, // 第三模拟通道饱和
+ ANALOG_CHANNEL_SATURATED_3 = BIT2, // 四阶模拟信道饱和
+ ANALOG_CHANNEL_SATURATED_4 = BIT3 // 五进制模拟通道饱和
+} analog_channel_saturated_e;
+
+// 5.28 固定模拟通道
+typedef enum
+{
+ ANALOG_CHANNEL_FIXED_0 = 0,
+ ANALOG_CHANNEL_FIXED_1 = BIT0, // 辅助模拟通道固定
+ ANALOG_CHANNEL_FIXED_2 = BIT1, // 三级模拟通道固定
+ ANALOG_CHANNEL_FIXED_3 = BIT2, // 四元模拟通道固定
+ ANALOG_CHANNEL_FIXED_4 = BIT3 // 固定五进制模拟通道
+} analog_channel_fixed_e;
+
+// 5.29 标准化状态0
+typedef enum
+{
+ STANDARDIZED_STATUS0_0 = 0,
+ STANDARDIZED_STATUS0_1 = BIT0, // 设备变量模拟激活。设备处于模拟模式,并且其一个或多个设备变量不能代表该过程
+ STANDARDIZED_STATUS0_2 = BIT1, // 非易失性存储器缺陷。非易失性内存检查无效或可能已损坏,或电池支持内存的电池有缺陷
+ STANDARDIZED_STATUS0_3 = BIT2, // 易失性存储器缺陷。RAM内存检查无效或可能已损坏
+ STANDARDIZED_STATUS0_4 = BIT3, // 看门狗复位执行。已执行看门狗复位
+ STANDARDIZED_STATUS0_5 = BIT4, // 电源条件超出范围。电源、电源或电压超出其允许范围
+ STANDARDIZED_STATUS0_6 = BIT5, // 环境条件超出范围。内部或环境条件超出可接受限度
+ STANDARDIZED_STATUS0_7 = BIT6, // 电子缺陷。检测到与传感器无关的硬件问题
+ STANDARDIZED_STATUS0_8 = BIT7 // 设备配置已锁定。设备处于写保护状态或已锁定
+} standardized_status0_e;
+// 5.30 标准化状态1
+typedef enum
+{
+ STANDARDIZED_STATUS1_0 = 0,
+ STANDARDIZED_STATUS1_1 = BIT0, // 状态模拟激活。状态模拟模式已被启用,设备状态和命令48响应中返回的状态位是固定的,可能不代表设备的当前状态
+ STANDARDIZED_STATUS1_2 = BIT1, // 离散变量模拟激活。设备处于模拟模式,其一个或多个离散变量不能代表过程
+ STANDARDIZED_STATUS1_3 = BIT2, // 事件通知溢出。当一个或多个事件规范(见通用实践命令规范中的事件通知)的事件队列溢出导致事件不能被记录时,必须设置该位。当所有挂起事件都已确认 时,此位必须重置
+ STANDARDIZED_STATUS1_4 = BIT3, // 电池或电源需要维护。当现场设备中的电池需要更换/充电时,必须设置此位。此位也必须被设置,如果电源需要维护
+ STANDARDIZED_STATUS1_5 = BIT4 // 保留的。必须设置(0)
+} standardized_status1_e;
+
+// 5.31 标准化状态2
+typedef enum
+{
+ STANDARDIZED_STATUS2_0 = 0,
+ STANDARDIZED_STATUS2_1 = BIT0, // 子设备列表已更改。设置时,/0系统与它的一个子设备失去了通信,或者发现了一个新的子设备。发出命令74以读取“检测到的设备的数目“或发出命令84以“子设备索引”为0或1仅仅重置该位”。使用Command读取当前子设备列表
+ STANDARDIZED_STATUS2_2 = BIT1, // 检测到重复的主设备。Adapter发现另一个主机与它的令牌传递接口具有相同的地址
+ STANDARDIZED_STATUS2_3 = BIT2, // 子设备不匹配。连接到系统的一个或多个子设备与所存储的/预配置的值不匹配
+ STANDARDIZED_STATUS2_4 = BIT3, // 发现具有重复ID的子设备,发现连接到U/O系统的具有重复唯一ID或长标签的子设备
+ STANDARDIZED_STATUS2_5 = BIT4 // 陈旧数据通知。当设置任何子设备的陈旧数据报警时,设置此位
+} standardized_status2_e;
+
+// 5.32 标准化状态3
+typedef enum
+{
+ STANDARDIZED_STATUS3_0 = 0,
+ STANDARDIZED_STATUS3_1 = BIT0, // 拒绝容量。设备无法获取支持指定的突发消息传递所需的通信带宽。如果网络管理器减少了分配给设备的带宽,也必须设置此值。当网络中的任何设备带宽不足时,网关必须设置此位
+ STANDARDIZED_STATUS3_2 = BIT1, // 保留,必须设置为0
+ STANDARDIZED_STATUS3_3 = BIT2, // 带宽分配挂起。设备已向网络管理器请求带宽,正在等待网络管理器的响应
+ STANDARDIZED_STATUS3_4 = BIT3, // 块传输挂起。该设备有一个数据集(例如,波形)等待传输到主机应用程序或网关。网关应打开块传输端口并传输数据
+ STANDARDIZED_STATUS3_5 = BIT4 // 无线电故障,radio或radio模块发生故障,设备需要维修或更换。设备状态字节中的“设备故障”位必须在设置此位时设置。
+} standardized_status3_e;
+
+// 5.33 突发消息触发代码
+typedef enum
+{
+ BURST_MESSAGE_TRIGGER_CODE_0 = 0, // 连续的。突发消息在(最坏情况) 最小更新周期内连续发布
+ BURST_MESSAGE_TRIGGER_CODE_1 = 1, // 窗口中。当源值偏离超过指定的触发值时,触发突发消息
+ BURST_MESSAGE_TRIGGER_CODE_2 = 2, // 正在上升。当源值高于指定的触发值时触发突发消息
+ BURST_MESSAGE_TRIGGER_CODE_3 = 3, // 在下降。当源值低于指定的触发值时触发突发消息
+ BURST_MESSAGE_TRIGGER_CODE_4 = 4, // 在改变。当消息中的任何值改变时,突发消息被触发
+} burst_message_trigger_code_e;
+
+// 5.34 设备变量代码
+///
+/// 设备变量代码 5.34
+///
+typedef enum
+{
+ // 0-239 枚举可用于制造商特定定义
+ DEV_INPUT_CURRENT = 0x00, ///< 输入电流
+ DEV_TEMPERATURE = 0x01, ///< 温度
+ DEV_PRESS = 0x02, ///< 压力
+ DEV_VALVE_TRAVEL = 0x03, ///< 阀门行程
+ DEV_PRESS_B = 0x05, ///< B路压力
+ DEV_SUPPLY_PRESS = 0x08, ///< 供应压力
+ DEV_TRAVEL_SETPT = 0x09, ///< 行程设置点
+ DEV_SERVO_FEEDBACK = 0x0A, ///< 伺服反馈
+} device_variable_code_e;
+
+typedef enum
+{
+ DIN_ANALOG_INPUT = 0, // 输入电流
+ DIN_INTERNAL_TEMPERATURE = 1, // 温度
+ DIN_PRESSURE_PORT_A = 2, // A路压力
+ DIN_TRAVEL = 3, // 阀门行程(实际行程)
+ DIN_DRIVE_SIGNAL = 4, // 驱动信号
+ DIN_PRESSURE_PORT_B = 5, // B路压力
+ DIN_TRAVEL_SETPOINT = 6, // 行程设置点(可写)
+ DIN_DIFFERENTIAL_PRESSURE = 7, // 压力A减压力B
+ DIN_SUPPLY_PRESSURE = 8, // 供气压力
+ DIN_IMPLIED_VALVE_POSITION = 9, // 行程设置点(只读)
+ DIN_PRIMARY_FEEDBACK = 10, // 伺服反馈
+
+ /************常量部分**************/
+
+ DIN_INST_MODE = 11, // 仪器模式
+ DIN_CONTROL_MODE = 12, // 控制模式
+ DIN_LEAD_LAG_OPEN = 16, // 超前滞后上限
+ DIN_LEAD_LAG_CLOSE = 17, // 超前滞后下限
+ DIN_LOOP_PST_ETT = 18, // 部分行程测试解电至跳闸
+ DIN_LOW_SUPPLY_ALERT_PT = 19, // 供应压力下限报警设定值
+ DIN_INPUT_UNIT = 20, // 电流单位
+ DIN_INPUT_RANGE_HI = 21, // 输入电流上限值
+ DIN_INPUT_RANGE_LO = 22, // 输入电流下限值
+ DIN_LOOP_PST_DETT = 25, // 部分行程测试充电至跳闸
+ DIN_INPUT_SPAN = 26, // 输入电流范围
+ DIN_INPUT_OFFSET = 27, // 输入电流偏移
+ DIN_AUX_INPUT_TYPE = 28, // 辅助输入类型
+ DIN_PRESS_UNIT = 36, // 压力单位
+ DIN_PRESS_100_PERCENT = 37, // 压力控制100位置压力值(只用于显示)
+ DIN_PRESS_0_PERCENT = 38, // 压力控制0位置压力值(只用于显示)
+ DIN_PRESS_A_SPAN = 39, // 压力A口跨度
+ DIN_PRESS_A_OFFSET = 40, // 压力A口偏移
+ DIN_TRAVEL_UNITS = 41, // 行程单位
+ DIN_TRAVEL_100_PERCENT = 42, // 行程控制100位置行程(只用于显示)
+ DIN_TRAVEL_0_PERCENT = 43, // 行程控制0位置行程(只用于显示)
+ DIN_FEEDBACK_CHAR = 44, // 反馈特性
+ DIN_POS_SPAN = 45, // 位置跨度
+ DIN_POS_OFFSETR = 46, // 位置偏移
+ DIN_MINOR_LOOP_SPAN = 50, // 小回路跨度
+ DIN_ACCESSORY_FLAGS = 53, // 附属标志
+ DIN_CROSS_UNSCALED = 54, // 磁条反馈原始值,磁条ADC采样值
+ DIN_SOFT_CUTOFF_RATE_OPEN_UNSCALED = 55, // 上限软切割速率
+ DIN_INTEGRAL_LIMIT_UNSCALED = 56, // 积分限位
+ DIN_AER_CONFIG = 57, // 警报记录使能
+ DIN_XMTR_MODE_FLAGS = 58, // XMTR模式标志
+ DIN_XMTR_ENABLE = 59, // XMTR使能
+ DIN_XMTR_INSTALLED_POSXMTRSTATE = 61, // 位置变送器状态
+ DIN_TVL_DEV_TRIP = 63, // 行程/压力偏差跳变点
+ DIN_TVL_DEV_TIME = 64, // 行程/压力偏差时间
+ DIN_SIS_OVERRIDE_STATUS = 65, // 仪表覆盖状态
+ DIN_SOFT_CUTOFF_RATE_CLOSE_UNSCALED = 66, // 下限软切割速率
+ DIN_TRAVEL_CHAR = 67, // 阀门特性
+ DIN_TRAVEL_CUTOFF_LIMIT_HI = 68, // 行程切割限位上限
+ DIN_TRVEL_CUTOFF_LIMIT_LO = 69, // 行程切割限位下限
+ DIN_CUTOFF_LIMIT_SEL = 70, // 切割限位选择
+ DIN_AUTOCAL_BTN = 71, // 自动校准按钮
+ DIN_RATE_LIMIT_OPEN = 72, // 行程/压力设定点速率上限
+ DIN_RATE_LIMIT_CLOSE = 73, // 行程/压力设定点速率下限
+ DIN_ZERO_POWER = 74, // 零功率条件
+ DIN_TRACEL_PRESS_SEL = 75, // 行程压力选择
+ DIN_INVERT_FEEDBACK = 76, // 反向反馈
+ DIN_RESERVE_78 = 78, // 保留位
+ DIN_MINOR_LOOP_NORMAL = 79, // 小回路正常值
+ DIN_AUTOCAL_STEP_ID = 80, // 整定步骤
+ DIN_RESTART_INST_MODE = 84, // 重启仪器模式
+ DIN_COMM_TIMEOUT = 85, // 通讯超时设置
+ DIN_TRAVEL_KP_GAIN = 86, // 行程比例增益
+ DIN_TRAVEL_KV_GAIN = 87, // 行程速度增益
+ DIN_TRAVEL_MLFB_GAIN = 88, // 行程控制小回路增益
+ DIN_PRESS_KI_GAIN = 89, // 压力积分增益
+ DIN_TRAVEL_KI_GAIN = 90, // 行程积分增益
+ DIN_COMP_MODE = 92, // 积分控制使能
+ DIN_ACT_STYLE = 93, // 执行机构类型
+ DIN_HIGH_SUPPLY_ALERT_PT = 95, // 供应压力上限报警设置值
+ DIN_PRESS_B_SPAN = 97, // 压力B口跨度
+ DIN_PRESS_B_OFFSET = 98, // 压力B口偏移
+ DIN_PRESS_S_SPAN = 99, // 气源压力跨度
+ DIN_PRESS_S_OFFSET = 100, // 气源压力偏移
+ DIN_PRESS_SETPOINT = 101, // 目标压力设定值
+ DIN_PRESS_SENSOR_ENABLE = 102, // 压力传感器使能
+ DIN_MSM_6X = 104, // 更多状态标志
+ DIN_PRESS_RNG_LO = 105, // 压力范围下限(起点压力)
+ DIN_PRESS_RNG_HI = 106, // 压力范围上限(顶点压力)
+ DIN_LCP_TRIP_ALERT_SEC = 107, // LCP通讯跳闸警报时间
+ DIN_AUTOCAL_STATUS = 108, // 上次整定结果
+ DIN_PRESS_KP_GAIN = 110, // 压力比例增益
+ DIN_PRESS_RATE = 111, // 压力速率
+ DIN_INTEGRAL_DB = 112, // 积分死区
+ DIN_LVP_FILTER_SELECTOR = 113, // 滞后时间
+ DIN_PRESS_MLFB_GAIN = 114, // 压力控制小回路增益
+ DIN_LEAD_LAG_BOOST = 116, // 超前滞后启动
+ DIN_SIS_OPT = 117, // 回路电流确认
+ DIN_TRIGGER_SENSITIVITY = 118, // 触发灵敏度
+ DIN_STROKE_ALERT_EN = 120, // 行程报警使能/禁止
+ DIN_PRESS_A_LIMIT = 121, // 压力A限制
+ DIN_PST_DEFERRAL_REASON = 122, // 部分行程测试延期原因
+ DIN_OUTPUT_PRESS_LIMIT_ENABLE = 124, // 输出压力限制使能
+ DIN_BREAKOUT_TIME_ALERT_PT = 127, // 启动时间报警设定值
+ DIN_AUTOCAL_SETTLING_TIME = 130, // 自动校准稳定时间
+ DIN_TRAVEL_DEV_ALERT_PT = 138, // 行程控制偏差报警设定值
+ DIN_TRAVEL_HI_ALERT_PT = 139, // 行程上限报警设定值
+ DIN_TRAVEL_LO_ALERT_PT = 140, // 行程下限报警设定值
+ DIN_TRAVEL_HIHI_ALERT_PT = 141, // 行程上限过高报警设定值
+ DIN_TRAVEL_LOLO_ALERT_PT = 142, // 行程下限过低报警设定值
+ DIN_TRAVEL_ALERT_DEADBAND_UNSCALED = 143, // 所有行程警报死区
+ DIN_TRAVEL_DEV_ALERT_TIME = 145, // 行程偏差报警时间
+ DIN_RST_STROKE_TIME_ALERT_PT = 146, // 复位时间报警设定值
+ DIN_DMD_STROKE_TIME_ALERT_PT = 147, // 行程时间报警设定值
+ DIN_CYCLE_COUNT_DEADBAND_UNSCALED = 149, // 周期计数累计死区(Cycle Cnt/Tv Accum Deadband (%))
+ DIN_CYCLE_COUNT_LIMIT = 150, // 动作次数报警设定值
+ DIN_CYCLE_COUNT = 151, // 动作次数
+ DIN_TRAVEL_ACCUM_ALERT_PT = 154, // 累计行程报警设定值
+ DIN_TRAVEL_ACCUM = 155, // 累计行程
+ DIN_PS1_TRIGGER_DB = 156, // A口压力跳变点
+ DIN_PS2_TRIGGER_DB = 157, // B口压力跳变点
+ DIN_CURRENT_TRIGGER_DB = 158, // 输入电流跳变点
+ DIN_MIN_PST_PRESS = 161, // 部分行程测试最小压力
+ DIN_MIN_PST_PRESS_TIME = 162, // 部分行程测试最小压力时间
+ DIN_PRESS_DEV_ALERT_PT = 163, // 压力控制偏差报警设定值
+ DIN_PRESS_DEV_ALERT_TIME = 164, // 压力偏差报警时间
+ DIN_MIN_TEMP = 170, // 温度范围下限
+ DIN_MAX_TEMP = 171, // 温度范围上限
+ DIN_RUN_TIME = 172, // 设备工作时长
+ DIN_POWER_UPS = 173, // 设备上电次数
+ DIN_XMTR_STATUS = 177, // XMTR状态
+ DIN_SERVO_OUTPUT_BIAS = 178, // 伺服偏差输出
+ DIN_MANUAL_LOADER = 182, // 手动加载
+ DIN_DEF_SETPT_UNSCALED = 200, // 默认设定点
+ DIN_RESTART_CTRL_MODE = 201, // 重新启动控制模式
+ DIN_SELFTEST_SHUTDOWN = 204, // 停机自检
+ DIN_DRIVE_RAW = 205, // 原始驱动
+ DIN_TEMP_UNIT = 210, // 温度单位
+ DIN_CROSSOVER_OUT = 212, // 变化点(与行程有关)
+ DIN_BURST_MODE = 218, // 突发模式
+ DIN_POLLING_ADDR = 219, // 轮询地址
+ DIN_SVT_ENABLE_FLAG = 221, // SVT使能标志
+ DIN_SVT_ALERT_EN = 222, // SVT报警使能/禁用
+ DIN_SVT_TRIP_PRESS_ALERT_PT = 224, // SVT跳闸压力报警设定值
+ DIN_SVT_RECOVERY_PRESS_ALERT_PT = 225, // SVT恢复压力报警设定值
+
+ DIN_AUTO_TUNING_ERR_CODE = 235, // 自动整定错误代码
+ DIN_PART_TRAVEL_ENABLE = 236, // 部分行程使能
+ DIN_PART_TRAVEL_LOWER = 237, // 部分行程下限
+ DIN_PART_TRAVEL_UPPER = 238, // 部分行程上限
+ DIN_OUTPUT_SPAN = 239, // 输入电流范围(预留暂时不使用)
+ DIN_OUTPUT_OFFSET = 240, // 输入电流偏移
+ DIN_DEVICE_TYPE = 241, // 设备类型 GPS2000/GPS3000
+
+ // 以下为标准设备变量
+ //(可选)电池电压(单位代码为“伏特”设备变量分类为“设备变量未分类”)。警告:取决于电池技术,电池电压不能提供剩余电池寿命的良好指标(即电池中剩余的电量)
+ DIN_242 = 0xF2,
+ // 电池寿命(浮动天数;单位代码为“天”;设备变量分类为“设备变量未分类”)
+ DIN_243 = 0xF3,
+ // 百分比范围(单位代码为“百分比”;设备变量分类为“设备变量未分类”)
+ DIN_244 = 0xF4,
+ // 回路电流(单位代码为“Miliamperes.31,设备变量分类为“设备变量未分类”)
+ DIN_245 = 0xF5,
+ // 主变量
+ DIN_246 = 0xF6,
+ // 次要变量
+ DIN_247 = 0xF7,
+ // 三级变量
+ DIN_248 = 0xF8,
+ // 四级变量
+ DIN_249 = 0xF9,
+ // 250 未使用(此代码必须仅在满足协议命令要求时返回。见,例如,常用命令规范)
+ DIN_250 = 0xFA,
+ DIN_251 = 0xFB, // 251 未使用
+
+} device_key_e;
+
+// 5.37 趋势控制代码
+typedef enum
+{
+ TREND_CONTROL_CODE_0 = 0x00, // 禁用
+ TREND_CONTROL_CODE_1 = 0x01, // 启用单一数据点趋势分析
+ TREND_CONTROL_CODE_2 = 0x02, // 启用筛选趋势。使用等于趋势样本周期三分之一的时间常数对样本进行过滤
+ TREND_CONTROL_CODE_3 = 0x03, // 启用平均趋势(可选)。换句话说,就是将周期内所有样本之和除以样本总数所得到的值
+ TREND_CONTROL_CODE_MAX,
+} trend_control_code_e;
+
+// 5.38 时间设置代码
+typedef enum
+{
+ TIME_SETTING_CODE_0 = 0x00, // 离开
+ TIME_SETTING_CODE_1 = 0x01, // 在令牌传递数据链路层上启用事件通知
+ TIME_SETTING_CODE_2 = 0x02, // 在TDMA数据链路层上启用事件通知
+ TIME_SETTING_CODE_3 = 0x03, // 在TDMA和令牌传递数据链路层上启用事件通知
+ TIME_SETTING_CODE_MAX,
+} time_setting_code_e;
+
+// 5.41 同步操作控制代码
+typedef enum
+{
+ SYNCHRONIZATION_OPERATION_CONTROL_CODE_1 = BIT0, // 命令当设置指示的命令将被执行在指定的时间。当重置一个设备变量要被采样
+ SYNCHRONIZATION_OPERATION_CONTROL_CODE_10 = BIT4, // 一击即中。当设置同步操作将只执行一次。当重置采样将触发在指定的时间,并在那里不断重复
+ SYNCHRONIZATION_OPERATION_CONTROL_CODE_80 = BIT7, // 操作已启用。当设置时,操作被启用。当动作是一个“一次性”,那么使能位在动作发生后被重置
+} synchronization_operation_control_code_e;
+
+// 5.42 实时时钟标志
+typedef enum
+{
+ REAL_TIME_CLOCK_FLAGS_1 = 1, // 非易失性时钟。当设置该设备包含一个电池支持时钟。在这种情况下,时钟不需要重置,如果有电源故障
+ REAL_TIME_CLOCK_FLAGS_2 = 2, // 未初始化时钟。实时时钟从未设置过日期和时间。例如,时钟是不稳定的,电源从设备中移除并恢复到设备中
+} real_time_clock_flags_e;
+
+// 5.54 SI单位控制代码
+typedef enum
+{
+ SI_UNITS_CONTROL_CODE_0 = 0x00, // 无限制(默认)
+ SI_UNITS_CONTROL_CODE_1 = 0x01, // 单位代码仅限于SI单位
+ SI_UNITS_CONTROL_CODE_MAX,
+} si_units_control_code_e;
+
+// 5.57 设备配置文件代码
+typedef enum
+{
+ // 过程自动化装置
+ DEVICE_CONFIGURATION_FILE_CODE_0 = 0x00,
+ // 分立器件
+ DEVICE_CONFIGURATION_FILE_CODE_1 = 0x01,
+ // 混合:过程自动化+离散
+ DEVICE_CONFIGURATION_FILE_CODE_3 = 0x03,
+ // I/O系统
+ DEVICE_CONFIGURATION_FILE_CODE_4 = 0x04,
+ // 分立适配器
+ DEVICE_CONFIGURATION_FILE_CODE_14 = 0x0E,
+ // HART-IP过程自动化装置
+ DEVICE_CONFIGURATION_FILE_CODE_65 = 0x41,
+ // HART-IP分立器件
+ DEVICE_CONFIGURATION_FILE_CODE_66 = 0x42,
+ // HART-IP混合型过程自动化+离散
+ DEVICE_CONFIGURATION_FILE_CODE_67 = 0x43,
+ // HART-IP输入输出系统
+ DEVICE_CONFIGURATION_FILE_CODE_68 = 0x44,
+ // 无线HART过程自动化装置
+ DEVICE_CONFIGURATION_FILE_CODE_129 = 0x81,
+ // Wireless HART分立器件
+ DEVICE_CONFIGURATION_FILE_CODE_130 = 0x82,
+ // 无线HART混合:过程自动化+离散
+ DEVICE_CONFIGURATION_FILE_CODE_131 = 0x83,
+ // Wireless HART网关
+ DEVICE_CONFIGURATION_FILE_CODE_132 = 0x84,
+ // 无线HART接入点
+ DEVICE_CONFIGURATION_FILE_CODE_140 = 0x8C,
+ // Wireless HART进程适配器
+ DEVICE_CONFIGURATION_FILE_CODE_141 = 0x8D,
+ // Wireless HART离散适配器
+ DEVICE_CONFIGURATION_FILE_CODE_142 = 0x8E,
+ // 支持无线HART的手持式/便携式维护工具
+ DEVICE_CONFIGURATION_FILE_CODE_144 = 0x90,
+} device_configuration_file_code_e;
+
+// 5.65 设备变量属性
+typedef enum
+{
+ DEVICE_VARIABLE_PROPERTY_FLAGS_0 = 0, // 可写入,设备变量被输入(例如,写入)到现场设备。
+ DEVICE_VARIABLE_PROPERTY_FLAGS_8 = BIT7, // 不可写入,正在模拟设备变量。如果没有在现场设备中计算设备变量,则不得设置此位(例如,设备变量是设定值或远程传感器值
+} device_variable_property_flags_e;
+
+// 5.66 呼叫控制
+typedef enum
+{
+ SQUAWK_CONTROL_CODE_0 = 0, // 关闭
+ SQUAWK_CONTROL_CODE_1 = 1, // 打开
+ SQUAWK_CONTROL_CODE_2 = 2, // 呼叫一次(在应答期间,请参阅设备特定文档)
+} squawk_control_code_e;
+
+// 5.67 事件管理器注册控制代码
+typedef enum
+{
+ EVENT_MANAGER_REGISTRATION_CONTROL_CODE_0 = 0, // 注册
+ EVENT_MANAGER_REGISTRATION_CONTROL_CODE_1 = 1, // 取消注册。事件管理器正在取消其注册重置
+ EVENT_MANAGER_REGISTRATION_CONTROL_CODE_2 = 2, // 重新设置。重置事件管理器注册。不管命令请求的来源是什么,在收到请求后,都不会注册事件管理器
+} event_manager_registration_control_code_e;
+// A-1 设备操作状态
+typedef enum
+{
+ // NONE
+ DEVICE_OPERATIONAL_STATE_0 = 0,
+ // 主变量超越极限PV已经超出了它的运行极限。
+ DEVICE_OPERATIONAL_STATE_1 = BIT0,
+ // 非主变量超越极限-A未映射到PV的设备变量超出其操作限制
+ DEVICE_OPERATIONAL_STATE_2 = BIT1,
+ // 回路电流饱和-回路电流已达到其上(或下) 端点限制,不能再增加(或减少)
+ DEVICE_OPERATIONAL_STATE_3 = BIT2,
+ // 回路电流固定1-环电流保持在一个固定的值,并没有响应进程的变化(不管)
+ DEVICE_OPERATIONAL_STATE_4 = BIT3,
+ // 更多状态可用-更多的状态信息可通过Command 48,读取额外的状态信息
+ DEVICE_OPERATIONAL_STATE_5 = BIT4,
+ // 冷启动-发生电源故障或设备重置(第一包发送完清除状态)
+ DEVICE_OPERATIONAL_STATE_6 = BIT5,
+ // 配置已更改-执行的操作更改了设备的配置
+ DEVICE_OPERATIONAL_STATE_7 = BIT6,
+ // 设备故障-设备检测到严重错误或故障,危及设备运行
+ DEVICE_OPERATIONAL_STATE_8 = BIT7,
+} device_operational_state_e;
+
+// 5.69 定位方法代码
+typedef enum
+{
+ LOCATION_METHOD_CODE_0 = 0, // 没有修复
+ LOCATION_METHOD_CODE_1 = 1, // GPS或标准定位服务(SPS)修复
+ LOCATION_METHOD_CODE_2 = 2, // 差分GPS定位
+ LOCATION_METHOD_CODE_3 = 3, // 精确定位服务(PPS)修复
+ LOCATION_METHOD_CODE_4 = 4, // 实时运动学(RTK)固定解
+ LOCATION_METHOD_CODE_5 = 5, // 实时动态(RTK)浮动解决方案
+ LOCATION_METHOD_CODE_6 = 6, // 估计航位推算
+ LOCATION_METHOD_CODE_7 = 7, // 手动输入模式
+ LOCATION_METHOD_CODE_8 = 8, // 仿真模式
+} location_method_code_e;
+
+// A-3 设备变量状态
+typedef union
+{
+ uint8_t data;
+ struct
+ {
+ uint8_t device_family_specific_status : 3, // 设备系列特定状态
+ more_device_variable_status_available : 1, // 更多的设备变量状态可用
+ limit_status : 2, // 极限状态
+ process_data_status : 2; // 过程数据状态
+ } bits;
+} device_variable_status_t;
+
+typedef enum
+{
+ // 常数
+ DEVICE_VARIABLE_STATUS_CONSTANT = 3,
+ // 高的
+ DEVICE_VARIABLE_STATUS_HIGHT_LIMIT = 2,
+ // 低的
+ DEVICE_VARIABLE_STATUS_LOW_LIMIT = 1,
+ // 不限
+ DEVICE_VARIABLE_STATUS_NO_LIMIT = 0,
+
+ // 好的
+ DEVICE_VARIABLE_STATUS_GOOD = 3,
+ // 手动/固定
+ DEVICE_VARIABLE_STATUS_MANUAL_FIXED = 2,
+ // 准确性差
+ DEVICE_VARIABLE_STATUS_POOR_ACCURACY = 1,
+ // 坏的
+ DEVICE_VARIABLE_STATUS_BAD = 0,
+} device_variable_status_e;
+
+// A-2 制造商设备特定状态文件
+typedef enum
+{
+ DEVICE_SPECIFIC_STATUS_0 = 0,
+ DEVICE_SPECIFIC_STATUS_1 = 1,
+} device_specific_status_e;
+#endif //__HART_COMMON_TABLES_SPECIFICATION_H__
diff --git a/User/hart/inc/hart_frame.h b/User/hart/inc/hart_frame.h
new file mode 100644
index 0000000..f6ac321
--- /dev/null
+++ b/User/hart/inc/hart_frame.h
@@ -0,0 +1,1229 @@
+/***
+ * @Author: xushenghao
+ * @Date: 2023-03-20 19:27:47
+ * @LastEditors: xushenghao
+ * @LastEditTime: 2023-03-30 00:29:48
+ * @FilePath: \hart\hart\inc\hart_frame.h
+ * @Description:
+ * @email:
+ * @Copyright (c) 2023 by xushenghao, All Rights Reserved.
+ */
+
+#ifndef __HART_FRAME_H_
+#define __HART_FRAME_H_
+#include "lib.h"
+#include "./hart_common_tables_specification.h"
+#include "./hart_frame_user.h"
+
+#ifndef LL_FLASH_PAGE_SIZE
+#define LL_FLASH_PAGE_SIZE (2 * 1024)
+#endif
+
+/*
+ flash : bank1 0x0800 0000 - 0x0800 FFFF
+ bank2 0x0801 0000 - 0x0801 FFFF
+ EEPROM : bank1 0x0808 0000 - 0x0808 0BFF
+ bank2 0x0808 0C00 - 0x0808 17FF
+ 6 Kbytes of data EEPROM with ECC
+ 在写入EEPROM 的时候,如果发生了串口中断,那么就很容易出问题
+*/
+
+// 内部调试开关,本地调试使用,上线后请根据需要设置
+#define HART_PROTOCOL_VERSION_SUPPORT_COMMAND 1U // hart版本指令检查 1:打开 0:关闭
+#define HART_REQUEST_ADDRESS_CHECK TRUE // 请求地址检查 TRUE:打开 FALSE:关闭
+
+// 国家代码
+#define COUNTRY_CODE_CN 86 // 中国
+#define MANUFACTURER_IDENTIFICATION_CODE MANUFACTURER_IDENTIFIER_GSDT // 制造商标识码
+// HART缓存区生命周期
+#define KEY_CACHE_TIME_SEC (30 * 1000)
+#define HART_INTERNAL (3U)
+
+#define HART_PROTOCOL_VERSION_5 5U // hart协议版本号5.0
+#define HART_PROTOCOL_VERSION_7 7U // hart协议版本号7.2
+
+#define HART_SHORT_ADDRESS 0x00 // 默认短地址
+#define HART_VARIABLE_UNITS_ALLOWED_CNT 4U // 变量单位允许数量
+
+#define HART_LONG_ADDRESS (((uint64_t)(EXTENDED_DEVICE_TYPE_GSDT_GPS2000) << 24) + (uint64_t)(0x000001)) // 默认长地址
+
+// 定时器检查周期
+#define HART_BYTE_INTERVAL_TIME 10U // 串口字节间隔周期
+#define HART_DATA_PARSE_TIME 257U // 数据解析周期
+
+// 从机参数宏定义
+#define HART_PREAMBLE 0xFF // 前导符
+#define HART_PREAMBLE_DEFAULT_LEN 5U // 前导符默认长度
+#define HART_BURST_FRAME 0x01 // 突发帧
+#define HART_STX_FRAME 0x02 // 请求帧, 主->从
+#define HART_ACK_FRAME 0x06 // 应答帧, 从->主
+#define HART_MASTER 0x01 // 主设备;第一主机
+#define HART_SLAVE 0x00 // 从设备;第二主机
+#define HART_DELIMITER_TYPE_SHORT 0x00 // 短帧类型
+#define HART_DELIMITER_TYPE_LONG 0x01 // 长帧类型
+#define HART_SHORT_ADDRESS_LEN 1U // 短帧格式地址长度
+#define HART_LONG_ADDRESS_LEN 5U // 长帧格式地址长度
+#define HART_SOLT_DEVICE_VARIABLE_LEN 8U // 插槽设备变量长度
+#define HART_DEVICE_VARIABLE_LEN 11 // 设备变量长度,统计device_key_e中的数值
+#define HART_DEVICE_CONSTANT_LEN 135 // 设备常数长度,统计device_key_e中的数值
+#define HART_DEVICE_STANDARD_VARIABLE_LEN 8 // 标准设备变量长度
+
+#define HART_ANALOG_CHANNEL_LEN ANALOG_CHANNEL_NUMBER_CODES_MAX // 模拟通道长度
+#define HART_INVALID_VALUE 0x7FA00000 // 无效值
+#define HART_SQUAWK_CONTROL_ONCE_TIME 0x02 // 一次性响应时间(秒)
+#define TREND_CONFIGURATIONS_LEN 1U // 趋势配置长度
+#define TREND_VALUES_LEN 12U // 趋势值长度
+#define SYNCHRONIZATION_OPERATION_LEN 1U // 同步操作长度
+#define SYNCHRONIZATION_OPERATION_COMMAND_DATA_LEN 4U // 同步操作命令数据长度
+#define BURST_MESSAGE_LEN HART_SOLT_DEVICE_VARIABLE_LEN // 突发消息长度
+#define BURST_MESSAGE_UPDATE_TIME_MAX 3600U // 突发消息更新时间最大值
+
+// 主机参数宏定义
+#define HART_IO_MAXIMUM_NUMBER_CARDS 1U // 最大卡数
+#define HART_IO_MAXIMUM_NUMBER_CHANNELS_CARD 1U // 每张卡最大通道数
+#define HART_IO_MAXIMUM_NUMBER_DEVICES_CHANNEL 1U // 每个通道最大设备数
+#define HART_IO_MAXIMUM_NUMBER_DELAY_RESPONSE 2U // 最大延迟响应数
+#define HART_IO_MAXIMUM_NUMBER_RETRY_COUNT 3U // 重试次数
+#define HART_IO_PRIMARY_MODE 1U // 主模式
+#define HART_IO_SECONDARY_MODE 0U // 辅助主模式
+
+// #define HART_USER_STORAGE_ADDRESS 20000U // 用户存储地址
+
+typedef enum
+{
+ // 无错误
+ HART_UART_NO_ERROR = BIT0,
+ // 奇偶校验错误中断
+ HART_UART_PARITY_ERROR = BIT1,
+ // 帧错误中断
+ HART_UART_FRAME_ERROR = BIT2,
+ // 噪声错误中断
+ HART_UART_NOISE_ERROR = BIT3,
+ // 溢出错误中断
+ HART_UART_OVERRUN_ERROR = BIT4,
+} hart_uarts_interupt_error_e; ///< UART中断错误枚举 和 uarts_interupt_error_e 定义一致
+
+// 结束:响应数据域结构
+
+typedef enum
+{
+ HART_STORAGE_PARAMS = 1,
+ HART_STORAGE_VARIABLE,
+ HART_STORAGE_CONSTANT,
+ HART_STORAGE_STANDARD_VARIABLE,
+ HART_STORAGE_SPECIFICATION_TABLE,
+} hart_storage_e;
+
+#pragma pack(1)
+
+// 响应数据域结构
+typedef union
+{
+ uint8_t version;
+ struct
+ {
+ uint8_t physical_signaling_code : 3; // 物理层信号编码
+ uint8_t hardware_revision : 5; // 硬件版本
+ } bits;
+} device_hardware_revision_u; // 硬件版本
+
+typedef union
+{
+ uint8_t data;
+ struct
+ {
+ uint8_t frame_type : 3; // 帧类型,1-突发模式(HART_BURST_FRAME),2-请求数据(HART_STX_FRAME), 6-应答数据(HART_ACK_FRAME)
+ uint8_t physical_layer : 2; // 物理层类型,0-异步,1-同步
+ uint8_t ext_bytes : 2; // 扩展字节数量,0-3
+ uint8_t addr_type : 1; // 地址类型,0-短帧,1-长帧
+ } bits;
+} hart_delimiter_u; // 定界符
+
+typedef union
+{
+ uint8_t data;
+
+ struct
+ {
+ uint8_t slave : 4; // 从机巡检地址 1-127
+ uint8_t reserved : 2; // 第四、五位必须置为0
+ uint8_t group : 1; // 成组模式,0-没有成组,1-从设备处于成组模式
+ uint8_t master : 1; // 主机地址,0-第二主机,1-第一主机
+ } bits;
+} hart_short_address_u; // 短帧地址格式:共1个字节(8位)
+
+typedef union
+{
+ uint40_t data;
+ struct
+ {
+ uint8_t reserved : 6;
+ uint8_t group : 1; // 成组模式,0-没有成组,1-从设备处于成组模式
+ uint8_t master : 1; // 主机地址,0-第二主机,1-第一主机
+ uint8_t slave[4]; // 设备的唯一标识符,共38位。均为0表示广播地址
+ } bits;
+} hart_long_address_u; // 长帧格式地址:共5个字节(40位)
+
+typedef struct
+{
+ hart_uarts_interupt_error_e uart_error; // UART错误
+ uint16_t rx_index; // 接收到的第几个字节
+} hart_uart_error_t;
+
+// hart命令码数据结构定义
+typedef struct
+{
+ uint8_t def;
+ uint16_t expanded_device_type; // 扩展设备类型
+ uint8_t m2s_preambles_limit_count; // 主机到从机前导符限制计数
+ uint8_t hart_revision; // HART协议版本
+ uint8_t device_revision; // 设备版本
+ uint8_t device_software_revision; // 设备软件版本
+ device_hardware_revision_u device_hardware_revision; // 硬件版本
+ uint8_t reserve; // 保留
+ uint24_t device_id; // 设备ID,长ID的后3个字节
+ // 以下V7版本才有
+ uint8_t s2m_response_preambles_count; // 从机到主机前导符计数
+ uint8_t last_device_variable_code; // 上一个设备变量,这表示应用程序应在现场设备中找到的最后一个设备变量代码(在执行Command 54时读取设备的变量)
+ uint16_t configuration_change_counter; // 配置被更新的次数
+ uint8_t extended_device_status; // 扩展设备状态,未指定的任何位都是未定义的,必须设置为零。
+ uint16_t manufacturer_identification_code; // 制造商标识码
+ uint16_t private_label_distributor_code; // 私有标签分销商代码
+ uint8_t device_profile; // 设备配置文件
+} hart_command_0_t; // 读取唯一标识命令
+typedef struct
+{
+ uint8_t unit; // 单位代码
+ float32 value; // 变量值
+} hart_command_1_t; // 读取主变量
+typedef struct
+{
+ float32 primary_variable_loop_current; // 主要回路电流(单位:毫安)
+ float32 primary_variable_percent_of_range; // 主要变量量程百分比
+} hart_command_2_t; // 读取环路电流和量程百分比
+typedef struct
+{
+ float32 primary_variable_loop_current; // 主要回路电流(单位:毫安)
+ uint8_t primary_variable_units_code; // 主要变量单位代码
+ float32 primary_variable; // 主要变量值
+ uint8_t secondary_variable_units_code; // 次要变量单位代码
+ float32 secondary_variable; // 次要变量值
+ uint8_t tertiary_variable_units_code; // 第三变量单位代码
+ float32 tertiary_variable; // 第三变量值
+ uint8_t quaternary_variable_units_code; // 第四变量单位代码
+ float32 quaternary_variable; // 第四变量值
+} hart_command_3_t; // 读取动态变量和环路电流
+typedef struct
+{
+ uint8_t poll_address; // 设备的轮询地址 V5
+
+ // 以下V7版本才有
+ uint8_t loop_current_mode; // 回路电流模式
+} hart_command_6_t; // 写入轮训地址
+typedef struct
+{
+ uint8_t poll_address; // 设备的轮询地址 V5
+
+ // 以下V7版本才有
+ uint8_t loop_current_mode; // 回路电流模式
+} hart_command_7_t; // 读取循环配置
+typedef struct
+{
+ uint8_t primary_variable_classification; // 主要变量分类
+ uint8_t secondary_variable_classification; // 次要变量分类
+ uint8_t tertiary_variable_classification; // 第三变量分类
+ uint8_t quaternary_variable_classification; // 第四变量分类
+} hart_command_8_t;
+
+typedef struct
+{
+ uint8_t slot0;
+ uint8_t slot1;
+ uint8_t slot2;
+ uint8_t slot3;
+ uint8_t slot4;
+ uint8_t slot5;
+ uint8_t slot6;
+ uint8_t slot7;
+} hart_command_9_req_t;
+
+typedef struct
+{
+ uint8_t code; // 设备变量代码(参见通用表5.34,设备变量代码表和适当的设备特定文件)
+ uint8_t classification; // 设备变量分类(参见通用表5.21)
+ uint8_t units_code; // 单位代码(请参阅通用表格规范5.2)
+ float32_u value; // 设备变量值
+ uint8_t status;
+} slot_device_variable_rsp_t;
+typedef struct
+{
+ uint8_t extended_field_device_status; // 扩展现场设备状态(参考通用表5.17,扩展现场设备状况)
+ slot_device_variable_rsp_t slot[HART_PACKED8_LEN];
+ uint32_t slot_data_timestamp; // 插槽0数据时间戳
+} hart_command_9_rsp_t;
+
+typedef union
+{
+ hart_command_9_req_t hart_command_9_req;
+ hart_command_9_rsp_t hart_command_9_rsp;
+} hart_command_9_t; // 读取具有状态的设备变量
+
+typedef struct
+{
+ uint8_t tag[HART_PACKED6_LEN]; // 标签
+} hart_command_11_t; // 读取与标签关联的唯一标识符
+
+typedef struct
+{
+ uint24_t pv_transducer_serial_number; // 主要变量传感器序列号
+ uint8_t pv_transducer_limits_and_minimum_span_units_code; // 主要变量传感器限制和最小跨度单位代码
+ float32_u pv_upper_transducer_limit; // 主要变量传感器上限
+ float32_u pv_lower_transducer_limit; // 主要变量传感器下限
+ float32_u pv_minimum_span; // 主要变量传感器最小跨度
+} hart_command_14_t; // 读取主变量传感器信息
+
+typedef struct
+{
+ uint8_t pv_alarm_selection_code; // 主要变量报警选择代码
+ uint8_t pv_transfer_function_code; // 主要变量传递函数代码
+ uint8_t pv_upper_and_lower_range_values_units_code; // 主要变量上限和下限值单位代码
+ float32_u pv_upper_range_value; // 主要变量上限值
+ float32_u pv_lower_range_value; // 主要变量下限值
+ float32_u pv_damping_value; // 主要变量阻尼值
+ uint8_t write_protect_code; // 写保护代码
+ uint8_t reserved; // 保留,必须设置250
+ uint8_t pv_analog_channel_flags; // 主要变量模拟通道标志
+} hart_command_15_t; // 读取设备信息
+
+typedef struct
+{
+ uint8_t message[HART_PACKED24_LEN]; // 设备消息24个字节,command17写入,command12读取
+} hart_command_17_t; // 消息
+
+typedef struct
+{
+ uint8_t tag[HART_PACKED6_LEN]; // 标签
+ uint8_t descriptor[HART_PACKED12_LEN]; // 描述符
+ uint8_t date[HART_DATE_LEN]; // 用于记录保存的日期代码
+} hart_command_18_t; // 标签、描述符、日期
+
+typedef struct
+{
+ uint8_t final_assembly_number[HART_PACKED3_LEN]; // 总装编号
+} hart_command_19_t;
+
+typedef struct
+{
+ uint8_t long_tag[HART_PACKED32_LEN]; // 长标签
+} hart_command_21_t; // 读取与标签关联的唯一标识符
+
+typedef struct
+{
+ uint16_t configuration_change_counter; // 配置被更新的次数
+} hart_command_38_t; // 重置配置更改标志
+
+typedef struct
+{
+ uint8_t slot_0; // 插槽0
+ uint8_t slot_1; // 插槽1
+ uint8_t slot_2; // 插槽2
+ uint8_t slot_3; // 插槽3
+} hart_command_33_t;
+
+typedef struct
+{
+ float32 pv_damping_value; // 主要变量阻尼值(以秒为单位)
+} hart_command_34_t;
+
+typedef struct
+{
+ uint8_t pv_upper_and_lower_range_values_units_code; // 主要变量上限值和下限值单位代码
+ float32 pv_upper_range_value; // 主要变量上限值
+ float32 pv_lower_range_value; // 主要变量下限值
+} hart_command_35_t;
+
+typedef struct
+{
+ uint8_t control_code; // 0 刻录EEPROM 1 恢复影子内存
+} hart_command_39_t;
+
+typedef struct
+{
+ float32 pv_fixed_current_level;
+} hart_command_40_t;
+
+typedef struct
+{
+ uint8_t pv_units_code; // 主要变量单位代码
+} hart_command_44_t;
+
+typedef struct
+{
+ float32 pv_loop_current_level;
+} hart_command_45_t;
+
+typedef struct
+{
+ float32 pv_loop_current_level;
+} hart_command_46_t;
+
+typedef struct
+{
+ uint8_t pv_transfer_function_code;
+} hart_command_47_t;
+
+typedef struct
+{
+ uint24_t pv_transducer_serial_number;
+} hart_command_49_t;
+
+typedef struct
+{
+ uint8_t device_ariables[4];
+} hart_command_51_t;
+
+typedef struct
+{
+ uint8_t device_ariable;
+} hart_command_52_t;
+
+typedef struct
+{
+ uint8_t device_ariable; // 设备变量代码,参考device_variable_code_e
+ uint8_t device_ariable_unit_code; // 设备变量单位代码
+} hart_command_53_t;
+
+typedef struct
+{
+ uint8_t device_ariable; // 设备变量代码
+} hart_command_54_t;
+
+typedef struct
+{
+ uint8_t device_ariable; // 设备变量代码
+ float32 damping_value; // 阻尼值(以秒为单位)
+} hart_command_55_t;
+
+typedef struct
+{
+ uint8_t device_ariable; // 设备变量代码
+ uint24_t serial_number; // 传感器序列号
+} hart_command_56_t;
+
+typedef struct
+{
+ uint8_t tag[HART_PACKED6_LEN]; // 单位标签6个字节
+ uint8_t descriptor[HART_PACKED12_LEN]; // 单位描述符12个字节
+ uint8_t date[HART_DATE_LEN]; // 单位日期3个字节
+} hart_command_58_t;
+
+typedef struct
+{
+ uint8_t s2m_preambles; // 从属设备向主设备发送响应消息时要发送的前导码数
+} hart_command_59_t;
+
+typedef struct
+{
+ uint8_t analog_channel_number_code; // 模拟通道编号代码
+} hart_command_60_t;
+
+typedef struct
+{
+ uint8_t slot0_analog_channel_number_code; // 插槽0模拟通道编号代码
+ uint8_t slot1_analog_channel_number_code; // 插槽1模拟通道编号代码
+ uint8_t slot2_analog_channel_number_code; // 插槽2模拟通道编号代码
+ uint8_t slot3_analog_channel_number_code; // 插槽3模拟通道编号代码
+} hart_command_62_t;
+
+typedef struct
+{
+ uint8_t analog_channel_number_code; // 模拟通道编号代码
+} hart_command_63_t;
+
+typedef struct
+{
+ uint8_t analog_channel_number_code; // 模拟通道编号代码
+ float32 damping_value; // 阻尼值(以秒为单位)
+} hart_command_64_t;
+
+typedef struct
+{
+ uint8_t analog_channel_number_code; // 模拟通道编号代码
+ uint8_t upper_and_lower_range_values_units_code; // 上限值和下限值单位代码
+ float32 upper_range_value; // 上限值
+ float32 lower_range_value; // 下限值
+} hart_command_65_t;
+
+typedef struct
+{
+ uint8_t analog_channel_number_code; // 模拟通道编号代码
+ uint8_t units_code; // 模拟通道单位代码
+ float32 fixed_analog_channel_level; // 固定模拟通道电平
+} hart_command_66_t;
+
+typedef struct
+{
+ uint8_t analog_channel_number_code; // 模拟通道编号代码
+ uint8_t units_code; // 模拟通道单位代码
+ float32 actual_analog_channel_level; // 实际模拟通道电平
+} hart_command_67_t;
+
+typedef struct
+{
+ uint8_t analog_channel_number_code; // 模拟通道编号代码
+ uint8_t units_code; // 模拟通道单位代码
+ float32 externally_measured_analog_channel_level; // 外部测量模拟通道电平
+} hart_command_68_t;
+
+typedef struct
+{
+ uint8_t analog_channel_number_code; // 模拟通道编号代码
+ uint8_t transfer_function_code; // 模拟通道传递函数代码
+} hart_command_69_t;
+
+typedef struct
+{
+ uint8_t analog_channel_number_code; // 模拟通道编号代码
+} hart_command_70_t;
+
+typedef struct
+{
+ uint8_t lock_code; // 锁定代码
+} hart_command_71_t;
+
+typedef struct
+{
+ uint8_t squawk_control_code; // Squawk控制代码
+} hart_command_72_t;
+
+typedef struct
+{
+ uint8_t card;
+ uint8_t channel;
+ uint8_t poll_address;
+} hart_command_75_t;
+
+typedef struct
+{
+ uint16_t command;
+ uint8_t payload_length;
+ uint8_t *command_payload;
+} hart_command_78_item_t;
+typedef struct
+{
+ uint8_t count;
+ uint8_t *item;
+} hart_command_78_t;
+
+typedef struct
+{
+ uint8_t device_ariable; // 设备变量代码
+ uint8_t device_ariable_command_code; // 设备变量命令代码
+ uint8_t device_ariable_unit_code; // 设备变量单位代码
+ float32 device_ariable_value; // 设备变量值
+ uint8_t status; // 状态
+} hart_command_79_t;
+
+typedef struct
+{
+ uint8_t device_ariable; // 设备变量代码
+} hart_command_80_t;
+
+typedef struct
+{
+ uint8_t device_ariable; // 设备变量代码
+} hart_command_81_t;
+
+typedef struct
+{
+ uint8_t device_ariable; // 设备变量代码
+ uint8_t trim_points; // 微调点
+ uint8_t units_code; // 单位代码
+ float32 value;
+} hart_command_82_t;
+
+typedef struct
+{
+ uint8_t device_ariable; // 设备变量代码
+} hart_command_83_t;
+
+typedef struct
+{
+ uint16_t identifier; // 子设备在IO系统中的索引
+} hart_command_84_t;
+
+typedef struct
+{
+ uint8_t card; // 卡索引
+ uint8_t channel; // 通道索引
+} hart_command_85_t;
+
+typedef struct
+{
+ uint16_t identifier; // 子设备在IO系统中的索引
+} hart_command_86_t;
+
+typedef struct
+{
+ uint8_t master_mode; // 主模式
+} hart_command_87_t;
+
+typedef struct
+{
+ uint8_t retry_count; // 重试计数
+} hart_command_88_t;
+
+typedef struct
+{
+ uint8_t time_set_code; // 时间集代码
+ uint8_t date[HART_DATE_LEN]; // 设置设备实时时钟的日期代码
+ uint32_t time; // 设置设备实时时钟的时间
+ uint16_t transmission_time; // 应设置为0。两个字节,以确保请求和响应占用相等的时间(补偿响应中响应代码和设备状态的传输时间
+} hart_command_89_t;
+
+typedef struct
+{
+ uint8_t trend_number; // 趋势编号
+} hart_command_91_t;
+
+typedef struct
+{
+ uint8_t trend_number; // 趋势编号
+ uint8_t trend_code; // 趋势控制代码
+ uint8_t device_variable_code; // 设备变量代码
+ uint32_t trend_sample_interval; // 趋势样本间隔(最大为2小时:每天一个趋势)
+} hart_command_92_t;
+
+typedef struct
+{
+ uint8_t trend_number; // 趋势编号
+} hart_command_93_t;
+
+typedef struct
+{
+ uint8_t action_number; // 行动编号
+} hart_command_96_t;
+
+typedef struct
+{
+ uint8_t action_number; // 行动编号
+ uint8_t action_control_code; // 动作控制 synchronization_operation_control_code_e
+ uint8_t device_variable_code; // 设备变量代码。如果操作执行命令,则设备变量代码必须设置为251,“NONE”。 device_key_e
+ uint16_t command_number; // 命令编号。如果操作是对设备变量进行采样,则命令编号必须设置为0xFFFF
+ uint8_t trigger_date[HART_DATE_LEN]; // 触发日期
+ uint32_t trigger_time; // 触发时间
+} hart_command_97_t;
+
+typedef struct
+{
+ uint8_t action_number; // 行动编号
+} hart_command_98_t;
+
+typedef struct
+{
+ uint8_t action_number; // 行动编号
+ uint16_t command_number; // 命令编号。
+ uint8_t command_data_length; // 命令数据长度
+ uint8_t command_data[SYNCHRONIZATION_OPERATION_COMMAND_DATA_LEN]; // 命令数据
+} hart_command_99_t;
+
+typedef struct
+{
+ uint8_t pv_alarm_selection_code; // 主要变量报警选择代码 alarms_code_e
+} hart_command_100_t;
+
+typedef struct
+{
+ uint8_t burst_message; // 突发消息
+} hart_command_101_t;
+
+typedef struct
+{
+ uint8_t burst_message; // 突发消息
+ uint16_t sub_device_index; // 子设备索引(索引0表示输入输出系统本身)
+} hart_command_102_t;
+
+typedef struct
+{
+ uint8_t burst_message; // 突发消息
+ uint32_t update_period_time; // 更新周期为1/32毫秒。更新周期不得超过3600秒
+ uint32_t max_update_period_time; // 更新周期为1/32毫秒。更新周期不得超过3600秒
+} hart_command_103_t;
+
+typedef struct
+{
+ uint8_t burst_message; // 突发消息
+ uint8_t burst_message_trigger_code; // 突发触发模式选择代码 burst_message_trigger_code_e
+ uint8_t device_variable_vlassification_for_trigger_level; // 触发电平的设备变量分类 device_variable_classification_code_e
+ uint8_t units_code; // 单位代码
+ float32 trigger_level; // 触发电平
+} hart_command_104_t;
+
+typedef struct
+{
+ uint8_t burst_message; // 突发消息
+} hart_command_105_t;
+
+typedef struct
+{
+ uint8_t solt_device_variable_codes[8];
+ uint8_t burst_message; // 突发消息
+} hart_command_107_t;
+
+typedef struct
+{
+ uint16_t country_code; // 国家代码
+ uint8_t si_units_control_code; // SI单位控制代码
+} hart_command_513_t;
+
+typedef struct
+{
+ uint8_t event_manager_registration_control_code;
+} hart_command_514_t;
+
+// 结束:hart命令码数据结构定义
+
+typedef union
+{
+ hart_command_6_t command_6; // 写入轮训地址
+ hart_command_9_t command_9; // 读取具有状态的设备变量
+ hart_command_11_t command_11; // 读取与标签关联的唯一标识符
+ hart_command_17_t command_17; // 写入消息
+ hart_command_18_t command_18; // 标签、描述符、日期
+ hart_command_19_t command_19; // 总装编号
+ hart_command_21_t command_21; // 读取与标签关联的唯一标识符
+ hart_command_21_t command_22; // 写长标签
+ hart_command_38_t command_38; // 重置配置更改标志
+ hart_command_33_t command_33; // 读取设备变量
+ hart_command_34_t command_34; // 写入主变量阻尼值
+ hart_command_35_t command_35; // 写入主变量范围值
+ hart_command_39_t command_39; // EEPROM控制
+ hart_command_40_t command_40; // 进入/退出固定电流模式
+ hart_command_44_t command_44; // 编写主变量单元
+ hart_command_45_t command_45; // 微调回路电流归零
+ hart_command_46_t command_46; // 微调回路电流增益
+ hart_command_47_t command_47; // 编写主变量传递函数
+ hart_command_49_t command_49; // 写入主变量传感器序列号
+ hart_command_51_t command_51; // 编写动态变量赋值
+ hart_command_52_t command_52; // 设置设备变量零
+ hart_command_53_t command_53; // 写入设备变量单位
+ hart_command_54_t command_54; // 读取设备变量信息
+ hart_command_55_t command_55; // 写入设备可变阻尼值
+ hart_command_56_t command_56; // 写入设备可变传感器序列号
+ hart_command_58_t command_58; // 编写单位标签、描述符、日期V5
+ hart_command_59_t command_59; // 写入从属设备到主设备响应前导符计数
+ hart_command_60_t command_60; // 写入模拟通道编号代码
+ hart_command_62_t command_62; // 读取模拟通道V5
+ hart_command_63_t command_63; // 读取模拟通道信息V5
+ hart_command_64_t command_64; // 写入模拟通道阻尼值V5
+ hart_command_65_t command_65; // 写入模拟通道上限值和下限值V5
+ hart_command_66_t command_66; // 写入模拟通道固定电平V5
+ hart_command_67_t command_67; // 写入模拟通道实际电平V5
+ hart_command_68_t command_68; // 外部测量模拟通道电平
+ hart_command_69_t command_69; // 写入模拟通道传递函数代码
+ hart_command_70_t command_70; // 读取模拟通道传递函数代码
+ hart_command_71_t command_71; // 写入锁定代码
+ hart_command_72_t command_72; // 写入Squawk控制代码
+ hart_command_75_t command_75; // 轮询子设备
+ hart_command_78_t command_78; // 读取聚合命令(需要动态内存,暂不实现)
+ hart_command_79_t command_79; // 写入设备变量
+ hart_command_80_t command_80; // 读取设备可变微调点
+ hart_command_81_t command_81; // 读取设备变量调整指南
+ hart_command_82_t command_82; // 写入设备可变微调点
+ hart_command_83_t command_83; // 重置设备变量调整
+ hart_command_84_t command_84; // 读取子设备标识摘要
+ hart_command_85_t command_85; // 读取I/O通道统计信息
+ hart_command_86_t command_86; // 读取子设备统计信息
+ hart_command_87_t command_87; // 写入主模式
+ hart_command_88_t command_88; // 写入重试计数
+ hart_command_89_t command_89; // 写入实时时钟
+ hart_command_91_t command_91; // 读取趋势数据
+ hart_command_92_t command_92; // 写入趋势控制
+ hart_command_93_t command_93; // 读取趋势控制
+ hart_command_96_t command_96; // 读取同步操作
+ hart_command_97_t command_97; // 配置同步操作
+ hart_command_98_t command_98; // 读取命令操作
+ hart_command_99_t command_99; // 配置命令操作
+ hart_command_100_t command_100; // 写入主要变量报警选择代码
+ hart_command_101_t command_101; // 读取子设备到突发消息映射
+ hart_command_102_t command_102; // 将子设备映射到突发信息
+ hart_command_103_t command_103; // 写入突发周期
+ hart_command_104_t command_104; // 写入突发触发器
+ hart_command_105_t command_105; // 读取突发模式配置
+ hart_command_107_t command_107; // 写入突发设备变量
+ hart_command_513_t command_513; // 编写国家代码
+ hart_command_514_t command_514; // 注册事件管理器
+
+ // 用户自定义
+ hart_user_command_req_data_u;
+
+} hart_command_req_data_u; // HART请求指令数据域
+
+typedef struct
+{
+ uint8_t delimiter_type; // 界定符类型: 0:短帧 1:长帧 默认1
+ uint8_t address[HART_LONG_ADDRESS_LEN]; // 短帧地址1个字节,长帧地址5个字节,上位机发送时从低位到高位填充,例如短地址:0x01,长地址:0x00 0x00 0x00 0x00 0x01
+ uint8_t command; // HART命令码
+ uint16_t expansion_command; // 扩展命令码
+ BOOL expansion; // 是否扩展命令
+ hart_command_req_data_u data; // 数据域
+ // 以下解析数据后填充
+ uint8_t data_length; // 数据域长度
+ uint8_t master; // 主机地址,0-第二主机,1-第一主机
+} hart_command_req_t; // 主机请求指令接口参数定义:hart_master_command_req
+
+typedef struct
+{
+ uint64_t uuid; // 唯一标识
+ uint32_t hart_cache_time; // hart缓存区寿命
+ hart_delimiter_u delimiter; // 分隔符
+ uint8_t address[HART_LONG_ADDRESS_LEN]; // 短帧地址1个字节,长帧地址5个字节,上位机发送时从低位到高位填充,例如短地址:0x01,长地址:0x00 0x00
+ uint8_t command; // HART命令码
+ uint16_t expansion_command; // 扩展命令码
+ // private:
+ BOOL expansion; // 是否扩展命令
+ uint8_t address_length; // 地址长度
+
+ response_communication_code_e code; // 回复状态码
+ uint8_t *payload;
+ uint8_t payload_length;
+ uint8_t uart_index; // 串口索引
+} hart_cache_t; // 缓存数据结构
+
+typedef struct
+{
+ uint8_t data[HART_RESPONSE_MAX_LEN]; // 回复数据缓冲区
+ uint16_t data_length; // 回复数据实际长度
+ uint8_t *data_p; // 回复数据指针
+ response_communication_code_e code; // 回复状态码
+ hart_cache_t cache_data; // 需要缓存的数据
+} hart_response_t; // 主机和从机回复数据结构
+
+typedef struct
+{
+ uint8_t alarm_selection_code; // 报警选择代码
+ uint8_t transfer_function_code; // 传递函数代码
+ float32 damping_value; // 阻尼值(以秒为单位)
+
+ uint8_t analog_channel_flags; // 模拟通道标志 analog_channel_code_e
+} device_attribute_t; // 设备属性
+
+typedef struct
+{
+ uint16_t stx; // 此设备接收的STX消息计数
+ uint16_t ack; // 从该设备发送的ACK消息计数
+ uint16_t back; // 从此设备发送的BACK消息计数
+} message_count_t;
+typedef struct
+{
+ uint24_t serial_number; // 传感器序列号
+ uint8_t limits_and_minimum_span_units_code; // 传感器限制和最小跨度单位代码
+ uint8_t upper_and_lower_range_values_units_code; // 上限值和下限值单位代码
+ float32_u upper_limit; // 传感器上限
+ float32_u lower_limit; // 传感器下限
+ float32_u minimum_span; // 传感器最小跨度
+} transducer_t; // 传感器
+typedef struct
+{
+ uint8_t trim_points; // 支持的微调点 trim_points_e
+ uint8_t units_code; // 单位代码
+ float32 value; // 微调点值
+ float32 lower; // 下端点值,单点值
+ float32 mini_lower; // 最小下微调点值(在低微调过程中,仪表不会接受低于此值的值)
+ float32 max_lower; // 最大下微调点值(在低微调过程中,仪表不会接受高于此值的值)
+ float32 upper; // 上端点值
+ float32 mini_upper; // 最小上微调点值(在高微调过程中,仪表不会接受低于此值的值)
+ float32 max_upper; // 最大上微调点值(在高微调过程中,仪表不会接受高于此值的值)
+ float32 mini_differential; // 最小差值(上边缘点和下边缘点之间可接受的最小差值)
+} trim_point_t; // 修正点
+typedef struct
+{
+ uint8_t code; // 模拟通道编号代码
+ uint8_t units_code; // 模拟通道单位代码
+ float32_u level; // 模拟通道电平
+ float32_u percent_range; // 模拟通道量程百分比
+ float32_u fixed_analog_channel_level; // 固定模拟通道电平 重启后恢复
+ float32_u actual_analog_channel_level; // 下端点值,实际模拟通道电平 重启后恢复
+ float32_u externally_measured_analog_channel_level; // 上端点值,外部测量的模拟通道电平 重启后恢复
+ device_attribute_t attribute; // 设备属性
+} analog_channel_t; // 模拟通道
+
+typedef struct
+{
+ uint8_t code; // 设备变量代码 device_key_e
+ uint8_t write_device_variable_command_code; // 写入设备变量命令代码 write_device_variable_command_code_e
+ uint8_t classification; // 设备变量分类 device_variable_classification_code_e
+ uint8_t family; // 设备变量家族 device_variable_family_code_e
+ uint8_t units_code; // 单位代码 transmission_function_code_e
+ uint8_t units_code_allow[HART_VARIABLE_UNITS_ALLOWED_CNT]; // 单位代码 transmission_function_code_e
+ uint8_t properties; // 设备变量属性,默认0,device_variable_property_flags_e
+ uint8_t alarm_code; // 报警代码,报警选择代码表示设备在错误条件下所采取的措施 alarms_code_e
+ uint32_t acquisition_period; // 采集周期,the Acquisition Period indicates the maximum period betweenDevice Variable updates
+ __IO void *value; // 变量值
+ device_variable_status_t status; // 设备变量状态
+ device_attribute_t attribute; // 设备属性
+ user_variable_t user_param; // 用户自定义
+
+ transducer_t transducer; // 传感器
+ trim_point_t trim_point; // 修正点
+} hart_device_variable_t; // 设备变量
+
+typedef struct
+{
+ uint8_t code; // 设备变量代码 device_key_e
+ uint8_t dynamic_variable_code; // 动态设备变量,不支持的动态变量返回250(未使用)作为分配的设备变量( Primary, Secondary, Tertiary, and Quaternary Variables)
+} hart_device_standard_variable_t; // 标准设备变量
+
+typedef struct
+{
+ uint8_t code; // 设备变量代码 device_key_e
+ uint8_t classification; // 设备变量分类 device_variable_classification_code_e
+ uint8_t family; // 设备变量家族 device_variable_family_code_e
+ uint8_t units_code; // 单位代码 transmission_function_code_e
+ __IO void *value; // 变量值
+ user_variable_t user_param; // 用户自定义
+} hart_device_constant_t; // 设备常数
+
+typedef struct
+{
+ uint8_t tag[HART_PACKED6_LEN]; // 单位标签6个字节
+ uint8_t descriptor[HART_PACKED12_LEN]; // 单位描述符12个字节
+ uint8_t date[HART_DATE_LEN]; // 单位日期3个字节
+} unit_device_t;
+
+typedef struct
+{
+ float32 latitude; // 纬度(度)正值表示北,负值表示南。绝对值不得大于90.0
+ float32 longitude; // 经度(度)正值表示东,负值表示西。绝对值不得大于180.0
+ float32 altitude; // 高于平均海平面的高度(米)。海平面以上数值为正,海平面以下数值为负
+ uint8_t location; // 选址方法/质量 location_method_code_e
+} position_t;
+typedef struct
+{
+ uint8_t time_set_code; // 时间集代码
+ uint8_t date[HART_DATE_LEN]; // 设置设备实时时钟的日期代码
+ uint32_t time; // 设置设备实时时钟的时间
+ uint16_t transmission_time; // 应设置为0。两个字节,以确保请求和响应占用相等的时间(补偿响应中响应代码和设备状态的传输时间
+ uint8_t rtc_flags; // 实时时钟标志
+} real_time_clock_t;
+
+typedef struct
+{
+ float32 value; // 趋势值
+ device_variable_status_t status; // 趋势值状态
+} trend_value_t;
+typedef struct
+{
+ uint8_t device_variable_code; // 设备变量代码 device_key_e
+ uint8_t device_variable_classification; // 设备变量分类 device_variable_classification_code_e
+ uint8_t device_variable_unit_code; // 设备变量单位代码 units_code_e
+ uint8_t trend_code; // 趋势控制代码 trend_control_code_e
+ uint32_t trend_sample_interval; // 趋势样本间隔(最大为2小时:每天一个趋势)
+
+ uint8_t trend_value_date[HART_DATE_LEN]; // 趋势值的日期戳
+ uint32_t trend_value_time; // 趋势值的时间戳
+ trend_value_t trend_values[TREND_VALUES_LEN];
+} trend_configuration_t; // 趋势配置
+
+typedef struct
+{
+ uint8_t action_control_code; // 动作控制 synchronization_operation_control_code_e
+ uint8_t device_variable_code; // 设备变量代码。如果操作执行命令,则设备变量代码必须设置为251,“NONE”。 device_key_e
+ uint16_t command_number; // 命令编号。如果操作是对设备变量进行采样,则命令编号必须设置为0xFFFF
+ uint8_t trigger_date[HART_DATE_LEN]; // 触发日期
+ uint32_t trigger_time; // 触发时间
+ uint8_t command_data_length; // 命令数据长度
+ uint8_t command_data[SYNCHRONIZATION_OPERATION_COMMAND_DATA_LEN]; // 命令数据
+} synchronization_operation_t; // 同步操作
+
+typedef struct
+{
+ uint8_t device_variable_code; // 设备变量代码 device_key_e
+} burst_message_slot;
+typedef struct
+{
+ uint8_t code; // 设备变量代码 device_key_e
+ uint8_t burst_message_trigger_code; // 突发触发模式选择代码 burst_message_trigger_code_e
+ uint8_t device_variable_vlassification_for_trigger_level; // 触发电平的设备变量分类 device_variable_classification_code_e
+ uint8_t units_code; // 单位代码 units_code_e
+ uint8_t burst_mode_control_code; // 突发模式控制代码 burst_mode_control_code_e
+ uint8_t command_number_expansion_flag; // 31(0x1F)-命令编号扩展标志 不清楚怎么用
+ uint16_t extended_command_number; // 扩展命令号
+ uint32_t update_period_time; // 更新周期为1/32毫秒。更新周期不得超过3600秒
+ uint32_t max_update_period_time; // 更新周期为1/32毫秒。更新周期不得超过3600秒
+ float32 trigger_level; // 触发电平
+} burst_message_t; // 突发消息
+
+typedef struct
+{
+ uint16_t init_flag; // 初始化标志
+ uint8_t poll_address; // 设备的轮询地址,地址1个字节
+ uint8_t long_address[HART_LONG_ADDRESS_LEN]; // 长帧地址5个字节,上位机发送时从低位到高位填充,例如短地址:0x01,长地址:0x00 0x00 0x00 0x00 0x01
+ uint8_t write_protect_code; // 写保护代码
+ uint8_t message[HART_PACKED32_LEN]; // 设备消息24个字节,command17写入,command12读取
+ uint8_t tag[HART_PACKED8_LEN]; // 标签8个字节
+ uint8_t long_tag[HART_PACKED32_LEN]; // 长标签32个字节
+ uint8_t descriptor[HART_PACKED16_LEN]; // 描述符16个字节
+ uint8_t date[HART_DATE_LEN]; // 用于记录保存的日期代码3个字节
+ uint8_t final_assembly_number[HART_PACKED3_LEN]; // 总装编号3个字节
+
+ uint8_t device_profile; // 设备配置文件
+ uint8_t device_revision; // 设备版本
+ uint8_t device_software_revision; // 设备软件版本,254,255保留
+ uint8_t s2m_preambles; // 从设备到主设备的响应前导码个数
+ uint16_t extended_device_type; // ?扩展设备类型
+ uint16_t manufacturer_identification_code; // 制造商标识码
+ uint16_t private_label_distributor_code; // 私有标签分销商代码
+ device_hardware_revision_u device_hardware_revision; // 硬件版本
+ unit_device_t unit_device; // 单位设备
+ // analog_channel_t analog_channel[HART_ANALOG_CHANNEL_LEN]; // 模拟通道
+ // 以下V7版本才有
+ uint16_t country_code; // 国家代码
+ uint8_t si_units_control_code; // SI单位控制代码
+ uint8_t loop_current_mode; // 回路电流模式
+ uint8_t lock_code; // 锁定代码,默认0
+ uint8_t event_manager_registration_control_code; // 事件管理器注册控制代码 event_manager_registration_control_code_e
+
+ burst_message_t burst_messages[BURST_MESSAGE_LEN]; // 突发消息 存储
+ uint16_t master_cfg_update_count; // 第一主机配置更新次数
+ uint16_t slave_cfg_update_count; // 第二主机配置更新次数
+ // trend_configuration_t trend_configurations[TREND_CONFIGURATIONS_LEN]; // 趋势配置
+ // synchronization_operation_t synchronization_operations[SYNCHRONIZATION_OPERATION_LEN]; // 同步操作
+} hart_storage_variable_t; // flash变量
+
+typedef struct
+{
+ uint8_t device_specific_status[HART_PACKED6_LEN]; // 设备特定状态 device_specific_status_e
+ uint8_t extended_device_status; // 实现:扩展设备状态 extended_device_status_e
+ uint8_t device_operating_mode; // 设备操作模式,所有设备必须在command48读取附加状态中为该字节返回0 operating_mode_codes_e
+ uint8_t standardized_status0; // 实现:标准化状态0 standardized_status0_e
+ uint8_t standardized_status1; // 标准化状态1 standardized_status1_e
+
+ // 根据费舍尔提交的文档上面48号指令下面的没有,下面的字段在7.2版本才有
+ // uint8_t analog_channel_saturated; // 模拟通道饱和 analog_channel_saturated_e
+ // uint8_t standardized_status2; // 标准化状态2 standardized_status2_e
+ // uint8_t standardized_status3; // 标准化状态3 standardized_status3_e
+ // uint8_t analog_channel_fixed; // 固定模拟通道 analog_channel_fixed_e
+ // uint8_t extended_device_specific_status[11]; // 设备特定状态 device_specific_status_e
+} additional_device_status_t; // 读取附加设备状态
+typedef struct
+{
+ BOOL reset; // 设备重启标志(应用层看到这个标志重启设备)
+ BOOL busy; // 设备自检过程中busy=TRUE,自检结束设置busy=FALSE
+ uint8_t communication_code; // 通讯状态码
+ uint8_t operational_state; // 设备操作状态 device_operational_state_e,该字段掉电不恢复
+ additional_device_status_t additional_device_status; // 附加设备状态
+ uint16_t additional_device_status_crc; // 附加设备状态crc校验码,设备初始化、设备状态也设置完成后,调用接口更新该字段记录设备状态初始值
+} hart_device_status_t; // 设备状态,所有状态位都是可选的,未指定的任何位都是未定义的,必须设置为零。
+
+typedef struct
+{
+ // 这里存放的都是动态变量
+} device_variable_dynamics_t; // 设备变量动态,开发人员对该结构体进行初始化
+
+typedef struct
+{
+ // 需要实时写入到FLASH中的变量,上电时需要从falsh中读取,在协议中被更新时需要写入到falsh中,地址HART_FLASH_ADDRESS
+ hart_storage_variable_t flash_variable; // flash变量 存储
+ hart_device_variable_t device_variable[HART_DEVICE_VARIABLE_LEN]; // 设备变量 存储
+ hart_device_constant_t device_constant[HART_DEVICE_CONSTANT_LEN]; // 设备常量 存储
+ hart_device_standard_variable_t device_standard_variable[HART_DEVICE_STANDARD_VARIABLE_LEN]; // 设备标准变量 存储
+
+ // 不需要写入到FLASH中的变量
+ uint8_t *hart_protocol_version; // hart协议版本号
+ float32 *actual_pv_current_level; // 实际PV电流水平,单位毫安
+ float32 pv_fixed_current_level; // 固定电流模式,值为0或设备重启后退出固定电流模式,单位毫安
+ float32 pv_loop_current_level; // 外部测量的PV回路电流水平,单位毫安
+ real_time_clock_t real_time_clock; // 实时时钟
+ hart_device_status_t device_status; // 设备状态,需要提供接口更新字段
+ // 指针映射到flash变量中
+ uint8_t *last_device_variable; // 上一个设备变量,这表示应用程序应在现场设备中找到的最后一个设备变量代码(在执行Command 54时读取设备的变量)
+ message_count_t message_count; // 消息计数
+
+ device_variable_dynamics_t dynamics; // 设备变量动态
+ uint16_t internal;
+
+ // 当前请求来自第一还是第二主机
+ uint8_t host;
+} hart_device_attribute_t; // 设备属性
+
+#pragma pack()
+
+// 主机属性定义
+#pragma pack(1)
+typedef struct
+{
+ uint16_t stx; // I/O系统在此通道上发送的STX消息的计数
+ uint16_t ack; // 接收到的ACK消息的计数
+ uint16_t ostx; // 接收到的OSTX消息的计数(来自其他主机的消息)
+ uint16_t oack; // 接收到的OACK消息的计数(对其他主机的答复)
+ uint16_t back; // 接收到的BACK消息计数(寻址到任一主机)
+} io_system_message_count_t;
+typedef struct
+{
+ uint16_t identifier; // 索引标识符
+ BOOL online; // 在线状态
+
+ uint16_t extended_device_type; // 扩展设备类型
+ uint8_t m2s_preambles_limit_count; // 主设备到从设备的最少同步前导码数量
+ uint8_t hart_revision;
+ uint8_t device_revision;
+ uint8_t device_software_revision;
+ device_hardware_revision_u device_hardware_revision;
+ uint8_t device_id[3];
+
+ // 以下版本7才有
+ uint8_t s2m_preambles; // 从设备到主设备的响应前导码个数
+ uint8_t last_device_variable; // 上一个设备变量,这表示应用程序应在现场设备中找到的最后一个设备变量代码(在执行Command 54时读取设备的变量)
+ uint16_t configuration_update_count; // 配置被更新的次数
+ uint8_t extended_device_status; // 扩展设备状态 extended_device_status_e
+ uint16_t manufacturer_identification_code; // 制造商标识码
+ uint16_t private_label_distributor_code; // 私有标签分销商代码
+ uint8_t device_profile; // 设备配置文件
+ uint8_t long_tag[HART_PACKED32_LEN]; // 长标签32个字节
+
+ io_system_message_count_t message_count; // 消息计数
+} io_system_device_t;
+
+typedef struct
+{
+ io_system_device_t devices[HART_IO_MAXIMUM_NUMBER_DEVICES_CHANNEL];
+ io_system_message_count_t message_count; // 消息计数
+} io_system_channel_t; // IO系统通道
+
+typedef struct
+{
+ io_system_channel_t channels[HART_IO_MAXIMUM_NUMBER_CHANNELS_CARD];
+} io_system_card_t; // IO系统卡
+typedef struct
+{
+ uint8_t write_protect_code; // 写保护代码
+ uint8_t retry_count; // 重试计数
+ uint16_t master_mode; // 主模式(0=辅助主模式;1=主模式)
+ io_system_card_t cards[HART_IO_MAXIMUM_NUMBER_CARDS];
+} io_system_t; // IO系统
+typedef struct
+{
+ io_system_t io_system; // IO系统
+} hart_master_attribute_t; // 主机属性
+
+#pragma pack()
+
+typedef void (*response_cb)(uint8_t uart_index, uint8_t *data, uint16_t len); // 回复消息接口回调定义
+typedef struct
+{
+ // 主从回复应答消息接口
+ response_cb response;
+
+ // 获取串口通讯错误长度
+ uint16_t (*uart_error_count)(uint8_t uart_index);
+
+ // 获取串口通讯错误
+ void (*uart_errors)(uint8_t uart_index, hart_uart_error_t *errors);
+
+ // 数据组包解析超时判断开始
+ void (*frame_data_parse_time_start)(uint16_t timer_period);
+
+ // 获取时间戳
+ uint32_t (*get_timestamp)(void);
+
+ // flash 读写接口
+ BOOL(*flash_read)
+ (hart_storage_e index, uint8_t *data);
+
+ BOOL(*flash_write)
+ (hart_storage_e index, uint8_t *data);
+
+ BOOL(*flash_read_item)
+ (hart_storage_e index, uint8_t item, uint8_t *data);
+
+ BOOL(*flash_write_item)
+ (hart_storage_e index, uint8_t item, uint8_t *data);
+
+ // 执行自检
+ void (*perform_self_test)(void);
+
+ // 设备重置
+ void (*device_reset)(void);
+
+ // 设备呼叫,0一直呼叫,1-255秒
+ void (*squawk_control)(BOOL open, uint8_t second);
+
+ // 技术人员按下一个特殊的按钮或按钮组合,指示从机应响应command74
+ BOOL(*armed)
+ (void);
+
+ // 用户自定义接口
+ BOOL(*user_common_event)
+ (hart_interface_user_event_e event, const void *const data);
+
+ // 属性初始化
+ void (*attribute_init)(void);
+ // 变量初始化
+ void (*variable_init)(void);
+ // 自定义属性初始化
+ void (*attribute_user_init)(void);
+
+ // 设置动态变量
+ BOOL(*set_dynamics)
+ (device_variable_dynamics_t *const dynamics);
+
+ // 设置实时时钟
+ void (*set_real_time_clock)(uint8_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t min, uint8_t sec);
+ void (*get_real_time_clock)(uint8_t *year, uint8_t *month, uint8_t *day, uint8_t *hour, uint8_t *min, uint8_t *sec);
+
+} hart_interface_t;
+
+extern BOOL (*hart_command_ptr_arr[HART_COMMAND_MAX])(const hart_command_req_t *const req, hart_response_t *resp); // 命令处理函数指针数组
+
+extern void hart_timer_interupt_cb(void);
+extern void hart_timer_start(uint16_t timer_period);
+extern BOOL hart_timeout_compare(void);
+extern uint16_t hart_uart_error_count(uint8_t uart_index); // 获取uart错误计数
+extern void hart_uart_errors(uint8_t uart_index, hart_uart_error_t *errors); // 获取uart错误
+extern void frame_data_parse_time_start(uint16_t timer_period); // 开始解析帧数据的计时
+extern uint32_t hart_get_timestamp(void); // 获取时间戳 // flash 写信号量更新
+extern BOOL hart_storage_write(hart_storage_e index, uint8_t *data); // flash 读写接口
+extern BOOL hart_storage_read(hart_storage_e index, uint8_t *data);
+extern BOOL hart_storage_write_item(hart_storage_e index, uint8_t item, uint8_t *data); // flash 读写接口
+extern BOOL hart_storage_read_item(hart_storage_e index, uint8_t item, uint8_t *data); // flash 读写接口
+extern void hart_perform_self_test(void); // 执行自检
+extern void hart_device_reset(void); // 设备重置
+extern void hart_squawk_control(BOOL open, uint8_t second); // 设备呼叫,0一直呼叫,1-255秒
+extern BOOL hart_armed(void); // 技术人员按下一个特殊的按钮或按钮组合,指示从机应响应command74
+extern void hart_set_real_time_clock(uint8_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t min, uint8_t sec); // 设置实时时钟
+extern void hart_get_real_time_clock(uint8_t *year, uint8_t *month, uint8_t *day, uint8_t *hour, uint8_t *min, uint8_t *sec); // 获取实时时钟
+extern BOOL hart_user_common_event(hart_interface_user_event_e event, const void *const data); // 用户自定义事件
+
+extern uint8_t hart_get_current_protocol_version(void); // 获取当前协议版本
+extern BOOL hart_is_support_command(uint16_t command); // 判断是否支持命令
+extern BOOL hart_is_write_command(uint16_t command); // 判断是否写命令
+
+extern void hart_frame_data_length_start(uint8_t **data_p); // 帧数据长度
+extern void hart_frame_data_length_end(uint8_t *data_p); // 帧数据长度
+extern BOOL hart_frame_data_length_check(uint8_t data_length, uint8_t data_structure_length, uint8_t *resp_code); // 数据域长度检查
+
+extern void hart_frame_response_code_start(uint8_t **data_p); // 响应码
+extern void hart_frame_response_communication_code(uint8_t code); // 通信响应码
+extern void hart_frame_slave_response_operate_code(hart_device_attribute_t *hart_device_attribute); // 从设备响应操作码
+extern void hart_frame_master_response_operate_code(void); // 主设备响应操作码
+
+extern BOOL is_broadcast_address(uint8_t *address, uint8_t len); // 判断是否广播地址
+extern void encode_ascii_6(const uint8_t *input, uint16_t input_length, uint8_t *output); // ASCII6编码
+extern void decode_ascii_6(const uint8_t *input, uint16_t input_length, uint8_t *output); // ASCII6解码
+extern void convert_time(uint32_t t, uint8_t *h, uint8_t *m, uint8_t *s);
+extern void convert_timestrap(uint32_t *t, uint8_t h, uint8_t m, uint8_t s, uint16_t ms);
+extern void covert_year_rtc(uint8_t *year); // 年份转换,HART的年份是从1900年开始的,如果要转换到标准的年份,需要加上1900。另外,HART的年份是一个字节,所以最大只能表示到2155年。
+extern void covert_rtc_year(uint8_t *year); // 将RTC的年份转换为HART的年份
+extern void covert_rtc_year_to_standard(uint16_t *year); // 将RTC的年份转换成标准的年份
+extern float32 covert_float(user_param_type_e data_type, void *data_p); // 转换浮点数
+
+extern void hart_cache_init(void); // 缓存消息初始化
+extern void hart_cache_add(hart_cache_t data); // 向缓存中添加数据
+extern void hart_cache_free(hart_cache_t *data); // 释放缓存数据
+extern hart_cache_t *hart_cache_get(uint64_t uuid); // 从缓存中获取数据
+extern void hart_cache_remove(uint64_t uuid); // 将指定的uuid对应的数据从缓存区移除
+extern void hart_cache_detection(void); // 检查HART缓存区是否存活
+
+INTERNAL_EXTERN void hart_execution_inspection_sem(void); // 执行自检信号量
+#endif //__HART_FRAME_H_
diff --git a/User/hart/inc/hart_frame_user.h b/User/hart/inc/hart_frame_user.h
new file mode 100644
index 0000000..4c7a9c6
--- /dev/null
+++ b/User/hart/inc/hart_frame_user.h
@@ -0,0 +1,361 @@
+#ifndef __HART_FRAME_USER_H__
+#define __HART_FRAME_USER_H__
+#include "lib.h"
+#include "hart_common_tables_specification.h"
+#if defined(__CC_ARM)
+#pragma anon_unions
+#endif
+
+#define HART_RESPONSE_MAX_LEN 254U // HART响应数据最大长度
+#define USER_PARAM_MAX_NUM 16U // 用户响应参数最大数量
+#define USER_RESPONSE_MAX_LEN USER_PARAM_MAX_NUM * 4 // 用户响应数据最大长度
+
+typedef enum
+{
+ USER_BYTE = DATA_TYPE_UINT8,
+ USER_WORD = DATA_TYPE_UINT16,
+ USER_UINT32 = DATA_TYPE_UINT32,
+ USER_FLOAT = DATA_TYPE_FLOAT,
+} user_param_type_e;
+
+typedef enum
+{
+ USER_READ_ONLY = 0,
+ USER_READ_WRITE = 1,
+ USER_WRITE,
+} user_param_access_e;
+
+typedef enum
+{
+ COMMAND_187_CLEAR_MORE_STATUS_BIT_AND_WRITE_PROTECT_OFF = 0, // 清除更多状态位并关闭写保护
+ // COMMAND_187_SET_PV_CLOSE_TO_LOWER_RANGE_VALUE = 1, // 将主变量设置为接近下限值
+ // COMMAND_187_SET_PV_TO_1_PERCENT_OF_RANGE = 2, // 将主变量设置为范围的1%
+ // COMMAND_187_SET_PV_TO_MID_SENSOR_RANGE = 3, // 将主变量设置为传感器范围的中间值
+ // COMMAND_187_SET_PV_CLOSE_TO_UPPER_TRANSDUCER_LIMIT = 4, // 将主变量设置为接近(但不超过)上限值
+ // COMMAND_187_SET_PV_BELOW_LOWER_TRANSDUCER_LIMIT = 5, // 将主变量设置为低于下限值
+ // COMMAND_187_SET_PV_ABOVE_UPPER_TRANSDUCER_LIMIT = 6, // 将主变量设置为高于上限值 / 将主变量设置为过高以重新归零
+ // COMMAND_187_SET_PV_TOO_LOW_TO_RE_ZERO = 7, // 将主变量设置为过低以重新归零
+ // COMMAND_187_SET_PV_EQUAL_TO_UPPER_TRANSDUCER_LIMIT = 8, // 将主变量设置为等于上限值
+ // COMMAND_187_SET_PV_TO_ZERO = 9, // 将主变量设置为0.0
+ COMMAND_187_SET_MORE_STATUS_AVAILABLE_STATUS_BIT = 10, // 请更改设备条件以设置“更多状态可用”状态位
+ COMMAND_187_PLACE_DEVICE_INTO_WRITE_PROTECT = 11, // 将设备置于写保护状态
+ COMMAND_187_RESET_IT_IN_COMMAND_48 = 13, // 请更改设备条件以重置命令48中设置的状态
+ // COMMAND_187_ENABLE_4_20MA_CURRENT_TEST = 14, // 开启4-20mA电流测试
+ // COMMAND_187_DISABLE_4_20MA_CURRENT_TEST = 15 // 关闭4-20mA电流测试
+} command_187_e;
+
+typedef enum
+{
+ HART_COMMAND_35_EVENT = HART_COMMAND_35, // 写入电流上下限
+ HART_COMMAND_44_EVENT = HART_COMMAND_44, // 写入设备变量单位
+ HART_COMMAND_53_EVENT = HART_COMMAND_53, // 写入主变量单位
+ HART_COMMAND_109_EVENT = HART_COMMAND_109, // 突发模式控制
+ HART_COMMAND_131_EVENT = HART_COMMAND_131, // 写入整定参数
+ HART_COMMAND_132_EVENT = HART_COMMAND_132, // 读取整定参数
+ HART_COMMAND_133_EVENT = HART_COMMAND_133, // 获取打开的文件信息
+ HART_COMMAND_134_EVENT = HART_COMMAND_134, // 读取文件
+ HART_COMMAND_135_EVENT = HART_COMMAND_135, // 写入文件
+ HART_COMMAND_136_EVENT = HART_COMMAND_136, // 读取/解除/写入EEPROM
+ HART_COMMAND_138_EVENT = HART_COMMAND_138, // 读取其他状态
+ HART_COMMAND_140_EVENT = HART_COMMAND_140, // 读取触发器定义的内容
+ HART_COMMAND_142_EVENT = HART_COMMAND_142, // 执行校准
+ HART_COMMAND_143_EVENT = HART_COMMAND_143, // 设置阀门序列号
+ HART_COMMAND_144_EVENT = HART_COMMAND_144, // 读取阀门序列号
+ HART_COMMAND_145_EVENT = HART_COMMAND_145, // 读取仪器序列号
+ HART_COMMAND_146_EVENT = HART_COMMAND_146, // 读取标准跨度信息
+ HART_COMMAND_147_EVENT = HART_COMMAND_147, // 读取设备等级
+ HART_COMMAND_149_EVENT = HART_COMMAND_149, // 设置仪器时间
+ HART_COMMAND_150_EVENT = HART_COMMAND_150, // 读取仪器时间
+ HART_COMMAND_151_EVENT = HART_COMMAND_151, // 读取版本信息
+ HART_COMMAND_153_EVENT = HART_COMMAND_153, // 读取校准记录
+ HART_COMMAND_154_EVENT = HART_COMMAND_154, // 设置仪器序列号
+ HART_COMMAND_155_EVENT = HART_COMMAND_155, // 执行诊断
+ HART_COMMAND_156_EVENT = HART_COMMAND_156, // 读取诊断状态
+ HART_COMMAND_157_EVENT = HART_COMMAND_157, // 停止诊断
+ HART_COMMAND_158_EVENT = HART_COMMAND_158, // 在线诊断测试
+ HART_COMMAND_162_EVENT = HART_COMMAND_162, // 设置气源气压/A口/B口
+ HART_COMMAND_164_EVENT = HART_COMMAND_164, // 读取规格表数据
+ HART_COMMAND_165_EVENT = HART_COMMAND_165, // 写入规格表数据
+ HART_COMMAND_167_EVENT = HART_COMMAND_167, // 写入操作日期和用户
+ HART_COMMAND_168_EVENT = HART_COMMAND_168, // 读取部分行程警报
+ HART_COMMAND_170_EVENT = HART_COMMAND_170, // 读取制造信息序列号
+ HART_COMMAND_187_EVENT = HART_COMMAND_187,
+ HART_COMMAND_200_EVENT = HART_COMMAND_200, // 读取制造信息序列号
+
+ HART_COMMAND_523_EVENT = HART_COMMAND_523, // 读取精简状态映射数组
+ HART_COMMAND_524_EVENT = HART_COMMAND_524, // 写入精简状态映射
+} hart_interface_user_event_e;
+
+typedef enum
+{
+ DVC_FILE_ID_CUSTOM_CHAR = 1, // 自定义数据特性
+ DVC_FILE_ID_DIAG_SCRIPT = 2, // 诊断脚本
+ DVC_FILE_ID_DIAG_DATA_BUFFER = 3, // 诊断数据缓冲区
+ DVC_FILE_ID_FACTORY_DEFAULTS = 5, // 出厂默认值
+ DVC_FILE_ID_PARAMETER_IMPORT = 20, // 参数导入
+} dvc_file_id_e;
+
+typedef enum
+{
+ EEPROM_COMMAND_WRITE = 1,
+ EEPROM_COMMAND_UNLOCK = 2,
+ EEPROM_COMMAND_READ = 3,
+} eeprom_lock_command_e;
+
+typedef enum
+{
+ EEPROM_STATE_UNLOCK = 0,
+ EEPROM_STATE_FLASH_APP_CODE = 1,
+ EEPROM_STATE_FLASH_BOOT_CODE = 3,
+ EEPROM_STATE_FLASH_TEMPCOMP = 5,
+ EEPROM_STATE_DIAGNOSTIOCS = 16,
+} eeprom_lock_state_e;
+
+#pragma pack(1)
+
+typedef struct
+{
+ uint8_t len;
+ user_param_type_e type;
+ user_param_access_e access;
+} user_variable_t;
+
+typedef struct
+{
+ uint8_t burst_mode; // 1:yes 0:no
+ uint8_t message_no; // 消息号
+} hart_command_109_t;
+
+typedef struct
+{
+ uint8_t pbuf[USER_PARAM_MAX_NUM];
+} hart_command_129_t;
+
+typedef struct
+{
+ uint8_t pbuf[USER_RESPONSE_MAX_LEN];
+} hart_command_130_t;
+
+typedef struct
+{
+ uint8_t tuning_type; // 整定类型
+ uint8_t tuning_data; // 整定数据
+} hart_command_131_t;
+
+typedef struct
+{
+ uint8_t pos_tuning_set; // 位置整定参数
+ uint8_t press_tuning_set; // 压力整定参数
+} hart_command_132_t;
+
+typedef struct
+{
+ uint8_t file_function; // 文件功能
+ uint8_t file_id; // 文件ID
+ uint16_t write_data_number; // 写数据个数
+} hart_command_133_t; // 命令133请求数据
+
+typedef struct
+{
+ dvc_file_id_e file_index;
+ uint16_t file_offset;
+ uint8_t read_length;
+} hart_command_134_t;
+
+typedef struct
+{
+ dvc_file_id_e file_index; // 文件编号
+ uint16_t address; // 起始地址
+ uint8_t pbuf[HART_PACKED128_LEN];
+} hart_command_135_t;
+
+typedef struct
+{
+ uint8_t sub_cmd; // 命令 eeprom_lock_command_e
+ uint8_t lock_type; // 锁类型
+} hart_command_136_t; // 读取/解除/写入EEPROM
+
+typedef struct
+{
+ uint16_t start_addr; // 起始地址
+ uint8_t read_data_len; // 读取数据长度
+} hart_command_140_t; // 命令140请求数据
+
+typedef struct
+{
+ write_protect_code_e protection_code;
+ uint16_t count;
+} hart_command_141_t;
+
+typedef struct
+{
+ uint8_t code;
+ uint8_t subcode;
+} hart_command_142_t;
+
+typedef struct
+{
+ uint8_t pbuf[HART_PACKED16_LEN];
+} hart_command_143_t;
+
+typedef struct
+{
+ uint8_t seed; // 参与Seed计算:随机数
+ uint16_t level; // 设备等级
+ uint8_t update_count; // 临时更新次数
+} hart_command_147_t; // 读取设备等级
+
+typedef struct
+{
+ uint32_t secs; // 校准时间
+} hart_command_149_t;
+
+typedef struct
+{
+ uint32_t secs; // 校准时间
+ uint32_t reserve; // 预留四位
+} hart_command_150_t;
+
+typedef struct
+{
+ uint8_t nvm_version; // NVM版本
+ uint8_t valvelink_version; // 上位机编译版本
+ uint8_t date[HART_PACKED3_LEN]; // 日期
+ uint8_t reserve[7]; // 保留
+} hart_command_151_t; // 读取版本信息
+
+typedef struct
+{
+ uint32_t calibration_time; // 校准时间
+ uint8_t control_byte; // 控制字节
+ uint8_t operator[HART_PACKED25_LEN]; // 操作员
+} hart_command_153_t; // 读取校准记录
+
+typedef struct
+{
+ uint8_t pbuf[HART_PACKED16_LEN];
+} hart_command_154_t;
+
+typedef struct
+{
+ uint8_t pbuf[HART_PACKED16_LEN];
+} hart_command_155_t;
+
+typedef struct
+{
+ uint8_t diagnostic_state; ///< 诊断状态
+} hart_command_156_t;
+
+typedef struct
+{
+ uint8_t diagnostic_type; ///< 诊断类型
+ uint8_t variable_code[HART_PACKED4_LEN]; ///< 设备变量,和HART中的设备变量有关系
+ uint8_t sampling_time; ///< 采集时间
+ uint16_t points; ///< 总数据点数
+} hart_command_158_t;
+
+typedef struct
+{
+ uint8_t press_type; // 压力类型,参考 pressure_type_e
+ uint8_t press_unit; // 压力单位,参考 press_unit_e
+ float32 press_value; // 压力值
+} hart_command_162_t;
+typedef struct
+{
+ uint16_t address; // 起始地址
+ uint8_t length; // 数据长度
+} hart_command_164_t;
+
+typedef struct
+{
+ uint16_t address; // 起始地址
+ uint8_t pbuf[HART_PACKED30_LEN]; // 数据
+} hart_command_165_t;
+
+typedef struct
+{
+ uint32_t operation_time; // 时间 4字节
+ uint8_t control_byte; // 控制字节
+ uint8_t operator[HART_PACKED25_LEN]; // 人员 25字节
+} hart_command_167_t; // 设置校准记录
+
+typedef struct
+{
+ uint8_t pbuf[HART_PACKED6_LEN];
+} hart_command_168_t; // 读取部分行程警报
+
+typedef struct
+{
+ uint8_t code; // 类别 0:制造主要信息 1:制造方案信息
+} hart_command_170_t; // 读取制造信息序列号
+
+typedef struct
+{
+ uint8_t code;
+} hart_command_187_t;
+
+typedef struct
+{
+ uint16_t start_addr; // 起始地址
+ uint16_t length; // 读取数据长度
+} hart_command_200_t; // 读取NVM非易失性存储器数据
+
+typedef struct
+{
+ uint8_t address;
+ uint8_t count; // 这里的长度不是字节,需要*0.5
+} hart_command_523_t;
+
+typedef struct
+{
+ hart_command_523_t;
+} hart_command_524_t;
+
+typedef union
+{
+ hart_command_109_t command_109; // 突发模式控制
+ hart_command_129_t command_129; // 读取用户自定义参数
+ hart_command_130_t command_130; // 写入用户自定义参数
+ hart_command_131_t command_131; // 写入整定参数
+ hart_command_133_t command_133; // 写入整定参数
+ hart_command_134_t command_134; // 读取文件
+ hart_command_135_t command_135; // 写入文件
+ hart_command_136_t command_136; // 读取/解除/写入EEPROM
+ hart_command_140_t command_140; // 读取触发器定义的内容
+ hart_command_141_t command_141; // 写保护
+ hart_command_142_t command_142; // 自整定
+ hart_command_143_t command_143; // 设置阀门序列号
+ hart_command_149_t command_149; // 设置仪器时间
+ hart_command_154_t command_154; // 设置仪器序列号
+ hart_command_155_t command_155; // 执行诊断
+ hart_command_156_t command_156; // 读取诊断状态
+ hart_command_158_t command_158; // 读取诊断状态
+ hart_command_162_t command_162; // 设置气源气压/A口/B口
+ hart_command_164_t command_164; // 读取规格表数据
+ hart_command_165_t command_165; // 写入规格表数据
+ hart_command_167_t command_167; // 写入操作日期和用户
+ hart_command_170_t command_170; // 读取制造信息序列号
+ hart_command_187_t command_187; // 测试指令
+ hart_command_200_t command_200; // 读取NVM非易失性存储器数据
+ hart_command_523_t command_523; // 读取压缩状态映射
+ hart_command_524_t command_524; // 写入压缩状态映射
+} hart_user_command_req_data_u; // 用户自定义请求指令数据域
+
+typedef struct
+{
+ uint8_t pbuf[HART_RESPONSE_MAX_LEN];
+ uint8_t len;
+} hart_user_rsp_t;
+
+typedef struct
+{
+ hart_user_command_req_data_u data; // 用户自定义请求指令数据域
+ uint8_t data_length; // 数据长度
+ response_communication_code_e code; // 响应通信代码
+ uint64_t uuid; // 唯一标识
+ hart_user_rsp_t rsp; // 用户自定义响应数据
+} hart_user_req_t;
+
+#pragma pack()
+
+#endif // __HART_FRAME_USER_H__
diff --git a/User/hart/inc/hart_storage.h b/User/hart/inc/hart_storage.h
new file mode 100644
index 0000000..37274b3
--- /dev/null
+++ b/User/hart/inc/hart_storage.h
@@ -0,0 +1,36 @@
+#ifndef __HART_STORAGE_H__
+#define __HART_STORAGE_H__
+
+// 下面的枚举顺序必须和数据结构中顺序一致,否则数据会错位
+typedef enum
+{
+ HPB_INIT_FLAG, // 初始化标志
+ HPB_POLL_ADDRESS, // 轮询地址
+ HPB_LONG_ADDRESS, // 长地址
+ HPB_WRITE_PROTECT_CODE, // 写保护代码
+ HPB_MESSAGE, // 设备消息
+ HPB_TAG, // 标签
+ HPB_LONG_TAG, // 长标签
+ HPB_DESCRIPTOR, // 描述符
+ HPB_DATE, // 日期代码
+ HPB_FINAL_ASSEMBLY_NUMBER, // 总装编号
+ HPB_DEVICE_PROFILE, // 设备配置文件
+ HPB_DEVICE_REVISION, // 设备版本
+ HPB_DEVICE_SOFTWARE_REVISION, // 设备软件版本
+ HPB_S2M_PREAMBLES, // 响应前导码个数
+ HPB_EXTENDED_DEVICE_TYPE, // 扩展设备类型
+ HPB_MANUFACTURER_IDENTIFICATION_CODE, // 制造商标识码
+ HPB_PRIVATE_LABEL_DISTRIBUTOR_CODE, // 私有标签分销商代码
+ HPB_DEVICE_HARDWARE_REVISION, // 硬件版本
+ HPB_UNIT_DEVICE, // 单位设备
+ HPB_COUNTRY_CODE, // 国家代码
+ HPB_SI_UNITS_CONTROL_CODE, // SI单位控制代码
+ HPB_LOOP_CURRENT_MODE, // 回路电流模式
+ HPB_LOCK_CODE, // 锁定代码
+ HPB_EVENT_MANAGER_REGISTRATION_CONTROL_CODE, // 事件管理器注册控制代码
+ HPB_BURST_MESSAGES, // 突发消息
+ HPB_MASTER_CFG_UPDATE_COUNT, // 主配置更新计数
+ HPB_SLAVE_CFG_UPDATE_COUNT, // 从配置更新计数
+} hart_params_table_e;
+
+#endif // __HART_STORAGE_H__
diff --git a/User/hart/lib/flow/README.md b/User/hart/lib/flow/README.md
new file mode 100644
index 0000000..f9fbfd2
--- /dev/null
+++ b/User/hart/lib/flow/README.md
@@ -0,0 +1,244 @@
+# flow_lib
+
+#### 介绍
+适用于嵌入式单片机的裸机程序微库,只占用你的rom 6个字节,是的,6个字节。颠覆式的设计思维,让你写代码的时候像flow(流水)一样丝滑,让你永远不用在为delay时cpu空转而烦恼,附加的超轻便的软件定时器让你轻松实现各种定时需求,另还有信号量的配方,让你任务间的同步像诗一样写意,并且能让你裸机程序效率提升百倍以上。
+
+#### 移植说明
+移植特别简单,flow_def.h有一个全局变量:
+```
+extern unsigned long flow_tick;
+```
+
+把这个变量放在你的某个硬件中断里去,这个硬件中断一定要是一直运行的,推荐RTC半秒中断,或者systick中断都可以。
+
+然后在flow.h里的第一行有个宏
+```
+#define FL_HARD_TICK (500) /* 系统硬件中断一次所需要的时间,单位ms */
+```
+
+把这里的值改成你的硬件中断一次所需的时间,单位是毫秒,比如你的flow_tick放在了一个500ms中断一次的rtc里,那么这里的宏FL_HARD_TICK的值就是500,具体中断设为多少取决于你的系统最短一次的延时的时间。
+
+假如我的最短延时需求是100ms,那么我就得给个100ms中断一次的硬件中断源,宏FL_HARD_TICK的值就是100,我就可以这样使用:
+```
+FL_LOCK_DELAY(fl, FL_CLOCK_SEC /10);
+```
+来延时100ms。
+
+#### 使用说明
+核心文件时flow.h,看这里的注释基本就会使用大部分功能。
+
+```
+#ifndef __FLOW_
+#define __FLOW_
+
+#include
+#include
+#include
+
+#define FL_HARD_TICK (500) /* 系统硬件中断一次所需要的时间,单位ms */
+#define FL_CLOCK_SEC (1000/FL_HARD_TICK) /* 一秒钟需要的tick,可以除也可以自行添加其它宏 */
+
+/**
+ * 初始化一个flow进程
+ */
+#define FL_INIT(fl) FLOW_INIT(fl)
+
+/**
+ * flow头,必须放在函数内的最前面
+ */
+#define FL_HEAD(fl) FLOW_HEAD(fl)
+
+/**
+ * flow尾,必须放在函数内的最后面
+ */
+#define FL_TAIL(fl) FLOW_TAIL(fl)
+
+/**
+ * 给进程加锁,直到judge为真,加锁期间一直放开cpu给其他进程使用
+ */
+#define FL_LOCK_WAIT(fl, judge) FLOW_LOCK_WAIT(fl, judge)
+
+/**
+ * 如果judge为真,就一直给进程加锁,加锁期间一直放开cpu给其他进程使用
+ */
+#define FL_LOCK_WHILE(fl, judge) FLOW_LOCK_WHILE(fl, judge)
+
+/**
+ * 退出该进程
+ */
+#define FL_EXIT(fl) FLOW_EXIT(fl)
+
+/**
+ * 无条件锁住进程一次,下次进来再接着往下运行
+ */
+#define FL_LOCK_ONCE(fl) FLOW_LOCK_ONCE(fl)
+
+/**
+ * 等待一个flow进程结束
+ */
+#define FL_WAIT_PROCESS_END(fl, process) FLOW_WAIT_PROCESS_END(fl, process)
+
+/**
+ * 等待一个flow子进程结束
+ */
+#define FL_WAIT_CHILD(fl, cfl, process) FLOW_WAIT_CHILD_PROCESS_END(fl, cfl, process)
+
+/**
+ * 给进程加锁,时长为time,加锁期间一直放开cpu给其他进程使用,time如果用FL_CLOCK_SEC来乘,那么time的单位就是s
+ * 此处time必须是常数
+ */
+#define FL_LOCK_DELAY(fl,time) FLOW_LOCK_DELAY(fl,time)
+
+/**
+ * 给进程加锁,时长为time,延时期间如果judge为真,就直接解锁进程
+ * 此处time必须是常数
+ */
+#define FL_LOCK_DELAY_OR_WAIT(fl,judge,time) FLOW_LOCK_DELAY_OR_WAIT(fl,judge,time)
+
+/**
+ * 初始化一个信号量
+ */
+#define FL_SEM_INIT(sem, count) FLOW_SEM_INIT(sem, count)
+
+/**
+ * 给进程加锁,直到有信号释放
+ */
+#define FL_LOCK_WAIT_SEM(f, sem) FLOW_LOCK_WAIT_SEM(f, sem)
+
+/**
+ * 给进程加锁,直到有信号或者超时,此处time可以为变量,其他的接口处time必须是常数
+ */
+#define FL_LOCK_WAIT_SEM_OR_TIMEOUT(fl, sem, time) FLOW_LOCK_WAIT_SEM_OR_TIMEOUT(fl, sem, time)
+
+/**
+ * 释放一个信号量
+ */
+#define FL_SEM_RELEASE(sem) FLOW_SEM_RELEASE(sem)
+
+/**
+ * 初始化一个软件定时器
+ */
+void fl_timer_set(struct flow_timer *t, unsigned long interval);
+
+/**
+ * 复位一个软件定时器
+ */
+void fl_timer_reset(struct flow_timer *t);
+
+/**
+ * 重启一个软件定时器
+ */
+void fl_timer_restart(struct flow_timer *t);
+
+/**
+ * 检测一个软件定时器是否超时,0为不超时,1为超时
+ */
+char fl_timer_timeout(struct flow_timer *t);
+
+/**
+ * 检测一个软件定时器还剩多少时间超时,单位为硬件tick,比如硬件tick 500ms中断一次,那么
+ * 返回的时间单位就是500ms
+ */
+unsigned long fl_hour_much_time(struct flow_timer *t);
+
+#endif /* __FLOW_ */
+```
+
+
+简单举个例子,先从需求说起,假如说你现在需要一个函数,这个函数的功能是每隔1s让你的led亮一次,正常设计的要么起个软件定时器或者硬件定时器,甚至状态机可以实现需求,但是都太low了,让我们看一下如何用flow库来实现这个函数。
+
+该函数格式如下:
+
+```
+char led_flash(struct flow *fl)
+{}
+```
+其中char、struct flow *fl是必备的。
+
+再来看看函数里面的内容格式:
+
+```
+char led_flash(struct flow *fl)
+{
+ FL_HEAD(fl);
+ FL_TAIL(fl);
+}
+```
+函数里面的FL_HEAD和FL_TAIL是使用flow库的所必须的宏,FL_HEAD(fl)放到函数的最前面,如果你的函数内部有变量定义的话放在变量定义的后面。而FL_TAIL(fl)是放在函数最后面一行的。
+
+基本格式有了,再来看下如何实现延时一秒呢?其实只用一个语句就OK。
+
+```
+char led_flash(struct flow *fl)
+{
+ FL_HEAD(fl);
+ FL_LOCK_DELAY(fl, FL_CLOCK_SEC * 1);
+ led_open();
+ FL_LOCK_DELAY(fl, FL_CLOCK_SEC * 1);
+ led_close();
+ FL_TAIL(fl);
+}
+```
+
+是的,你没看错,仅仅只需要FL_LOCK_DELAY(fl, FL_CLOCK_SEC * 1)这一个语句就OK,当执行到这个语句的时候该函数就会让出CPU权限,当延时时间到了之后,就会回来接着执行FL_LOCK_DELAY(fl, FL_CLOCK_SEC * 1)下面的语句。一直到FL_TAIL(fl),该函数就会结束任务,再也不会执行了,那么如果我们想让它一直循环执行呢?看下面:
+
+```
+char led_flash(struct flow *fl)
+{
+ FL_HEAD(fl);
+ while(1)
+ {
+ FL_LOCK_DELAY(fl, FL_CLOCK_SEC * 1);
+ led_open();
+ FL_LOCK_DELAY(fl, FL_CLOCK_SEC * 1);
+ led_close();
+ }
+ FL_TAIL(fl);
+}
+```
+看起来像不像个进程?其实也有点操作系统的样子了。。。
+
+光有这个函数也不行,还得进行一些额外的操作
+
+比如:
+
+```
+static struct flow fl_led; /* 1,定义一个struct flow变量给这个函数使用 */
+
+static char led_flash(struct flow *fl)
+{
+ FL_HEAD(fl);
+ led_init(); /* 这里还能解决你的初始化问题,这里的函数只会在开机时或者说进程第一次进来时运行一次,以后将永远不会运行。注意:如果放在
+ FL_HEAD(fl)前面,那么就是每次轮到这个进程运行的时侯就会运行一次,总之很灵活 */
+ while(1)
+ {
+ FL_LOCK_DELAY(fl, FL_CLOCK_SEC * 1);
+ led_open();
+ FL_LOCK_DELAY(fl, FL_CLOCK_SEC * 1);
+ led_close();
+ }
+ FL_TAIL(fl);
+}
+
+int main(void)
+{
+ FL_INIT(&fl_led); /* 2,初始化struct flow变量 */
+ while(1)
+ {
+ led_flash(&fl_led); /* 3,把led_flash进程放在main函数的while循环里 */
+ ...
+ }
+ return 0;
+}
+```
+经过以上3步,就可以实现进程之间的切换啦。然后想根据某个条件来锁住线程释放CPU的话,可以把里面的
+```
+FL_LOCK_DELAY(fl, FL_CLOCK_SEC * 1);
+```
+换成
+```
+FL_LOCK_WAIT(fl, judge);
+```
+当里面的judge为假时线程就一直锁住在这一行语句,当judge为真时就可以往下执行啦。同理可以完成很多其他的神奇功能,让你的cpu再也不空转啦,具体请看flow.h文件。。。。
+
+这个版本暂时先写这么多,先看看example.c。
diff --git a/User/hart/lib/flow/example.c b/User/hart/lib/flow/example.c
new file mode 100644
index 0000000..ef0ecc4
--- /dev/null
+++ b/User/hart/lib/flow/example.c
@@ -0,0 +1,28 @@
+#include "flow.h"
+
+/* 1,初始化一个struct flow变量 */
+static struct flow fl_led;
+
+static char led_flash(struct flow *fl)
+{
+ FL_HEAD(fl);
+ for (;;)
+ {
+ FL_LOCK_DELAY(fl, FL_CLOCK_SEC * 1U); /* 延时一秒 */
+ led_open();
+ FL_LOCK_DELAY(fl, FL_CLOCK_SEC * 1U); /* 延时一秒 */
+ led_close();
+ }
+ FL_TAIL(fl);
+}
+
+int main(void)
+{
+ FL_INIT(&fl_led);
+ for (;;)
+ {
+ led_flash(&fl_led);
+ // other_process();
+ }
+ return 0;
+}
diff --git a/User/hart/lib/flow/flow.h b/User/hart/lib/flow/flow.h
new file mode 100644
index 0000000..b4b93ea
--- /dev/null
+++ b/User/hart/lib/flow/flow.h
@@ -0,0 +1,130 @@
+/***
+ * @Author:
+ * @Date: 2023-04-17 10:51:38
+ * @LastEditors: xxx
+ * @LastEditTime: 2023-04-17 22:20:34
+ * @Description:
+ * @email:
+ * @Copyright (c) 2023 by xxx, All Rights Reserved.
+ */
+
+#ifndef __FLOW_
+#define __FLOW_
+
+#include "flow_def.h"
+#include "flow_core.h"
+#include "flow_sem.h"
+
+#define FL_HARD_TICK (10U) /* 系统硬件中断一次所需要的时间,单位ms */
+#define FL_CLOCK_SEC (1000U / FL_HARD_TICK) /* 一秒钟需要的tick,可以根据需求添加其他时间更短的宏 */
+#define FL_CLOCK_100MSEC (100U / FL_HARD_TICK)
+#define FL_CLOCK_10MSEC (FL_CLOCK_100MSEC / 10U)
+/**
+ * 初始化一个flow进程
+ */
+#define FL_INIT(fl) FLOW_INIT((fl))
+
+/**
+ * flow头,必须放在函数内的最前面
+ */
+#define FL_HEAD(fl) FLOW_HEAD((fl))
+
+/**
+ * flow尾,必须放在函数内的最后面
+ */
+#define FL_TAIL(fl) FLOW_TAIL((fl))
+
+/**
+ * 给进程加锁,直到judge为真,加锁期间一直放开cpu给其他进程使用
+ */
+#define FL_LOCK_WAIT(fl, judge) FLOW_LOCK_WAIT((fl), (judge))
+
+/**
+ * 如果judge为真,就一直给进程加锁,加锁期间一直放开cpu给其他进程使用
+ */
+#define FL_LOCK_WHILE(fl, judge) FLOW_LOCK_WHILE((fl), (judge))
+
+/**
+ * 退出该进程
+ */
+#define FL_EXIT(fl) FLOW_EXIT((fl))
+
+/**
+ * 无条件锁住进程一次,下次进来再接着往下运行
+ */
+#define FL_LOCK_ONCE(fl) FLOW_LOCK_ONCE((fl))
+
+/**
+ * 等待一个flow进程结束
+ */
+#define FL_WAIT_PROCESS_END(fl, process) FLOW_WAIT_PROCESS_END((fl), (process))
+
+/**
+ * 等待一个flow子进程结束
+ */
+#define FL_WAIT_CHILD(fl, cfl, process) FLOW_WAIT_CHILD_PROCESS_END((fl), (cfl), (process))
+
+/**
+ * 给进程加锁,时长为time,加锁期间一直放开cpu给其他进程使用,time如果用FL_CLOCK_SEC来乘,那么time的单位就是s
+ * 此处time必须是常数
+ */
+#define FL_LOCK_DELAY(fl, time) FLOW_LOCK_DELAY((fl), (time))
+
+/**
+ * 给进程加锁,时长为time,延时期间如果judge为真,就直接解锁进程
+ * 此处time必须是常数
+ */
+#define FL_LOCK_DELAY_OR_WAIT(fl, judge, time) FLOW_LOCK_DELAY_OR_WAIT((fl), (judge), (time))
+
+/**
+ * 初始化一个信号量
+ */
+#define FL_SEM_INIT(sem, count) FLOW_SEM_INIT((sem), (count))
+
+/**
+ * 给进程加锁,直到有信号释放
+ */
+#define FL_LOCK_WAIT_SEM(fl, sem) FLOW_LOCK_WAIT_SEM((fl), (sem))
+
+/**
+ * 给进程加锁,直到有信号或者超时,此处time可以为常数或者变量,其他的接口处time必须是常数
+ */
+#define FL_LOCK_WAIT_SEM_OR_TIMEOUT(fl, sem, time) FLOW_LOCK_WAIT_SEM_OR_TIMEOUT((fl), (sem), (time))
+
+/**
+ * 释放一个信号量
+ */
+#define FL_SEM_RELEASE(sem) FLOW_SEM_RELEASE((sem))
+
+/**
+ * 检测一个信号量是否被释放
+ */
+#define FL_SEM_IS_RELEASE(fl, sem) FLOW_SEM_IS_RELEASE((fl), (sem))
+
+/**
+ * 初始化一个软件定时器
+ */
+void fl_timer_set(struct flow_timer *t, unsigned long interval);
+
+/**
+ * 复位一个软件定时器
+ */
+void fl_timer_reset(struct flow_timer *t);
+
+/**
+ * 重启一个软件定时器
+ */
+void fl_timer_restart(struct flow_timer *t);
+
+/**
+ * 检测一个软件定时器是否超时,0为不超时,1为超时
+ */
+unsigned char fl_timer_timeout(struct flow_timer *t);
+
+/**
+ * 检测一个软件定时器还剩多少时间超时,单位为硬件tick,比如硬件tick 500ms中断一次,那么
+ * 返回的剩余时间就是500ms*n
+ */
+unsigned long fl_hour_much_time(struct flow_timer *t);
+
+#endif /* __FLOW_ */
diff --git a/User/hart/lib/flow/flow_core.c b/User/hart/lib/flow/flow_core.c
new file mode 100644
index 0000000..32bce03
--- /dev/null
+++ b/User/hart/lib/flow/flow_core.c
@@ -0,0 +1,46 @@
+/**
+ * @file flow_core.c
+ * @author xxx
+ * @date 2023-09-04 15:59:16
+ * @brief 任务流程
+ * @copyright Copyright (c) 2023 by xxx, All Rights Reserved.
+ */
+
+#include "flow.h"
+
+unsigned long flow_tick;
+
+void fl_timer_set(struct flow_timer *t, unsigned long interval)
+{
+ t->interval = interval;
+ t->start = flow_tick;
+}
+
+void fl_timer_reset(struct flow_timer *t)
+{
+ t->start += t->interval;
+}
+
+void fl_timer_restart(struct flow_timer *t)
+{
+ t->start = flow_tick;
+}
+
+unsigned char fl_timer_timeout(struct flow_timer *t)
+{
+ return ((flow_tick - t->start) >= t->interval) ? 1U : 0U;
+}
+
+unsigned long fl_hour_much_time(struct flow_timer *t)
+{
+ unsigned long time_len = t->start + t->interval;
+
+ if (time_len >= flow_tick)
+ {
+ return (time_len - flow_tick);
+ }
+ else
+ {
+ return 0U;
+ }
+}
diff --git a/User/hart/lib/flow/flow_core.h b/User/hart/lib/flow/flow_core.h
new file mode 100644
index 0000000..6c238fb
--- /dev/null
+++ b/User/hart/lib/flow/flow_core.h
@@ -0,0 +1,96 @@
+/**
+ * @file flow_core.h
+ * @author xxx
+ * @date 2023-09-04 15:59:16
+ * @brief 任务流程
+ * @copyright Copyright (c) 2023 by xxx, All Rights Reserved.
+ */
+
+#ifndef __FLOW_CORE_
+#define __FLOW_CORE_
+
+#include "flow_def.h"
+
+// 在定时器中断中调用
+#define FLOW_TICK_UPDATE() \
+ do \
+ { \
+ flow_tick++; \
+ } while (0);
+
+#define FLOW_INIT(f) ((f)->line = 0)
+
+#define FLOW_HEAD(f) \
+ { \
+ volatile char lock_once_flag = 0; \
+ switch ((f)->line) \
+ { \
+ case 0:
+
+#define FLOW_TAIL(f) \
+ } \
+ ; \
+ lock_once_flag = (f)->line = 0; \
+ return FLOW_END; \
+ } \
+ ;
+
+#define FLOW_LOCK_WAIT(f, judge) \
+ do \
+ { \
+ (f)->line = __LINE__; \
+ case __LINE__:; \
+ if (!(judge)) \
+ return FLOW_WAIT; \
+ } while (0)
+
+#define FLOW_LOCK_WHILE(f, judge) \
+ do \
+ { \
+ (f)->line = __LINE__; \
+ case __LINE__:; \
+ if (judge) \
+ return FLOW_WAIT; \
+ } while (0)
+
+#define FLOW_EXIT(f) \
+ do \
+ { \
+ (f)->line = 0; \
+ return FLOW_FINISH; \
+ } while (0)
+
+#define FLOW_LOCK_ONCE(f) \
+ do \
+ { \
+ lock_once_flag = 1; \
+ (f)->line = __LINE__; \
+ case __LINE__:; \
+ if (lock_once_flag) \
+ return FLOW_LOCK; \
+ } while (0)
+
+#define FLOW_WAIT_PROCESS_END(f, process) FLOW_LOCK_WHILE(f, (process) < FLOW_FINISH)
+
+#define FLOW_WAIT_CHILD_PROCESS_END(f, cf, process) \
+ do \
+ { \
+ FLOW_INIT((cf)); \
+ FLOW_WAIT_PROCESS_END((f), (process)); \
+ } while (0)
+
+#define FLOW_LOCK_DELAY(f, t) \
+ do \
+ { \
+ (f)->time = flow_tick; \
+ FLOW_LOCK_WAIT((f), ((flow_tick - (f)->time) >= (t))); \
+ } while (0)
+
+#define FLOW_LOCK_DELAY_OR_WAIT(f, judge, t) \
+ do \
+ { \
+ (f)->time = flow_tick; \
+ FLOW_LOCK_WAIT((f), ((judge) || ((flow_tick - (f)->time) >= (t)))); \
+ } while (0)
+
+#endif /* __FLOW_CORE_ */
diff --git a/User/hart/lib/flow/flow_def.h b/User/hart/lib/flow/flow_def.h
new file mode 100644
index 0000000..de7e1e2
--- /dev/null
+++ b/User/hart/lib/flow/flow_def.h
@@ -0,0 +1,44 @@
+/***
+ * @Author:
+ * @Date: 2023-04-17 10:51:38
+ * @LastEditors: xxx
+ * @LastEditTime: 2023-04-17 10:53:25
+ * @Description:
+ * @email:
+ * @Copyright (c) 2023 by xxx, All Rights Reserved.
+ */
+
+#ifndef __FLOW_DEF_
+#define __FLOW_DEF_
+
+// 机制状态
+#define FLOW_WAIT (0)
+#define FLOW_LOCK (1)
+#define FLOW_FINISH (2)
+#define FLOW_END (3)
+
+//
+struct flow
+{
+ unsigned long line;
+ unsigned long time;
+};
+
+//
+struct flow_timer
+{
+ unsigned long start;
+ unsigned long interval;
+};
+
+//
+struct flow_sem
+{
+ unsigned long count;
+ unsigned long time;
+};
+
+//
+extern unsigned long flow_tick;
+
+#endif /* __FLOW_DEF_ */
diff --git a/User/hart/lib/flow/flow_sem.h b/User/hart/lib/flow/flow_sem.h
new file mode 100644
index 0000000..87cb89c
--- /dev/null
+++ b/User/hart/lib/flow/flow_sem.h
@@ -0,0 +1,39 @@
+/***
+ * @Author:
+ * @Date: 2023-04-17 10:51:38
+ * @LastEditors: xxx
+ * @LastEditTime: 2023-04-17 22:20:58
+ * @Description:
+ * @email:
+ * @Copyright (c) 2023 by xxx, All Rights Reserved.
+ */
+
+#ifndef __FLOW_SEM_H__
+#define __FLOW_SEM_H__
+
+#include "flow_def.h"
+#include "flow_core.h"
+
+#define FLOW_SEM_INIT(s, c) ((s)->count = c)
+
+#define FLOW_LOCK_WAIT_SEM(f, s) \
+ do \
+ { \
+ FLOW_LOCK_WAIT(f, (s)->count > 0); \
+ --(s)->count; \
+ } while (0)
+
+#define FLOW_LOCK_WAIT_SEM_OR_TIMEOUT(f, s, t) \
+ do \
+ { \
+ (f)->time = flow_tick; \
+ (s)->time = (t); \
+ FLOW_LOCK_WAIT(f, (((s)->count > 0) || ((flow_tick - (f)->time) >= ((s)->time)))); \
+ if (((s)->count > 0) && ((flow_tick - (f)->time) < ((s)->time))) \
+ --(s)->count; \
+ } while (0)
+
+#define FLOW_SEM_RELEASE(s) (++(s)->count)
+
+#define FLOW_SEM_IS_RELEASE(f, s) (flow_tick - (f)->time) < ((s)->time)
+#endif /* __FLOW_SEM_H__ */
diff --git a/User/hart/lib/inc/aes.h b/User/hart/lib/inc/aes.h
new file mode 100644
index 0000000..7c2a92c
--- /dev/null
+++ b/User/hart/lib/inc/aes.h
@@ -0,0 +1,161 @@
+/*
+ ---------------------------------------------------------------------------
+ Copyright (c) 1998-2008, Brian Gladman, Worcester, UK. All rights reserved.
+
+ LICENSE TERMS
+
+ The redistribution and use of this software (with or without changes)
+ is allowed without the payment of fees or royalties provided that:
+
+ 1. source code distributions include the above copyright notice, this
+ list of conditions and the following disclaimer;
+
+ 2. binary distributions include the above copyright notice, this list
+ of conditions and the following disclaimer in their documentation;
+
+ 3. the name of the copyright holder is not used to endorse products
+ built using this software without specific written permission.
+
+ DISCLAIMER
+
+ This software is provided 'as is' with no explicit or implied warranties
+ in respect of its properties, including, but not limited to, correctness
+ and/or fitness for purpose.
+ ---------------------------------------------------------------------------
+ Issue 09/09/2006
+
+ This is an AES implementation that uses only 8-bit byte operations on the
+ cipher state.
+ */
+
+#ifndef AES_H
+#define AES_H
+
+#if 1
+#define AES_ENC_PREKEYED /* AES encryption with a precomputed key schedule */
+#endif
+#if 1
+#define AES_DEC_PREKEYED /* AES decryption with a precomputed key schedule */
+#endif
+#if 0
+#define AES_ENC_128_OTFK /* AES encryption with 'on the fly' 128 bit keying */
+#endif
+#if 0
+#define AES_DEC_128_OTFK /* AES decryption with 'on the fly' 128 bit keying */
+#endif
+#if 0
+#define AES_ENC_256_OTFK /* AES encryption with 'on the fly' 256 bit keying */
+#endif
+#if 0
+#define AES_DEC_256_OTFK /* AES decryption with 'on the fly' 256 bit keying */
+#endif
+
+#define N_ROW 4
+#define N_COL 4
+#define N_BLOCK (N_ROW * N_COL)
+#define N_MAX_ROUNDS 14
+
+typedef uint8_t return_type;
+
+/* Warning: The key length for 256 bit keys overflows a byte
+ (see comment below)
+*/
+
+typedef uint8_t length_type;
+
+typedef struct
+{
+ uint8_t ksch[(N_MAX_ROUNDS + 1) * N_BLOCK];
+ uint8_t rnd;
+} aes_context;
+
+/* The following calls are for a precomputed key schedule
+
+ NOTE: If the length_type used for the key length is an
+ unsigned 8-bit character, a key length of 256 bits must
+ be entered as a length in bytes (valid inputs are hence
+ 128, 192, 16, 24 and 32).
+*/
+
+#if defined(AES_ENC_PREKEYED) || defined(AES_DEC_PREKEYED)
+
+return_type aes_set_key(const uint8_t key[],
+ length_type keylen,
+ aes_context ctx[1]);
+#endif
+
+#if defined(AES_ENC_PREKEYED)
+
+return_type aes_encrypt(const uint8_t in[N_BLOCK],
+ uint8_t out[N_BLOCK],
+ const aes_context ctx[1]);
+
+return_type aes_cbc_encrypt(const uint8_t *in,
+ uint8_t *out,
+ int32_t n_block,
+ uint8_t iv[N_BLOCK],
+ const aes_context ctx[1]);
+#endif
+
+#if defined(AES_DEC_PREKEYED)
+
+return_type aes_decrypt(const uint8_t in[N_BLOCK],
+ uint8_t out[N_BLOCK],
+ const aes_context ctx[1]);
+
+return_type aes_cbc_decrypt(const uint8_t *in,
+ uint8_t *out,
+ int32_t n_block,
+ uint8_t iv[N_BLOCK],
+ const aes_context ctx[1]);
+#endif
+
+/* The following calls are for 'on the fly' keying. In this case the
+ encryption and decryption keys are different.
+
+ The encryption subroutines take a key in an array of bytes in
+ key[L] where L is 16, 24 or 32 bytes for key lengths of 128,
+ 192, and 256 bits respectively. They then encrypts the input
+ data, in[] with this key and put the reult in the output array
+ out[]. In addition, the second key array, o_key[L], is used
+ to output the key that is needed by the decryption subroutine
+ to reverse the encryption operation. The two key arrays can
+ be the same array but in this case the original key will be
+ overwritten.
+
+ In the same way, the decryption subroutines output keys that
+ can be used to reverse their effect when used for encryption.
+
+ Only 128 and 256 bit keys are supported in these 'on the fly'
+ modes.
+*/
+
+#if defined(AES_ENC_128_OTFK)
+void aes_encrypt_128(const uint8_t in[N_BLOCK],
+ uint8_t out[N_BLOCK],
+ const uint8_t key[N_BLOCK],
+ uint8_t o_key[N_BLOCK]);
+#endif
+
+#if defined(AES_DEC_128_OTFK)
+void aes_decrypt_128(const uint8_t in[N_BLOCK],
+ uint8_t out[N_BLOCK],
+ const uint8_t key[N_BLOCK],
+ uint8_t o_key[N_BLOCK]);
+#endif
+
+#if defined(AES_ENC_256_OTFK)
+void aes_encrypt_256(const uint8_t in[N_BLOCK],
+ uint8_t out[N_BLOCK],
+ const uint8_t key[2 * N_BLOCK],
+ uint8_t o_key[2 * N_BLOCK]);
+#endif
+
+#if defined(AES_DEC_256_OTFK)
+void aes_decrypt_256(const uint8_t in[N_BLOCK],
+ uint8_t out[N_BLOCK],
+ const uint8_t key[2 * N_BLOCK],
+ uint8_t o_key[2 * N_BLOCK]);
+#endif
+
+#endif
diff --git a/User/hart/lib/inc/clist.h b/User/hart/lib/inc/clist.h
new file mode 100644
index 0000000..d04158a
--- /dev/null
+++ b/User/hart/lib/inc/clist.h
@@ -0,0 +1,49 @@
+/**
+ * @file clist.h
+ * @author xxx
+ * @date 2023-08-08 23:18:15
+ * @brief 简单链表 使用方法 lib\examples\simple_clist.c
+ * @copyright Copyright (c) 2023 by xxx, All Rights Reserved.
+ */
+
+#ifndef __CLIST_H
+#define __CLIST_H
+#include "lib.h"
+typedef void *cnode;
+
+/// 链表中一个节点的结构体
+typedef struct CLIST_NODE
+{
+ cnode data; /// 值
+ struct CLIST_NODE *Next; /// 指向下一个结点
+} clist_node_t;
+
+void clist_init(clist_node_t **ppFirst); ///< 初始化 ,构造一条空的链表
+
+void clist_print(clist_node_t *First); ///< 打印链表
+
+uint32_t clist_node_count(clist_node_t *First); ///< 获取链表节点数
+
+void clist_push_back(clist_node_t **ppFirst, cnode data); ///< 尾部插入
+
+void clist_push_front(clist_node_t **ppFirst, cnode data); ///< 头部插入
+
+void clist_pop_back(clist_node_t **ppFirst); ///< 尾部删除
+
+void clist_pop_front(clist_node_t **ppFirst); ///< 头部删除
+
+void clist_insert_for_node(clist_node_t **ppFirst, clist_node_t *pPos, cnode data); ///< 给定结点插入,插入到结点前
+
+int32_t clist_insert(clist_node_t **ppFirst, int32_t Pos, cnode data); ///< 按位置插入
+
+void clist_erase_for_node(clist_node_t **ppFirst, clist_node_t *pPos); ///< 给定结点删除
+
+void clist_remove(clist_node_t **ppFirst, cnode data); ///< 按值删除,只删遇到的第一个
+
+void clist_remove_all(clist_node_t **ppFirst, cnode data); ///< 按值删除,删除所有的
+
+void clist_destroy(clist_node_t **ppFirst); ///< 销毁 ,需要销毁每一个节点
+
+clist_node_t *clist_find(clist_node_t *pFirst, cnode data); ///< 按值查找,返回第一个找到的结点指针,如果没找到,返回 NULL
+
+#endif //__CLIST_H
diff --git a/User/hart/lib/inc/cmac.h b/User/hart/lib/inc/cmac.h
new file mode 100644
index 0000000..7ff5585
--- /dev/null
+++ b/User/hart/lib/inc/cmac.h
@@ -0,0 +1,63 @@
+/**************************************************************************
+Copyright (C) 2009 Lander Casado, Philippas Tsigas
+
+All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files
+(the "Software"), to deal with the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimers. Redistributions in
+binary form must reproduce the above copyright notice, this list of
+conditions and the following disclaimers in the documentation and/or
+other materials provided with the distribution.
+
+In no event shall the authors or copyright holders be liable for any special,
+incidental, indirect or consequential damages of any kind, or any damages
+whatsoever resulting from loss of use, data or profits, whether or not
+advised of the possibility of damage, and on any theory of liability,
+arising out of or in connection with the use or performance of this software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS WITH THE SOFTWARE
+
+*****************************************************************************/
+
+#ifndef _CMAC_H_
+#define _CMAC_H_
+
+#include "aes.h"
+
+#define AES_CMAC_KEY_LENGTH 16
+#define AES_CMAC_DIGEST_LENGTH 16
+
+typedef struct _AES_CMAC_CTX
+{
+ aes_context rijndael;
+ uint8_t X[16];
+ uint8_t M_last[16];
+ uint32_t M_n;
+} AES_CMAC_CTX;
+
+// #include
+
+//__BEGIN_DECLS
+void AES_CMAC_Init(AES_CMAC_CTX *ctx);
+void AES_CMAC_SetKey(AES_CMAC_CTX *ctx, const uint8_t key[AES_CMAC_KEY_LENGTH]);
+void AES_CMAC_Update(AES_CMAC_CTX *ctx, const uint8_t *data, uint32_t len);
+// __attribute__((__bounded__(__string__,2,3)));
+void AES_CMAC_Final(uint8_t digest[AES_CMAC_DIGEST_LENGTH], AES_CMAC_CTX *ctx);
+// __attribute__((__bounded__(__minbytes__,1,AES_CMAC_DIGEST_LENGTH)));
+//__END_DECLS
+
+#endif /* _CMAC_H_ */
diff --git a/User/hart/lib/inc/cmd.h b/User/hart/lib/inc/cmd.h
new file mode 100644
index 0000000..735776a
--- /dev/null
+++ b/User/hart/lib/inc/cmd.h
@@ -0,0 +1,49 @@
+/**
+ * @file cmd.h
+ * @author xxx
+ * @date 2023-06-25 13:07:02
+ * @brief 命令解析器
+ * @copyright Copyright (c) 2023 by xxx, All Rights Reserved.
+ */
+
+#ifndef _CMD_H_
+#define _CMD_H_
+
+#define CMD_HASH 0xb433e5c6
+
+#if defined(__CC_ARM) || defined(__CLANG_ARM) /* ARM Compiler */
+#define SECTION(x) __attribute__((section(x)))
+#define CMD_USED __attribute__((used))
+
+#elif defined(__IAR_SYSTEMS_ICC__) /* IAR Compiler */
+#define SECTION(x) @x
+#define CMD_USED __root
+#else
+#error "not supported tool chain..."
+#endif
+
+typedef void (*cmd_handler)(void);
+
+typedef struct cmd
+{
+ const char *cmd;
+ const char *cmd_mess;
+ unsigned int hash;
+ cmd_handler handler;
+} cmd_t;
+
+/// 注册命令
+#define REGISTER_CMD(cmd, handler, desc) \
+ const char _register_##cmd##_cmd[] = #cmd; \
+ const char _register_##cmd##_desc[] = #desc; \
+ CMD_USED cmd_t _register_##cmd SECTION("CMDS") = \
+ { \
+ _register_##cmd##_cmd, \
+ _register_##cmd##_desc, \
+ (unsigned int)CMD_HASH, \
+ (cmd_handler)&handler};
+
+void cmd_init(void); ///< 初始化命令
+void cmd_parsing(char *str); ///< 命令解析
+
+#endif
diff --git a/User/hart/lib/inc/data_analysis.h b/User/hart/lib/inc/data_analysis.h
new file mode 100644
index 0000000..4ac52fe
--- /dev/null
+++ b/User/hart/lib/inc/data_analysis.h
@@ -0,0 +1,79 @@
+/**
+ * @file data_analysis.h
+ * @author xxx
+ * @date 2023-06-25 13:07:02
+ * @brief 处理传输层的数据
+ * @copyright Copyright (c) 2023 by xxx, All Rights Reserved.
+ */
+
+#ifndef COMPONENTS_COMMON_INCLUDE_DATA_ANALYSIS_H_
+#define COMPONENTS_COMMON_INCLUDE_DATA_ANALYSIS_H_
+#include "data_type_def.h"
+
+typedef enum
+{
+ DATA_1,
+ DATA_2,
+ DATA_MAX,
+} DataId_t; // 处理数据模块的个数,请根据实际情况修改
+
+#define DATA_NUM (DATA_MAX)
+
+#define DATA_BUF_RECV_SQQ_LEN 650u
+#define DATA_BUF_SEND_SQQ_LEN 0u
+
+#define DATA_SD_LEN_MAX 2
+#define DATA_LD_LEN_MAX 2
+#define DATA_ED_LEN_MAX 1
+
+typedef struct _data_reg_t_
+{
+ struct
+ {
+ uint8_t len;
+ uint8_t pos;
+ uint8_t data[DATA_SD_LEN_MAX];
+ BOOL valid; // 是否有效
+ } sd; // start delimiter
+
+ struct
+ {
+ uint8_t len;
+ uint8_t pos; // 偏移量,在wait_end_state中根据帧长去掉固定长度来判断是否是结束符
+ uint8_t little_endian;
+ BOOL valid; // 是否有效
+ } ld; // length describe
+
+ struct
+ {
+ uint16_t len_max;
+ uint16_t len_min;
+ } argu;
+
+ struct
+ {
+ uint8_t len;
+ uint8_t data[DATA_ED_LEN_MAX];
+ BOOL valid;
+ } ed;
+
+ BOOL echo_en;
+ void (*func_ptr)(void);
+} data_reg_t;
+
+typedef void (*data_interupt_cb_t)(uint8_t id, uint8_t ch); ///< 中断回调函数,数据从这里写入
+
+extern uint8_t data_read(uint8_t id, void *buffer, uint16_t len); ///< 读取数据
+
+extern void data_write(uint8_t id, uint8_t *const string, uint16_t len); ///< TODO 写入数据
+
+extern void lock_data(uint8_t data_id); ///< 锁定数据,防止中断写入数据
+
+extern void unlock_data(uint8_t data_id); ///< 解锁数据
+
+extern data_interupt_cb_t data_fsm_init(uint8_t data_id); ///< 初始化数据状态机
+
+extern BOOL data_reg(uint8_t id, data_reg_t reg); ///< 注册数据
+
+extern void data_unreg(uint8_t id); ///< 注销数据
+#endif /* COMPONENTS_COMMON_INCLUDE_DATA_ANALYSIS_H_ */
diff --git a/User/hart/lib/inc/data_type_def.h b/User/hart/lib/inc/data_type_def.h
new file mode 100644
index 0000000..db7d7be
--- /dev/null
+++ b/User/hart/lib/inc/data_type_def.h
@@ -0,0 +1,279 @@
+/***
+ * @Author:
+ * @Date: 2023-03-29 13:16:28
+ * @LastEditors: xxx
+ * @LastEditTime: 2023-03-30 00:34:11
+ * @Description:数据类型定义
+ * @email:
+ * @Copyright (c) 2023 by xxx, All Rights Reserved.
+ */
+
+#ifndef __DATA_TYPE_DEF_H_
+#define __DATA_TYPE_DEF_H_
+#include
+#ifndef PI
+#define PI (3.14159265358979323846f)
+#endif
+
+#ifndef TRUE
+#define TRUE 1
+#define FALSE 0
+#endif
+
+#ifndef OK
+typedef enum
+{
+ OK = 0,
+ FAIL = !OK,
+} state_e;
+#endif
+
+#ifndef __IO
+#define __IO volatile
+#endif
+
+typedef unsigned char BOOL; /* boolean data */
+typedef unsigned char bool_t; /* boolean data */
+
+#if !defined(__stdint_h) && !defined(_GCC_WRAP_STDINT_H)
+typedef unsigned char uint8_t;
+typedef unsigned short int uint16_t;
+typedef unsigned long int uint32_t;
+typedef unsigned long long uint64_t;
+
+typedef signed char int8_t;
+typedef signed short int int16_t;
+typedef signed long int int32_t;
+typedef long long int64_t;
+#endif
+
+typedef float float32;
+typedef double float64;
+
+#ifndef float32_t
+typedef float float32_t;
+#endif
+
+#ifndef float64_t
+typedef double float64_t;
+#endif
+
+#pragma pack(1)
+typedef struct
+{
+ uint8_t bs[3];
+} uint24_t;
+typedef struct
+{
+ uint8_t bs[5];
+} uint40_t;
+
+typedef union
+{
+ float32 f;
+ int32_t c;
+} float32_u;
+
+#pragma pack()
+
+typedef enum
+{
+ DATA_TYPE_INT8 = 0, // 8-bit signed integer
+ DATA_TYPE_UINT8, // 8-bit unsigned integer
+ DATA_TYPE_INT16, // 16-bit signed integer
+ DATA_TYPE_UINT16, // 16-bit unsigned integer
+ DATA_TYPE_INT32, // 32-bit signed integer
+ DATA_TYPE_UINT32, // 32-bit unsigned integer
+ DATA_TYPE_INT64, // 64-bit signed integer
+ DATA_TYPE_UINT64, // 64-bit unsigned integer
+ DATA_TYPE_FLOAT, // 32-bit floating point number
+ DATA_TYPE_DOUBLE, // 64-bit floating point number
+ DATA_TYPE_STRING, // string
+ DATA_TYPE_ARRAY, // array
+ DATA_TYPE_STRUCT, // structure
+ DATA_TYPE_UNION, // union
+ DATA_TYPE_ENUM, // enumeration
+ DATA_TYPE_POINTER, // pointer
+ DATA_TYPE_FUNCTION, // function
+ DATA_TYPE_VOID, // void
+ DATA_TYPE_MAX,
+} data_type_e;
+
+typedef uint16_t nwk_id_t;
+
+/**
+ * STANDARD BITS
+ */
+#ifndef BIT0
+#define BIT0 (0x01u)
+#define BIT1 (0x02u)
+#define BIT2 (0x04u)
+#define BIT3 (0x08u)
+#define BIT4 (0x10u)
+#define BIT5 (0x20u)
+#define BIT6 (0x40u)
+#define BIT7 (0x80u)
+#define BIT8 (0x0100u)
+#define BIT9 (0x0200u)
+#define BIT10 (0x0400u)
+#define BIT11 (0x0800u)
+#define BIT12 (0x1000u)
+#define BIT13 (0x2000u)
+#define BIT14 (0x4000u)
+#define BIT15 (0x8000u)
+#define BIT16 (0x00010000u)
+#define BIT17 (0x00020000u)
+#define BIT18 (0x00040000u)
+#define BIT19 (0x00080000u)
+#define BIT20 (0x00100000u)
+#define BIT21 (0x00200000u)
+#define BIT22 (0x00400000u)
+
+#define BIT_SET(x, b) x |= b // 置位
+#define BIT_CLR(x, b) x &= ~b // 清零
+#define BIT_IS_SET(x, b) ((x) & (b)) // 判断某一位是否为1
+#define BIT_IS_CLR(x, b) (!((x) & (b))) // 判断某一位是否为0
+
+#endif
+
+#ifndef BF
+/**
+ * @brief 从一个字节中提取指定位的值
+ * @return {*}
+ * @note
+ *> uint8_t num = 0x12; 二进制表示为00010010
+ *> uint8_t bit = 2; 提取第2位(从0开始计数)
+ *> uint8_t width = 1; 提取1位
+ *> uint8_t result = BF(num, bit, width); 结果为1
+ */
+#define BF(x, b, s) (((x) & (b)) >> (s))
+#endif
+
+#ifndef MIN
+/**
+ * @brief
+ * @return {*}
+ * @note
+ *> int num1 = 10;
+ *> int num2 = 20;
+ *> int result = MIN(num1, num2); // 结果为10
+ */
+#define MIN(n, m) (((n) < (m)) ? (n) : (m))
+#endif
+
+#ifndef MAX
+/**
+ * @brief
+ * @return {*}
+ * @note
+ *> int num1 = 10;
+ *> int num2 = 20;
+ *> int result = MAX(num1, num2); // 结果为20
+ */
+#define MAX(n, m) (((n) < (m)) ? (m) : (n))
+#endif
+
+#ifndef ABS
+/**
+ * @brief
+ * @return {*}
+ * @note
+ *> int num = -10;
+ *> int result = ABS(num); // 结果为10
+ */
+#define ABS(n) (((n) < 0) ? -(n) : (n))
+#endif
+
+#ifndef RANGE
+#define RANGE(x, a, b) (MIN(MAX(x, a), b))
+#endif
+
+/**
+ * @brief Macro to check if a value is between a minimum and maximum value (inclusive).
+ * @param x The value to check.
+ * @param min The minimum value.
+ * @param max The maximum value.
+ * @return Returns 1 if the value is between the minimum and maximum values (inclusive), 0 otherwise.
+ */
+#define IS_BETWEEN(x, min, max) ((x) >= min && (x) <= max)
+
+#define ARRAY_LEN(arr) (sizeof(arr)) / (sizeof(arr[0]))
+
+#define HI_UINT16(a) (((uint16_t)(a) >> 8) & 0xFF)
+#define LO_UINT16(a) ((uint16_t)(a) & 0xFF)
+
+#define HI_1_UINT32(a) (((uint32_t)(a) >> 24) & 0xFF)
+#define HI_2_UINT32(a) (((uint32_t)(a) >> 16) & 0xFF)
+#define HI_3_UINT32(a) (((uint32_t)(a) >> 8) & 0xFF)
+#define HI_4_UINT32(a) ((uint32_t)(a) & 0xFF)
+
+#define LO_1_UINT8(a) (uint8_t)((a) & 0xFF)
+#define LO_2_UINT8(a) (uint8_t)(((a) & 0xFF00) >> 8)
+#define LO_3_UINT8(a) (uint8_t)(((a) & 0xFF0000) >> 16)
+#define LO_4_UINT8(a) (uint8_t)(((a) & 0xFF000000) >> 24)
+
+// uint32小端转大端
+#define S2B_UINT32(a) \
+ (((uint32_t)(a) & 0xFF000000) >> 24) + (((uint32_t)(a) & 0x00FF0000) >> 8) + (((uint32_t)(a) & 0x0000FF00) << 8) + (((uint32_t)(a) & 0x000000FF) << 24)
+
+// uint32大端转小端
+#define B2S_UINT32(a) S2B_UINT32(a)
+
+// uint16小端转大端
+#define S2B_UINT16(a) ((((uint16_t)(a) & 0xFF00) >> 8) + (((uint16_t)(a) & 0x00FF) << 8))
+
+// uint16大端转小端
+#define B2S_UINT16(a) S2B_UINT16(a)
+
+#define BUILD_UINT16(loByte, hiByte) \
+ ((uint16_t)(((loByte) & 0x00FF) + (((hiByte) & 0x00FF) << 8)))
+
+// float32小端转大端
+static inline float32 S2B_FLOAT32(float fv)
+{
+ float32_u _f;
+ _f.f = fv;
+ _f.c = S2B_UINT32(_f.c);
+ return _f.f;
+}
+
+// float32大端转小端
+#define B2S_FLOAT32(a) S2B_FLOAT32(a)
+
+// 反序数组
+#define REVERSE_ARRAY(arr, len) \
+ do \
+ { \
+ uint8_t _tmp; \
+ uint16_t _i; \
+ for (_i = 0; _i < len / 2; _i++) \
+ { \
+ _tmp = arr[_i]; \
+ arr[_i] = arr[len - _i - 1]; \
+ arr[len - _i - 1] = _tmp; \
+ } \
+ } while (0);
+
+// 比较2个数组是否相等
+#define IsEqual(arr1, arr2, n) ({ \
+ int _equal = 1; \
+ for (int _i = 0; _i < n; _i++) \
+ { \
+ if (arr1[_i] != arr2[_i]) \
+ { \
+ _equal = 0; \
+ break; \
+ } \
+ } \
+ _equal; \
+})
+
+// ASSIC码转换为数字
+#define ASCII_TO_NUM(c) ((c) >= '0' && (c) <= '9' ? (c) - '0' : (c) - 'A' + 10)
+
+// 数字转换为ASSIC码
+#define NUM_TO_ASCII(x) ((x) < 10 ? (x) + '0' : (x) - 10 + 'A')
+
+#define FLOAT_TO_UINT16(x) (x * 8192 / 100 + 2048) ///> 浮点压缩uint16_t
+#define UINT16_TO_FLOAT(x) (100 * (x - 2048) / 8192) ///> uint16转浮点
+#endif /* __DATA_TYPE_DEF_H_ */
diff --git a/User/hart/lib/inc/debug.h b/User/hart/lib/inc/debug.h
new file mode 100644
index 0000000..e1745f0
--- /dev/null
+++ b/User/hart/lib/inc/debug.h
@@ -0,0 +1,21 @@
+/***
+ * @Author:
+ * @Date: 2023-04-04 08:13:11
+ * @LastEditors: xxx
+ * @LastEditTime: 2023-04-04 13:21:46
+ * @Description:
+ * @email:
+ * @Copyright (c) 2023 by xxx, All Rights Reserved.
+ */
+#ifndef __DEBUG_H
+#define __DEBUG_H
+#include "lib.h"
+
+/*形参*/
+#define _DBG_LINE_ , uint16_t line
+/*实参*/
+#define __DBG_LINE , __LINE__
+
+extern BOOL DBG_ASSERT(uint8_t cond _DBG_LINE_);
+
+#endif //__DEBUG_H
diff --git a/User/hart/lib/inc/filter.h b/User/hart/lib/inc/filter.h
new file mode 100644
index 0000000..de165d9
--- /dev/null
+++ b/User/hart/lib/inc/filter.h
@@ -0,0 +1,53 @@
+/**
+ * @file filter.h
+ * @author xxx
+ * @date 2023-08-08 22:59:46
+ * @brief
+ * @copyright Copyright (c) 2023 by xxx, All Rights Reserved.
+ */
+
+#ifndef __FILTER_H__
+#define __FILTER_H__
+#include "lib.h"
+
+typedef struct
+{
+ float32 x; // 卡尔曼滤波器的估计值
+ float32 a; // 状态转移矩阵(1,表示没有动态变化)
+ float32 h; // 观测矩阵(1,表示直接观测)
+ float32 q; // 过程噪声协方差
+ float32 r; // 观测噪声协方差
+ float32 p; // 估计误差协方差
+ float32 gain; // 卡尔曼增益
+
+ float32 change_max; // 允许的最大变化量,用于判断观测值是否异常
+} kalman_t; // 卡尔曼滤波器结构
+
+typedef struct
+{
+ BOOL fisrt_flag; // 第一次标志位
+ float32 alpha; // 滤波系数 0~1
+ float32 last_value; // 上次滤波结果
+} lpf_t; // 一阶低通滤波器
+
+typedef struct
+{
+ uint16_t size; // 滑动窗口大小
+ float32 *window; // 滑动窗口
+ volatile float32 sum; // 滑动窗口和
+ volatile float32 out; // 滤波结果
+ uint16_t index; // 滑动窗口索引
+} lpf_window_t; // 滑动窗口滤波器
+
+void kalman_init(kalman_t *cfg, float32 change_max);
+float32 kalman_update(kalman_t *cfg, float32 input);
+
+void lpf_init(lpf_t *cfg);
+float32 lpf_update(lpf_t *cfg, float32 input);
+void lpf_reset(lpf_t *cfg);
+
+void lpf_window_init(lpf_window_t *cfg, uint16_t size);
+void lpf_window_dinit(lpf_window_t *cfg);
+float32 lpf_window_update(lpf_window_t *cfg, float32 input);
+void lpf_window_reset(lpf_window_t *cfg);
+#endif // __FILTER_H__
diff --git a/User/hart/lib/inc/fsm.h b/User/hart/lib/inc/fsm.h
new file mode 100644
index 0000000..4bdb7b6
--- /dev/null
+++ b/User/hart/lib/inc/fsm.h
@@ -0,0 +1,307 @@
+#ifndef __FSM_H__
+#define __FSM_H__
+#include
+/* ----------------------- Defines ------------------------------------------*/
+// 用于快速识别出 STATE与STEP
+#define FSM_STATE(name) state_##name
+#define FSM_FUNCT(name) funct_##name
+
+// 数据类型定义区
+typedef signed char state;
+typedef long long step_ret;
+typedef void *AS_STEP_RETVAL;
+
+/*!
+ * @brief 状态机过程实现原型函数
+ * 设计状态机时需要按照这个模式写
+ *
+ * @param[in] void* 你所需要的任何参数
+ *
+ * @return 返回值 代表下一个状态
+ */
+typedef void *(*Procedure)(void *);
+
+typedef struct
+{
+ state ds; // 默认状态
+ state cs; // 当前状态
+ state ns; // 下个状态
+} SM_STATE;
+
+// 状态机 属性 定义
+typedef struct
+{
+ // 状态管理
+ SM_STATE st;
+
+ // 状态机跳转表
+ Procedure *procedures;
+
+ // 状态机数据区域
+ void *data;
+
+ // 错误处理(用于存放 状态 执行 的结果)
+ step_ret ret_ptr; // 状态 执行结果
+ void *err_ptr;
+ state err_flag;
+} FSM;
+
+/* ----------------------- Start function declaration -----------------------------*/
+
+/*!
+ * @brief 设置状态机的错误容器
+ *
+ * @param[in] fsm 状态机实例
+ *
+ * @param[in] err_var 容器
+ *
+ * @return 是/否
+ */
+static inline void set_err_var(FSM *fsm, void *err_var)
+{
+ if (!fsm)
+ return;
+ fsm->err_ptr = err_var;
+}
+
+/*!
+ * @brief 获取错误值容器(用于读取其中的内容)
+ *
+ * @param[in] fsm 状态机实例
+ *
+ * @return 是/否
+ */
+static inline void *get_err_var(FSM *fsm)
+{
+ return fsm->err_ptr;
+}
+
+/*!
+ * @brief 获取状态机 在 步进中是否遇到了错误。
+ *
+ * @param[in] fsm 状态机实例
+ *
+ * @return 是/否
+ */
+static inline state is_fsm_error(FSM *fsm)
+{
+ return fsm->err_flag;
+}
+
+/*!
+ * @brief 置 状态机 错误位
+ *
+ * @param[in] fsm 状态机实例
+ *
+ * @return 是/否
+ */
+static inline state set_fsm_error_flag(FSM *fsm)
+{
+ if (!fsm)
+ return -1;
+ fsm->err_flag = 1;
+ return 0;
+}
+
+/*!
+ * @brief 置 状态机 错误位
+ *
+ * @param[in] fsm 状态机实例
+ *
+ * @return 是/否
+ */
+static inline state clr_fsm_error_flag(FSM *fsm)
+{
+ if (!fsm)
+ return -1;
+ fsm->err_flag = 0;
+ return 0;
+}
+
+/*!
+ * @brief 为状态机添加 过程方法 序列
+ *
+ * @param[in] fsm 状态机实例
+ *
+ * @param[in] procedures 状态机的所有过程方法
+ *
+ */
+static inline void set_procedures(FSM *fsm, Procedure *procedures)
+{
+ if (fsm)
+ {
+ fsm->procedures = procedures;
+ fsm->st.cs = -1; // 执行run之前,当前状态是未定的
+ }
+}
+
+/*!
+ * @brief 配置状态机的数据域
+ *
+ * @param[in] fsm 状态机实例
+ *
+ * @param[in] data 状态机需要的数据域
+ *
+ */
+static inline void set_data_entry(FSM *fsm, void *data)
+{
+ if (fsm)
+ fsm->data = data;
+}
+
+/*!
+ * @brief 配置状态机的数据域
+ *
+ * @param[in] fsm 状态机实例
+ *
+ * @return 返回 状态机 数据域
+ *
+ */
+static inline void *get_data_entry(FSM *fsm)
+{
+ return fsm->data;
+}
+
+/*!
+ * @brief 让 状态机 步进一次
+ *
+ * @param[in] fsm 状态机实例
+ *
+ * @return 非负数 :代表 所成功执行的状态
+ * -1 : 失败
+ */
+static inline state run_state_machine_once(FSM *fsm)
+{
+ if (!fsm)
+ return -1;
+
+ // 切换到新状态
+ fsm->st.cs = fsm->st.ns;
+
+ // 跳转到下一个状态(状态 执行 结果 保存在 ret_ptr 中 )
+ fsm->ret_ptr = (step_ret)fsm->procedures[fsm->st.cs](fsm);
+
+ return fsm->st.cs;
+}
+
+/*!
+ * @brief 获取步进执行结果
+ *
+ * @param[in] fsm 状态机实例
+ *
+ * @return 是/否
+ */
+static inline step_ret *get_step_retval(FSM *fsm)
+{
+ return &fsm->ret_ptr;
+}
+
+/*!
+ * @brief 获取状态机的当前状态
+ *
+ * @param[in] fsm 状态机实例
+ *
+ * @return 当前状态
+ */
+static inline state get_curr_state(FSM *fsm)
+{
+ return fsm->st.cs;
+}
+
+/*!
+ * @brief 设置状态机默认状态
+ *
+ * @param[in] fsm 状态机实例
+ *
+ * @param[in] st 状态值
+ *
+ */
+static inline void set_default_state(FSM *fsm, state st)
+{
+ if (!fsm)
+ return;
+ fsm->st.ds = st;
+ fsm->st.ns = st;
+}
+
+/*!
+ * @brief 设置状态机的下次状态
+ *
+ * @param[in] fsm 状态机实例
+ *
+ * @param[in] st 状态值
+ *
+ */
+static inline void set_next_state(FSM *fsm, state st)
+{
+ if (fsm)
+ fsm->st.ns = st;
+}
+
+/*!
+ * @brief 获取状态机的下次状态
+ *
+ * @param[in] fsm 状态机实例
+ *
+ * @return 下一个状态
+ */
+static inline state get_next_state(FSM *fsm)
+{
+ return fsm->st.ns;
+}
+
+/*!
+ * @brief 将状态机设为默认状态
+ *
+ * @param[in] fsm 状态机实例
+ *
+ */
+static inline void init_state_machine(FSM *p)
+{
+ set_next_state(p, p->st.ds);
+ p->st.cs = -1; // 执行run之前,当前状态是未定的
+}
+
+/*!
+ * @brief 将状态机设为默认状态,同时清除错误状态
+ *
+ * @param[in] fsm 状态机实例
+ *
+ */
+static inline void reset_state_machine(FSM *p)
+{
+ if (!p)
+ return;
+ clr_fsm_error_flag(p);
+ init_state_machine(p);
+}
+
+/*!
+ * @brief 判断状态机是否在某个状态
+ *
+ * @param[in] fsm 状态机实例
+ *
+ * @param[in] st 状态值
+ *
+ * @return 是/否
+ */
+static inline state is_curr_state(FSM *fsm, state st)
+{
+ return fsm->st.cs == st;
+}
+
+/*!
+ * @brief 判断状态机是否即将进行某个状态
+ *
+ * @param[in] fsm 状态机实例
+ *
+ * @param[in] st 状态值
+ *
+ * @return 是/否
+ */
+static inline state is_next_state(FSM *fsm, state st)
+{
+ return fsm->st.ns == st;
+}
+
+#endif // __FSM_H__
diff --git a/User/hart/lib/inc/lib.h b/User/hart/lib/inc/lib.h
new file mode 100644
index 0000000..d4fdf1d
--- /dev/null
+++ b/User/hart/lib/inc/lib.h
@@ -0,0 +1,122 @@
+/***
+ * @Author:
+ * @Date: 2023-04-04 08:13:11
+ * @LastEditors: xxx
+ * @LastEditTime: 2023-04-04 10:13:21
+ * @Description:
+ * @email:
+ * @Copyright (c) 2023 by xxx, All Rights Reserved.
+ */
+
+#ifndef __LIB_H
+#define __LIB_H
+#include
+#include "data_type_def.h"
+#include "malloc.h"
+#include "data_analysis.h"
+#include "osel_arch.h"
+#include "debug.h"
+#include "sqqueue.h"
+#include "clist.h"
+
+#define INTERNAL_EXTERN extern
+
+#ifndef STM32
+#include "log.h"
+#else
+#define LOG_PRINT(fmt, ...) \
+ do \
+ { \
+ } while (0);
+#define LOG_ERR(fmt, ...) \
+ do \
+ { \
+ } while (0);
+#define LOG_HEX(data, len) \
+ do \
+ { \
+ } while (0);
+
+#endif
+
+#define EXIT(x) \
+ do \
+ { \
+ DBG_ASSERT(FALSE, __DBG_LINE); \
+ } while (0);
+
+////< 时间结构
+typedef union
+{
+ uint8_t data[6];
+ struct
+ {
+ uint8_t year;
+ uint8_t month;
+ uint8_t day;
+ uint8_t hour;
+ uint8_t minute;
+ uint8_t second;
+ } date;
+} date_time_t;
+
+typedef struct
+{
+ uint16_t year;
+ uint8_t month;
+ uint8_t day;
+} rtc_date_t;
+
+typedef struct
+{
+ uint8_t hour;
+ uint8_t minute;
+ uint8_t second;
+} rtc_time_t;
+
+typedef struct
+{
+ float32 x;
+ float32 y;
+} point_t;
+
+typedef struct
+{
+ float32 a;
+ float32 b;
+} linear_func_param_t;
+
+extern void assic_to_str(uint8_t *assic, uint8_t len, uint8_t *str); // ASCII码转字符串
+extern void get_cpu_id(uint32_t *id); // 获取CPU ID
+extern uint32_t cpu_encrypt(void); // CPU加密
+extern BOOL cpu_judge_encrypt(uint32_t cupid_encrypt); // CPU判断加密
+extern void version_split(uint8_t *version, uint8_t *hi, uint8_t *lo); // 版本号1.0拆解成1和0
+extern void reverse(uint8_t *buf, uint16_t len); // 反序数组
+extern BOOL is_in_array(uint16_t *arr, uint16_t len, uint16_t val); // 判断val是否在数组arr中
+extern BOOL is_same_value(uint8_t *buf, uint16_t len, uint8_t value); // 判断数组中的值是否都相等
+extern uint16_t crc16_compute(const uint8_t *const data, uint16_t length); // CRC16校验
+extern uint32_t crc32_compute(const uint8_t *const data, uint16_t length); // CRC32校验
+extern uint64_t crc64_compute(const uint8_t *const data, const uint16_t length); // CRC64校验
+extern uint8_t xor_compute(const uint8_t *const data, uint16_t length); // 异或校验
+extern uint8_t get_bit_num(uint8_t bit); // 获取bit位的值
+extern BOOL is_bit_set(int x, int k); // 判断x的第k位是否为1
+extern uint8_t is_leap_year(uint16_t year); // 检查是否是闰年
+extern uint32_t days_since_1970(uint16_t year, uint8_t month, uint8_t day); // 计算从1970年1月1日到给定年月日的天数
+extern uint32_t date_to_seconds(uint16_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t minute, uint8_t second); // 将日期转换为秒数
+extern void seconds_to_date(uint32_t total_seconds, rtc_date_t *date, rtc_time_t *time); // 将秒数转换为日期
+extern uint16_t dayOfyear(uint16_t year, uint8_t month, uint8_t day); // 计算一年中的第几天
+extern uint16_t weekOfyear(uint16_t year, uint8_t month, uint8_t day); // 计算一年中的第几周
+extern uint8_t get_weekday(uint16_t year, uint8_t month, uint8_t day); // 获取今天星期几
+extern uint8_t hex_format_dec(uint8_t hex); // 十六进制转十进制
+extern uint8_t dec_format_hex(uint8_t dec); // 十进制转十六进制
+extern void quicksort(uint16_t arr[], int low, int high); // 快速排序
+extern void insertion_sort(uint16_t arr[], uint16_t n); // 插入排序
+
+extern uint32_t time2stamp(const rtc_date_t *const date, const rtc_time_t *const time); // 日期时间转时间戳
+extern void stamp2time(uint32_t stamp, rtc_date_t *date, rtc_time_t *time); // 时间戳转北京时间
+extern void convert_seconds(uint32_t total_seconds, char *date); // 秒数转换成时分秒
+extern void add_commas(uint32_t num, char *result); // 数字添加逗号
+
+extern linear_func_param_t calculate_linear_regression(const point_t *points, int32_t count); // 计算线性回归
+extern float32 get_linearity_value(const point_t *points, int32_t count, linear_func_param_t param); // 获取线性度
+#endif //__LIB_H
diff --git a/User/hart/lib/inc/log.h b/User/hart/lib/inc/log.h
new file mode 100644
index 0000000..802ba9f
--- /dev/null
+++ b/User/hart/lib/inc/log.h
@@ -0,0 +1,45 @@
+/***
+ * @Author:
+ * @Date: 2023-03-20 19:27:47
+ * @LastEditors: xxx
+ * @LastEditTime: 2023-03-30 00:34:41
+ * @Description:日志打印模块PC端调试使用
+ * @email:
+ * @Copyright (c) 2023 by xxx, All Rights Reserved.
+ */
+
+#ifndef __LOG_H_
+#define __LOG_H_
+#include
+#include
+
+#define __FILENAME__ (strrchr(__FILE__, '/') ? (strrchr(__FILE__, '/') + 1) : __FILE__)
+
+/*调试日志宏定义*/
+
+#define LOG_PRINT(fmt, ...) \
+ do \
+ { \
+ printf("[DEBUG:%s][%s:%d] " fmt "\n", __FILENAME__, __FUNCTION__, __LINE__, ##__VA_ARGS__); \
+ } while (0);
+
+/*错误日志打印(在日志打印模块还未启动时使用)*/
+#define LOG_ERR(fmt, ...) \
+ do \
+ { \
+ printf("[ERROR:%s][%s:%d] " fmt "\n", __FILENAME__, __FUNCTION__, __LINE__, ##__VA_ARGS__); \
+ } while (0);
+
+// 打印十六进制字符串
+#define LOG_HEX(data, len) \
+ do \
+ { \
+ printf("[DEBUG:%s][%s:%d] ", __FILENAME__, __FUNCTION__, __LINE__); \
+ for (int i = 0; i < len; i++) \
+ { \
+ printf("%02x ", data[i]); \
+ } \
+ printf("\n"); \
+ } while (0);
+
+#endif //__LOG_H_
diff --git a/User/hart/lib/inc/malloc.h b/User/hart/lib/inc/malloc.h
new file mode 100644
index 0000000..5100b8a
--- /dev/null
+++ b/User/hart/lib/inc/malloc.h
@@ -0,0 +1,45 @@
+#ifndef _MOLLOC_H
+#define _MOLLOC_H
+
+#include "../inc/data_type_def.h"
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+// 定义两个内存池
+#define SRAMIN 0 // 内部内存池
+#define SRAMEX 1 // 外部内存池(精英STM32开发板不支持外部内存)
+// 我们又多少个SRAM可管理
+#define SRAMBANK 2 // 定义支持的SRAM块数. 精英版实际上只支持1个内存区域,即内部内存.
+
+// mem1内存参数设定.mem1完全处于内部SRAM里面.(设置内部SARM的内存池和内存表的参数)
+#define MEM1_BLOCK_SIZE 32 // 一个内存块大小为32字节
+#define MEM1_MAX_SIZE 24 * 1024 // 最大管理内存 1K (我们这个内存管理系统的内部SRAM可控制的内存大小)
+#define MEM1_ALLOC_TABLE_SIZE MEM1_MAX_SIZE / MEM1_BLOCK_SIZE // 内存表大小(有多少块内存块)
+
+// mem2内存参数设定.mem2的内存池处于外部SRAM里面
+#define MEM2_BLOCK_SIZE 32 // 一个内存块大小为32字节
+#define MEM2_MAX_SIZE 20 * 1024 // 因为精英版没有外扩内存,故这里设置一个最小值
+#define MEM2_ALLOC_TABLE_SIZE MEM2_MAX_SIZE / MEM2_BLOCK_SIZE // 内存表大小
+
+// 内存管理控制器结构体
+// 注意:内存管理由内存池和内存列表组成
+// SRAMBANK:SARM块数,一般有内部SRAM和外部SRAM、CCM
+struct _m_mallco_dev
+{
+ void (*init)(uint8_t); // 初始化
+ uint8_t (*perused)(uint8_t); // 内存使用率
+ uint8_t *membase[SRAMBANK]; // 内存池 管理SRAMBANK个区域的内存
+ uint16_t *memmap[SRAMBANK]; // 内存管理状态表
+ uint8_t memrdy[SRAMBANK]; // 内存管理是否就绪
+};
+
+void my_mem_init(uint8_t memx);
+uint8_t my_mem_perused(uint8_t memx);
+
+void *mymalloc(uint8_t memx, uint32_t size);
+void myfree(uint8_t memx, void *ptr);
+void *myrealloc(uint8_t memx, void *ptr, uint32_t size);
+
+#endif
diff --git a/User/hart/lib/inc/mlist.h b/User/hart/lib/inc/mlist.h
new file mode 100644
index 0000000..ebc043f
--- /dev/null
+++ b/User/hart/lib/inc/mlist.h
@@ -0,0 +1,268 @@
+/***
+ * @Author:
+ * @Date: 2023-04-04 08:39:32
+ * @LastEditors: xxx
+ * @LastEditTime: 2023-04-04 08:46:20
+ * @Description:双向链表操作接口 该双向链表的操作,请参照Linux内核 (include/linux/list.h)
+ * @email:
+ * @Copyright (c) 2023 by xxx, All Rights Reserved.
+ */
+
+#ifndef __LIST_H
+#define __LIST_H
+#include
+#include "data_type_def.h"
+typedef struct list_head
+{
+ struct list_head *next;
+ struct list_head *prev;
+} list_head_t;
+
+/**
+ * 获得链表元素所在实体的地址, 该实体在链表中保存
+ *
+ * @param ptr: 链表的入口指针
+ * @param type: 结构类型
+ * @param member: 元素结构中链表变量的名字
+ *
+ * @return 指向该元素所在实体的指针
+ */
+#define list_entry_addr_find(ptr, type, member) \
+ ((type *)((char *)(ptr) - (char *)(&((type *)NULL)->member)))
+
+/**
+ * 移除并返回链表中首元素所在的实体,该实体在链表中不保存
+ *
+ * @param head: 链表的入口指针
+ * @param type: 结构类型
+ * @param member: 指向该链表的第一个元素的指针
+ *
+ * @return 表首元素所在实体的指针,链表为空则返回空指针
+ */
+#define list_entry_decap(head, type, member) \
+ ( \
+ (list_empty(head)) ? (type *)NULL \
+ : (list_entry_addr_find(list_next_elem_get(head), type, member)))
+
+#define list_entry_get_head(head, type, member) \
+ ((list_empty(head)) ? (type *)NULL : (list_entry_addr_find((head)->next, type, member)))
+/**
+ * 移除并返回链表尾部所在实体,该实体在链表中不保存
+ *
+ * @param head: 链表入口指针
+ * @param type: 链表所在结构体的名称
+ * @param member: 结构体中,链表变量的名称
+ *
+ * @return 表尾部所在实体指针,链表为空则返回空指针
+ */
+#define list_entry_curtail(head, type, member) \
+ ((list_empty(head)) ? (type *)NULL \
+ : (list_entry_addr_find(list_curtail(head), type, member)))
+
+/**
+ * 正向遍历链表,在该遍历中不能对链表做删除操作 -- list_for_each
+ *
+ * @param pos: 链表元素计数器
+ * @param head: 链表的入口指针
+ */
+#define list_for_each_forwards(pos, head) \
+ for ((pos) = (head)->next; (pos) != (head); (pos) = (pos)->next)
+
+/**
+ * 反向遍历链表,在该遍历中不能对链表做删除操作
+ *
+ * @param pos: 链表元素计数器
+ * @param head: 链表的入口指针
+ */
+#define list_for_each_backwards(pos, head) \
+ for ((pos) = (head)->prev; (pos) != (head); (pos) = (pos)->prev)
+
+/**
+ * 链表遍历,支持删除操作
+ *
+ * @param pos: 链表元素计数器
+ * @param n: 临时链表元素
+ * @param head: 链表入口指针
+ */
+#define list_for_each_safe(pos, n, head) \
+ for ((pos) = (head)->next, n = (pos)->next; (pos) != (head); \
+ (pos) = n, n = (pos)->next)
+
+/**
+ * 遍历链表所在实体,不可删除实体
+ *
+ * @param pos: 链表元素计数器
+ * @param head: 链表入口指针
+ * @param type: 链表所在结构体的名称
+ * @param member: 结构体中,链表变量的名称
+ */
+#define list_entry_for_each(pos, head, type, member) \
+ for ((pos) = list_entry_addr_find((head)->next, type, member); \
+ &(pos)->member != (head); \
+ (pos) = list_entry_addr_find((pos)->member.next, type, member))
+
+/**
+ * 遍历链表所在实体, 支持删除操作
+ *
+ * @param pos: 链表元素计数器
+ * @param n: 临时链表元素
+ * @param head: 链表入口指针
+ * @param type: 链表所在结构体的名称
+ * @param member: 结构体中,链表变量的名称
+ */
+#define list_entry_for_each_safe(pos, n, head, type, member) \
+ for ((pos) = list_entry_addr_find((head)->next, type, member), \
+ n = list_entry_addr_find((pos)->member.next, type, member); \
+ &(pos)->member != (head); \
+ (pos) = n, n = list_entry_addr_find(n->member.next, type, member))
+
+/**
+ * 计算链表中元素的个数
+ */
+#define list_count(head, count) \
+ do \
+ { \
+ count = 0; \
+ for (list_head_t *pos = (head)->next; pos != (head); pos = pos->next) \
+ { \
+ count++; \
+ } \
+ } while (0)
+
+/**
+ * 将实体按顺序插入到链表中合适的地方,顺序由函数funcCompare来决定 -- list_sorted_add
+ *
+ * @param new_entry: 所要插入的实体
+ * @param head: 链表头
+ * @param type: 链表所在结构体的名称
+ * @param member: 结构体中,链表变量的名称
+ * @param func_compare: 顺序比较函数,声明:bool func_compare(Node* A, Node* B)
+ * 如果 A < B, 返回 true, 否则返回 false
+ * @param pos: 链表元素计数器
+ */
+#define list_entry_sorted_add(new_entry, head, type, member, func_compare, pos) \
+ do \
+ { \
+ type *entry_a = NULL; \
+ type *entry_b = NULL; \
+ for ((pos) = (head)->next; (pos) != (head); (pos) = (pos)->next) \
+ { \
+ entry_a = list_entry_addr_find((new_entry), type, member); \
+ entry_b = list_entry_addr_find((pos), type, member); \
+ if (func_compare(entry_a, entry_b)) \
+ { \
+ break; \
+ } \
+ } \
+ if ((pos) != (head)) \
+ { \
+ list_insert_forwards((new_entry), (pos)); \
+ } \
+ else \
+ { \
+ list_add_to_tail((new_entry), (head)); \
+ } \
+ } while (__LINE__ == -1)
+
+/**
+ * 链表头初始化
+ *
+ * @param ptr: 需要被初始化的链表头指针
+ */
+void list_init(list_head_t *const ptr);
+
+/**
+ * 在指定位置之前插入新的元素
+ *
+ * @param new_entry: 需要放入链表中的新元素
+ * @param pos: 链表中放入新元素的位置指针
+ */
+void list_insert_forwards(list_head_t *const new_entry, list_head_t *const pos);
+
+/**
+ * 在指定位置之后插入新的元素
+ *
+ * @param new_entry: 需要放入链表中的新元素
+ * @param pos: 链表中放入新元素的位置指针
+ */
+void list_insert_backwards(list_head_t *const new_entry, list_head_t *const pos);
+
+/**
+ * 在链表尾部之后插入新的元素 -- list_append
+ *
+ * @param new_entry: 需要放入链表尾部的新元素
+ * @param list: 链表头指针
+ */
+void list_add_to_tail(list_head_t *const new_entry, list_head_t *const list);
+
+/**
+ * 在链表头部之后插入新的元素
+ *
+ * @param new_entry: 需要放入链表尾部的新元素
+ * @param list: 链表头指针
+ */
+void list_add_to_head(list_head_t *const new_entry, list_head_t *const list);
+
+/**
+ * 将指定元素从链表中删除
+ *
+ * @param elem: 需要删除的链表元素
+ */
+void list_del(list_head_t *const elem);
+
+/**
+ * 将链表的尾元素删除并返回
+ *
+ * @param head: 链表指针
+ *
+ * @return 链表尾元素
+ */
+list_head_t *list_curtail(const list_head_t *const head);
+
+/**
+ * 判断链表是否为空
+ *
+ * @param head: 链表头指针
+ *
+ * @return 为空时返回TRUE,否则为FALSE
+ */
+bool list_empty(const list_head_t *const head);
+
+/**
+ * 获取链表中第一个元素的地址 -- list_get_head
+ *
+ * @param head: 链表头指针
+ *
+ * @return 首元素的地址
+ */
+list_head_t *list_first_elem_look(const list_head_t *const head);
+
+/**
+ * 取出给定位置的下一个元素
+ *
+ * @param pos: 链表元素地址
+ *
+ * @return 下一个链表元素地址
+ */
+list_head_t *list_next_elem_get(const list_head_t *const pos);
+
+/**
+ * 将一个元素从一个链表中移除,然后再插入另外一个链表中的头部
+ *
+ * @param elem: 被移除的链表元素
+ * @param head: 新链表头
+ */
+void list_move_to_another_head(list_head_t *const elem, list_head_t *const head);
+
+/**
+ * 将一个元素从一个链表中移除,然后再放入另外一个链表中的尾部
+ *
+ * @param elem: 被移除的链表元素
+ * @param head: 新链表头
+ */
+void list_move_to_another_tail(list_head_t *const elem, list_head_t *const head);
+
+#endif
+/**
+ * @}
+ */
diff --git a/User/hart/lib/inc/osel_arch.h b/User/hart/lib/inc/osel_arch.h
new file mode 100644
index 0000000..9860e8c
--- /dev/null
+++ b/User/hart/lib/inc/osel_arch.h
@@ -0,0 +1,181 @@
+/***
+ * @Author:
+ * @Date: 2023-04-04 08:13:11
+ * @LastEditors: xxx
+ * @LastEditTime: 2023-04-04 08:16:58
+ * @Description:
+ * @email:
+ * @Copyright (c) 2023 by xxx, All Rights Reserved.
+ */
+
+#ifndef __OSEL_ARCH_H__
+#define __OSEL_ARCH_H__
+
+#include "lib.h"
+#define hal_int_state_t char
+#ifdef STM32
+#include "stm32l4xx.h"
+#define HAL_ENTER_CRITICAL(__HANDLE__) \
+ do \
+ { \
+ if ((__HANDLE__)->Lock == HAL_LOCKED) \
+ { \
+ return HAL_BUSY; \
+ } \
+ else \
+ { \
+ (__HANDLE__)->Lock = HAL_LOCKED; \
+ } \
+ } while (0U)
+
+#define HAL_EXIT_CRITICAL(__HANDLE__) \
+ do \
+ { \
+ (__HANDLE__)->Lock = HAL_UNLOCKED; \
+ } while (0U)
+#else
+#define HAL_ENTER_CRITICAL(__HANDLE__)
+
+#define HAL_EXIT_CRITICAL(__HANDLE__)
+
+#endif
+
+#define osel_memset _memset
+#define osel_memcmp _memcmp
+#define osel_memcpy _memcpyL
+#define osel_memcpyr _memcpyR
+#define osel_reverse _reverse
+#define osel_mem_alloc _malloc
+#define osel_mem_free _free
+#define osel_mem_alloc2 _malloc2
+#define osel_mem_free2 _free2
+#define osel_mstrlen _mstrlen
+
+static inline void *_malloc(uint32_t size)
+{
+ return mymalloc(SRAMIN, size);
+}
+
+static inline void _free(void *ptr)
+{
+ myfree(SRAMIN, ptr);
+}
+
+static inline void *_malloc2(uint32_t size)
+{
+ return mymalloc(SRAMEX, size);
+}
+
+static inline void _free2(void *ptr)
+{
+ myfree(SRAMEX, ptr);
+}
+
+/**
+ * @brief Fills a block of memory with a given value.
+ *
+ * @param dst The destination block of memory.
+ * @param value The value to fill the memory with.
+ * @param size The size of the memory block, in bytes.
+ */
+static inline void _memset(uint8_t *dst, uint8_t value, uint16_t size)
+{
+ while (size--)
+ {
+ *dst++ = value;
+ }
+}
+
+/**
+ * @brief Compares two blocks of memory for equality.
+ *
+ * @param[in] dst The first block of memory to compare.
+ * @param[in] src The second block of memory to compare.
+ * @param[in] size The number of bytes to compare.
+ *
+ * @return 0 if the blocks of memory are equal, -1 otherwise.
+ */
+static inline int8_t _memcmp(const uint8_t *dst, const uint8_t *src, uint16_t size)
+{
+ while (size--)
+ {
+ if (*dst++ != *src++)
+ {
+ return -1;
+ }
+ }
+ return 0;
+}
+
+/**
+ * @brief Copies data from a source buffer to a destination buffer in a forward direction.
+ *
+ * @param dst The destination buffer.
+ * @param src The source buffer.
+ * @param size The number of bytes to copy.
+ */
+static inline void _memcpyL(uint8_t *dst, const uint8_t *src, uint16_t size)
+{
+ while (size--)
+ {
+ *dst++ = *src++;
+ }
+}
+
+/**
+ * @brief Copies data from a source buffer to a destination buffer in reverse order.
+ *
+ * @param dst The destination buffer.
+ * @param src The source buffer.
+ * @param size The number of bytes to copy.
+ */
+static inline void _memcpyR(uint8_t *dst, const uint8_t *src, uint16_t size)
+{
+ // dst is a pointer to the last byte of the destination buffer
+ // src is a pointer to the first byte of the source buffer
+ // size is the number of bytes to copy
+
+ // decrement the destination pointer by the size, since we want to write to the last byte of the buffer
+ dst = dst + (size - 1);
+
+ // loop through each byte in the buffer, copying from the source to the destination in reverse order
+ while (size--)
+ {
+ // write the next byte from the source to the destination
+ *dst-- = *src++;
+ }
+}
+
+/**
+ * @brief Reverses the order of bytes in a buffer
+ *
+ * @param buf The buffer to reverse
+ * @param len The length of the buffer, in bytes
+ */
+static inline void _reverse(uint8_t *buf, uint16_t len)
+{
+ uint8_t temp = 0;
+ uint16_t i;
+ for (i = 0; i < len / 2; i++)
+ {
+ temp = buf[i];
+ buf[i] = buf[len - i - 1];
+ buf[len - i - 1] = temp;
+ }
+}
+/**
+ * @brief Returns the length of a null-terminated string
+ *
+ * @param s The string to measure
+ * @return The length of the string, not including the null terminator
+ */
+static inline unsigned int _mstrlen(const unsigned char *s)
+{
+ const unsigned char *ss = s;
+ while (*ss)
+ ss++;
+
+ return ss - s;
+}
+
+#endif // __OSEL_ARCH_H__
diff --git a/User/hart/lib/inc/pbuf.h b/User/hart/lib/inc/pbuf.h
new file mode 100644
index 0000000..ee3a6ce
--- /dev/null
+++ b/User/hart/lib/inc/pbuf.h
@@ -0,0 +1,169 @@
+/***
+ * @Author:
+ * @Date: 2023-04-04 10:06:40
+ * @LastEditors: xxx
+ * @LastEditTime: 2023-04-04 13:21:27
+ * @Description:
+ * @email:
+ * @Copyright (c) 2023 by xxx, All Rights Reserved.
+ */
+
+#ifndef COMPONENTS_COMMON_INCLUDE_PBUF_H_
+#define COMPONENTS_COMMON_INCLUDE_PBUF_H_
+#include "../inc/data_type_def.h"
+#include "../inc/mlist.h"
+#include "../inc/malloc.h"
+
+#define PBUF_DBG_EN (1u)
+#define PBUF_TYPE_MAX_NUM (3u)
+
+#define PBUF_NUM_MAX (10u)
+
+// 如果size>254,并使用data_analysis接收数据,需要修改data_analysis.c中的DATA_BUF_RECV_SQQ_LEN
+#define SMALL_PBUF_BUFFER_SIZE (32)
+#define MEDIUM_PBUF_BUFFER_SIZE (32 * 2)
+#define LARGE_PBUF_BUFFER_SIZE (32 * 4)
+
+#define SMALL_PBUF_NUM (4u) // 各种PBUF最大个数
+#define MEDIUM_PBUF_NUM (4u)
+#define LARGE_PBUF_NUM (4u)
+
+#if PBUF_DBG_EN > 0
+
+/*形参*/
+#define _PLINE1_ , uint16_t line
+#define _PLINE2_ , uint16_t line
+/*实参*/
+#define __PLINE1 , __LINE__
+#define __PLINE2 , __LINE__
+
+#else
+
+#define _PLINE1_
+#define _PLINE2_
+#define __PLINE1
+#define __PLINE2
+
+#endif
+
+enum _PBUF_TYPE
+{
+ SMALL_PBUF,
+ MEDIUM_PBUF,
+ LARGE_PBUF,
+ PBUF_TYPE_INVALID
+};
+
+typedef struct __send_times_t
+{
+ uint8_t app_send_times;
+ uint8_t mac_send_times;
+} send_times_t;
+
+typedef struct
+{
+ int8_t rssi_dbm;
+ uint8_t seq;
+
+ nwk_id_t src_id; // 接收到数据帧时,为同步模块提供同步对象信息;
+ nwk_id_t dst_id; // 填写帧的目的节点网络地址
+
+ uint8_t send_mode : 2,
+ is_ack : 1,
+ need_ack : 1,
+ crc_ok : 1,
+ is_pending : 1,
+ debug_info : 1,
+ reserved : 1;
+
+ send_times_t already_send_times;
+} pkt_attri_t;
+
+typedef struct
+{
+ struct list_head list;
+ uint8_t *data_p; // 指向数据区
+ uint8_t *head; // 指向数据区的第一个字节
+ uint8_t *end; // 指向数据区的最后一个字节
+ uint16_t data_len; // 该pbuf的实际数据长度
+ pkt_attri_t attri;
+ bool used;
+#if PBUF_DBG_EN > 0
+ uint16_t alloc_line;
+ uint16_t free_line;
+#endif
+} pbuf_t;
+
+/**
+ * pbuf_initz: 为pbuf申请一块内存区域,需要配置各种pbuf的大小和数量等
+ */
+void pbuf_initz(void);
+
+/**
+ * 申请一个pbuf,用来存放用户数据
+ *
+ * @param size: 用户的数据长度
+ * @param _PLINE1_: pbuf_allocz()位置的行号,调用时传入实参形式__PLINE1
+ *
+ * @return: 申请成功则返回pbuf的指针,失败则进入断言
+ */
+extern pbuf_t *pbuf_allocz(uint16_t size _PLINE1_);
+
+/**
+ * 释放已经使用完的pbuf
+ *
+ * @param pbuf: 需要操作的pbuf的指针的指针
+ * @param _PLINE2_: 调用pbuf_freez()位置的行号,调用时传入实参形式__PLINE2
+ *
+ * @return: 无
+ */
+void pbuf_freez(pbuf_t **const pbuf _PLINE2_);
+
+/**
+ * 向pbuf->end方向移动pbuf->data_p指针,移动距离为len
+ *
+ * @param pbuf: 需要操作的pbuf的指针
+ * @param len: data_p需要移动的距离
+ *
+ * @return: 成功则返回data_p指针,失败返回NULL
+ */
+extern uint8_t *pbuf_skip_datap_forward(pbuf_t *const pbuf,
+ uint8_t len);
+
+/**
+ * 向pbuf->head方向移动pbuf->data_p指针,移动距离为len
+ *
+ * @param pbuf: 需要操作的pbuf的指针
+ * @param len: data_p需要移动的距离
+ *
+ * @return: 成功则返回data_p指针,失败返回NULL
+ */
+extern uint8_t *pbuf_skip_datap_backward(pbuf_t *const pbuf,
+ uint8_t len);
+
+/**
+ * 向pbuf的数据区拷贝数据,并移动data_p指针,改变data_len
+ *
+ * @param pbuf: 目的地址pbuf的指针(从pbuf->data_p开始拷贝)
+ * @param src: 源地址的指针
+ * @param len: 需要拷贝的数据长度
+ *
+ * @return: 成功则返回TRUE, 失败则返回FALSE
+ */
+extern bool pbuf_copy_data_in(pbuf_t *const pbuf,
+ const uint8_t *const src,
+ uint8_t len);
+
+/**
+ * 从pbuf的数据区拷贝数据,并移动data_p指针,不改变data_len
+ *
+ * @param dst: 目的地址的指针
+ * @param pbuf: 源地址pbuf的指针(从pbuf->data_p开始拷贝)
+ * @param len: 需要拷贝的数据长度
+ *
+ * @return: 成功则返回TRUE, 失败则返回
+ */
+extern bool pbuf_copy_data_out(uint8_t *const dst,
+ pbuf_t *const pbuf,
+ uint8_t len);
+#endif /* COMPONENTS_COMMON_INCLUDE_PBUF_H_ */
diff --git a/User/hart/lib/inc/sqqueue.h b/User/hart/lib/inc/sqqueue.h
new file mode 100644
index 0000000..e6e92c7
--- /dev/null
+++ b/User/hart/lib/inc/sqqueue.h
@@ -0,0 +1,49 @@
+/**
+ * @file sqqueue.h
+ * @author xxx
+ * @date 2023-06-25 13:07:02
+ * @brief 提供循环队列功能
+ * @copyright Copyright (c) 2023 by xxx, All Rights Reserved.
+ */
+
+#ifndef __SQQUEUE_H
+#define __SQQUEUE_H
+#include
+#include "data_type_def.h"
+
+typedef struct _sqqueue_t
+{
+ uint8_t *base; // 队列存储元素的首地址
+ uint8_t entry_size; // 队列元素的宽度
+ uint16_t sqq_len; // 队列总长
+ uint16_t front; // 队列头下标
+ uint16_t rear; // 队列尾下标
+} sqqueue_t;
+
+/**
+ * 通用循环队列伪类
+ * 该队列有九个操作,分别为单元素入队列、多元素入队列、出队列,
+ * 单元素撤销入队列(队尾删除)、取队列长度、判空、清空队列、遍历和删除指定位置
+ */
+typedef struct _sqqueue_ctrl_t
+{
+ sqqueue_t sqq;
+ bool (*enter)(struct _sqqueue_ctrl_t *const p_this, const void *const e); // 单元素入队列
+ bool (*string_enter)(struct _sqqueue_ctrl_t *const p_this, const void *const string, uint16_t len); // 多元素入队列
+ void *(*del)(struct _sqqueue_ctrl_t *const p_this); // 出队列
+ void *(*revoke)(struct _sqqueue_ctrl_t *const p_this); // 撤销入队列
+ uint16_t (*get_len)(const struct _sqqueue_ctrl_t *const p_this); // 取队列长度
+ bool (*full)(const struct _sqqueue_ctrl_t *const p_this); // 判满
+ void (*clear_sqq)(struct _sqqueue_ctrl_t *const p_this); // 清空队列
+ void (*traverse)(struct _sqqueue_ctrl_t *const p_this, void (*vi)(const void *e)); // 遍历
+ void (*remove)(struct _sqqueue_ctrl_t *const p_this, uint16_t location); // 删除指定位置
+} sqqueue_ctrl_t;
+
+bool sqqueue_ctrl_init(sqqueue_ctrl_t *const p_this,
+ uint8_t entry_size,
+ uint16_t sqq_len); ///< 初始化
+
+#endif
+/**
+ * @}
+ */
diff --git a/User/hart/lib/inc/wl_flash.h b/User/hart/lib/inc/wl_flash.h
new file mode 100644
index 0000000..694fac9
--- /dev/null
+++ b/User/hart/lib/inc/wl_flash.h
@@ -0,0 +1,108 @@
+/**
+ * @file wl_flash.h
+ * @author xushenghao
+ * @date 2024-07-22 13:57:02
+ * @brief
+ * @copyright Copyright (c) 2024 by xxx, All Rights Reserved.
+ */
+/**
+ * @brief 磨损平衡算法
+ *
+ * 1. 初始化block_page大小和当前写入地址
+ * 2. 写入数据前,检查剩余空间是否足够
+ * a. 如果足够,直接写入数据
+ * b. 如果不足够,执行以下步骤:
+ * i. 检查是否有已擦除但未使用的block_page,如果有,移动到该block_page继续写入
+ * ii. 如果没有已擦除的block_page,检查当前block_page是否已满
+ * - 如果已满,移动到下一个block_page
+ * - 在移动前,检查该block_page是否有有效数据需要迁移,如果有,则先迁移数据
+ * 3. 在决定擦除新的block_page前,采用Wear Leveling算法选择最佳的block_page进行擦除
+ * 4. 数据写入后,更新剩余空间大小和当前写入地址
+ */
+
+/**
+ * 使用方法
+ *
+ #define LL_FLASH_PAGE_SIZE (2 * 1024)
+ #define PVD_RESET_STORAGE_START_ADDRESS (256 * LL_FLASH_PAGE_SIZE)
+ static void test_wl_flash(void)
+ {
+ uint32_t address = 0;
+ wl_flash_t wf = {
+ .wl_flag = TRUE,
+ .addr = PVD_RESET_STORAGE_START_ADDRESS,
+ .len = 2 * LL_FLASH_PAGE_SIZE,
+ .page_size = LL_FLASH_PAGE_SIZE,
+ .data_size = sizeof(device_reset_t),
+ .write_gran = 8,
+
+ .ops.srand = board_srand,
+ .ops.read = flash_read,
+ .ops.write = flash_write,
+ .ops.erase_page = flash_erase_page,
+ };
+ wl_flash_init(&wf);
+ wl_flash_erase(&wf);
+ address = wl_flash_get_current_address(&wf);
+
+ device_reset_t power_on;
+ power_on.flag = PVD_RESET_FLAG;
+
+ // 一页2048/16 = 128个数据,2页 = 256个数据,i=255时数据从头开始
+ for (uint16_t i = 0; i < 1000; i++)
+ {
+ wl_flash_write(&wf, (uint8_t *)&power_on, sizeof(device_reset_t));
+ wl_flash_set_next_address(&wf);
+ address = wl_flash_get_current_address(&wf);
+ if (address == wf.addr)
+ {
+ __NOP();
+ }
+ }
+ }
+ */
+
+#ifndef __WL_FLASH_H__
+#define __WL_FLASH_H__
+#include "lib.h"
+
+typedef struct
+{
+ BOOL wl_flag; // 开启平衡擦写标志
+ uint32_t addr; // Flash 起始地址
+ uint32_t len; // Flash 长度
+ uint16_t page_size; // Flash 页大小 2^N
+ uint16_t data_size; // 数据大小
+ /* write minimum granularity, unit: byte.
+ 1(stm32f2/f4)/ 4(stm32f1)/ 8(stm32l4)
+ 0 will not take effect. */
+ uint8_t write_gran;
+ struct
+ {
+ void (*srand)(void); // 随机数种子
+ BOOL(*read)
+ (uint32_t addr, uint8_t *buf, uint16_t size);
+ BOOL(*write)
+ (uint32_t addr, const uint8_t *buf, uint16_t size);
+ BOOL(*erase_page)
+ (uint32_t page);
+ } ops;
+
+ struct
+ {
+ uint32_t current_address; // 当前准备写入的地址
+ uint16_t residue_size; // 剩余可写大小
+ uint16_t start_page; // 起始页
+ uint16_t page_total; // 总页数
+ uint16_t block_page; // 擦除块大小
+ } private;
+} wl_flash_t;
+
+extern void wl_flash_init(wl_flash_t *cfg); ///< 初始化 Flash 磨损平衡算法
+extern uint32_t wl_flash_get_current_address(wl_flash_t *cfg); ///< 获取当前写入地址
+extern void wl_flash_set_next_address(wl_flash_t *cfg); ///< 设置下一个写入地址,下一个写入区域会被擦除
+extern void wl_flash_set_current_address(wl_flash_t *cfg, uint32_t address); ///< 设置当前写入地址
+extern void wl_flash_erase(wl_flash_t *cfg); ///< 擦除 Flash, 如果开启了平衡擦写标志, 则会随机分配写入地址
+extern BOOL wl_flash_write(wl_flash_t *cfg, const uint8_t *buf, uint16_t size); ///< 写入 Flash
+extern BOOL wl_flash_read(wl_flash_t *cfg, uint8_t *buf, uint16_t size); ///< 读取 Flash
+#endif // __WL_FLASH_H__
diff --git a/User/lib/src/aes.c b/User/hart/lib/src/aes.c
similarity index 100%
rename from User/lib/src/aes.c
rename to User/hart/lib/src/aes.c
diff --git a/User/lib/src/clist.c b/User/hart/lib/src/clist.c
similarity index 100%
rename from User/lib/src/clist.c
rename to User/hart/lib/src/clist.c
diff --git a/User/lib/src/cmac.c b/User/hart/lib/src/cmac.c
similarity index 100%
rename from User/lib/src/cmac.c
rename to User/hart/lib/src/cmac.c
diff --git a/User/lib/src/cmd.c b/User/hart/lib/src/cmd.c
similarity index 100%
rename from User/lib/src/cmd.c
rename to User/hart/lib/src/cmd.c
diff --git a/User/lib/src/data_analysis.c b/User/hart/lib/src/data_analysis.c
similarity index 100%
rename from User/lib/src/data_analysis.c
rename to User/hart/lib/src/data_analysis.c
diff --git a/User/lib/src/debug.c b/User/hart/lib/src/debug.c
similarity index 91%
rename from User/lib/src/debug.c
rename to User/hart/lib/src/debug.c
index e0f3ce2..a03ef5f 100644
--- a/User/lib/src/debug.c
+++ b/User/hart/lib/src/debug.c
@@ -33,11 +33,10 @@ BOOL DBG_ASSERT(uint8_t cond _DBG_LINE_)
{
if ((cond) == FALSE)
{
-// dbg_assert_line = line;
#if DEBUG_ENABLE == FALSE
sys_soft_reset();
#endif
-// leds_on(LEDS_ORANGE);
+ leds_on(LEDS_ORANGE);
while (1)
{
LOG_ERR("DBG_ASSERT:%d", line);
diff --git a/User/lib/src/filter.c b/User/hart/lib/src/filter.c
similarity index 57%
rename from User/lib/src/filter.c
rename to User/hart/lib/src/filter.c
index 86110ed..1a907ce 100644
--- a/User/lib/src/filter.c
+++ b/User/hart/lib/src/filter.c
@@ -1,63 +1,57 @@
#include "filter.h"
#include
#include "osel_arch.h"
-// 卡尔曼滤波
-#define FILTER_COUNT 10
-void kalman_init(kalman_t *cfg)
-{
- cfg->Last_P = 1;
- cfg->Now_P = 0;
- cfg->out = 0;
- cfg->Kg = 0;
- cfg->Q = 0;
- cfg->R = 0.05;
- cfg->filter_count = 0;
- if (cfg->default_filter_count == 0)
- {
- cfg->default_filter_count = FILTER_COUNT;
- }
- if (cfg->filter_limit == 0)
- {
- cfg->filter_limit = 1.0f; // 限制滤波器的最大误差
- }
- cfg->change = TRUE;
-}
-
-void kalman_reset(kalman_t *cfg)
-{
- kalman_init(cfg);
+/**
+ * @brief 初始化卡尔曼滤波器
+ *
+ * 初始化给定的卡尔曼滤波器配置结构体,并设置初始参数。
+ *
+ * @param cfg 卡尔曼滤波器配置结构体指针
+ * @param change_max 最大变化量
+ */
+void kalman_init(kalman_t *cfg, float32 change_max)
+{
+ DBG_ASSERT(cfg != NULL __DBG_LINE);
+ // 初始化卡尔曼滤波器配置
+ cfg->x = 0; // 初始状态估计值
+ cfg->p = 5; // 初始估计误差协方差
+ cfg->a = 1; // 状态转移矩阵
+ cfg->h = 1; // 观测矩阵
+ cfg->q = 0.25; // 过程噪声协方差
+ cfg->r = 1; // 观测噪声协方差
+ cfg->change_max = change_max; // 最大变化值
}
+/**
+ * @brief 卡尔曼滤波器更新函数
+ *
+ * 根据输入的观测值和卡尔曼滤波器的配置参数,更新滤波器的状态和估计值。
+ *
+ * @param cfg 卡尔曼滤波器配置指针
+ * @param input 输入的观测值
+ *
+ * @return 更新后的卡尔曼滤波器估计值
+ */
float32 kalman_update(kalman_t *cfg, float32 input)
{
- if (fabs(input - cfg->out) > cfg->filter_limit)
+ DBG_ASSERT(cfg != NULL __DBG_LINE);
+ // 计算变化值
+ float32 delta = input - cfg->x;
+ // 如果变化值超过0.5,直接返回输入值
+ if (ABS(delta) > cfg->change_max)
{
- if (cfg->filter_count < cfg->default_filter_count)
- {
- cfg->filter_count++;
- cfg->change = FALSE;
- }
- else
- {
- kalman_init(cfg);
- }
- }
- else
- {
- cfg->filter_count = 0;
- cfg->change = FALSE;
+ cfg->x = input;
+ return cfg->x;
}
+ cfg->x = cfg->a * cfg->x;
+ cfg->p = cfg->a * cfg->a * cfg->p + cfg->q;
- // 预测协方差方程:k时刻系统估算协方差 = k-1时刻的系统协方差 + 过程噪声协方差
- cfg->Now_P = cfg->Last_P + cfg->Q;
- // 卡尔曼增益方程:卡尔曼增益 = k时刻系统估算协方差 / (k时刻系统估算协方差 + 观测噪声协方差)
- cfg->Kg = cfg->Now_P / (cfg->Now_P + cfg->R);
- // 更新最优值方程:k时刻状态变量的最优值 = 状态变量的预测值 + 卡尔曼增益 * (测量值 - 状态变量的预测值)
- cfg->out = cfg->out + cfg->Kg * (input - cfg->out); // 因为这一次的预测值就是上一次的输出值
- // 更新协方差方程: 本次的系统协方差付给 cfg->LastP 威下一次运算准备。
- cfg->Last_P = (1 - cfg->Kg) * cfg->Now_P;
- return cfg->out;
+ cfg->gain = cfg->p * cfg->h / (cfg->p * cfg->h * cfg->h + cfg->r);
+ cfg->x = cfg->x + cfg->gain * (input - cfg->h * cfg->x);
+ cfg->p = (1 - cfg->gain * cfg->h) * cfg->p;
+
+ return cfg->x;
}
// 一阶滞后滤波法
@@ -97,17 +91,19 @@ void lpf_reset(lpf_t *cfg)
/**
* 滑动平均窗口滤波
*/
-lpf_window_t *lpf_window_init(uint16_t size)
+void lpf_window_init(lpf_window_t *cfg, uint16_t size)
{
- lpf_window_t *cfg = (lpf_window_t *)osel_mem_alloc(sizeof(lpf_window_t));
DBG_ASSERT(cfg != NULL __DBG_LINE);
+ if (cfg->window != NULL)
+ {
+ osel_mem_free(cfg->window);
+ }
osel_memset((uint8_t *)cfg, 0, sizeof(lpf_window_t));
cfg->size = size;
cfg->window = (float32 *)osel_mem_alloc(sizeof(float32) * size);
DBG_ASSERT(cfg->window != NULL __DBG_LINE);
cfg->index = 0;
cfg->sum = 0;
- return cfg;
}
void lpf_window_dinit(lpf_window_t *cfg)
diff --git a/User/lib/src/lib.c b/User/hart/lib/src/lib.c
similarity index 56%
rename from User/lib/src/lib.c
rename to User/hart/lib/src/lib.c
index 6d26ae1..8a8f9b3 100644
--- a/User/lib/src/lib.c
+++ b/User/hart/lib/src/lib.c
@@ -11,7 +11,7 @@
#include "../inc/lib.h"
#include
#include
-
+#include "cmac.h"
const uint8_t _days[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
const uint16_t _month_days[12] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
static uint32_t crc32_table[256]; // CRC32表
@@ -38,12 +38,12 @@ void add_commas(uint32_t num, char *result)
char temp[64];
sprintf(temp, "%d", num);
- int len = strlen(temp);
- int commas = (len - 1) / 3;
+ int32_t len = strlen(temp);
+ int32_t commas = (len - 1) / 3;
- int index = 0;
- int resultIndex = 0;
- for (int i = len - 1; i >= 0; i--)
+ int32_t index = 0;
+ int32_t resultIndex = 0;
+ for (int32_t i = len - 1; i >= 0; i--)
{
result[resultIndex++] = temp[i];
index++;
@@ -56,8 +56,8 @@ void add_commas(uint32_t num, char *result)
result[resultIndex] = '\0';
// Reverse the result string
- int start = 0;
- int end = resultIndex - 1;
+ int32_t start = 0;
+ int32_t end = resultIndex - 1;
while (start < end)
{
char temp = result[start];
@@ -68,6 +68,16 @@ void add_commas(uint32_t num, char *result)
}
}
+void get_cpu_id(uint32_t *id)
+{
+#ifdef STM32
+ // 获取CPU唯一的ID
+ id[0] = *(uint32_t *)(UID_BASE);
+ id[1] = *(uint32_t *)(UID_BASE + 4);
+ id[2] = *(uint32_t *)(UID_BASE + 8);
+#endif
+}
+
uint32_t cpu_encrypt(void)
{
uint32_t cpuid[3];
@@ -273,6 +283,39 @@ uint32_t crc32_compute(const uint8_t *const data, uint16_t length)
return crc ^ 0xFFFFFFFF;
}
+/**
+ * @brief 计算 64 位 CRC 值
+ *
+ * 根据给定的数据块和长度,使用 AES-CMAC 算法和 CRC32 算法计算 64 位 CRC 值。
+ * 使用这个函数heap设置0x800
+ *
+ * @param data 数据块指针
+ * @param length 数据块长度
+ *
+ * @return 返回计算得到的 64 位 CRC 值
+ */
+uint64_t crc64_compute(const uint8_t *const data, const uint16_t length)
+{
+ uint8_t cmac_key[] = {
+ 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6,
+ 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C}; // 密钥
+ uint8_t dst[4];
+ uint8_t mic[16];
+ uint8_t *p;
+ uint32_t lo = 0, hi = 0;
+ AES_CMAC_CTX AesCmacCtx[1]; // 密钥扩展表
+ AES_CMAC_Init(AesCmacCtx); // 完成密钥扩展表的初始化
+ AES_CMAC_SetKey(AesCmacCtx, cmac_key); // 完成密钥扩展表数据 // 存放生成校验数据的数组
+ AES_CMAC_Update(AesCmacCtx, data, length & 0xFF); // 完成数据的奇偶校验
+ AES_CMAC_Final(mic, AesCmacCtx); // 生成16个字节的校验表
+ uint32_t xor_vol = (uint32_t)((uint32_t)mic[3] << 24 | (uint32_t)mic[2] << 16 | (uint32_t)mic[1] << 8 | (uint32_t)mic[0]); // 取表4个字节作为校验码
+ p = (uint8_t *)&xor_vol;
+ osel_memcpy(dst, p, 4);
+ lo = (uint32_t)dst[0] << 24 | (uint32_t)dst[1] << 16 | (uint32_t)dst[2] << 8 | (uint32_t)dst[3];
+ hi = crc32_compute(data, length);
+ return ((uint64_t)hi << 32) | lo;
+}
+
/**
* 计算并返回指定数据区域异或的值
*
@@ -310,9 +353,9 @@ uint8_t get_bit_num(uint8_t bit)
}
// 通过bit位获取置1的位置
-BOOL is_bit_set(int x, int k)
+BOOL is_bit_set(int32_t x, int32_t k)
{
- int mask = 1 << k;
+ int32_t mask = 1 << k;
return (x & mask) != 0;
}
@@ -331,18 +374,109 @@ BOOL is_same_value(uint8_t *buf, uint16_t len, uint8_t value)
}
// 检查是否是闰年
-uint8_t is_leap(uint16_t year)
+uint8_t is_leap_year(uint16_t year)
{
return (year % 400 == 0) || (year % 100 != 0 && year % 4 == 0);
}
+// 计算从1970年1月1日到给定年月日的天数
+uint32_t days_since_1970(uint16_t year, uint8_t month, uint8_t day)
+{
+ static const uint8_t month_days[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
+ uint32_t days = 0;
+ uint16_t y = 1970;
+
+ // 计算整年过去的天数
+ while (y < year)
+ {
+ days += is_leap_year(y) ? 366 : 365;
+ y++;
+ }
+
+ // 计算当前年份中过去的天数
+ for (int32_t m = 0; m < month - 1; m++)
+ {
+ days += month_days[m];
+ if (m == 1 && is_leap_year(year))
+ { // 如果是2月且是闰年,多加一天
+ days++;
+ }
+ }
+
+ // 加上当前月的天数
+ days += day - 1; // 因为day是从1开始的,而我们需要的是从0开始的偏移量
+
+ return days;
+}
+
+// 将日期转换为秒数
+uint32_t date_to_seconds(uint16_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t minute, uint8_t second)
+{
+ uint32_t secs = 0;
+ uint32_t days = days_since_1970(year, month, day);
+ secs = days * 24 * 60 * 60; // 一天有24小时,每小时有60分钟,每分钟有60秒
+ secs += hour * 60 * 60 + minute * 60 + second;
+ return secs;
+}
+
+// 函数用于将秒数转换为日期和时间,年份4位
+void seconds_to_date(uint32_t total_seconds, rtc_date_t *date, rtc_time_t *time)
+{
+ uint16_t year = 1970; // Unix时间戳的起始年份
+ uint8_t month = 1;
+ uint8_t day = 1;
+ uint32_t seconds = total_seconds;
+ uint8_t hours, minutes, secs;
+
+ // 正确处理小时、分钟和秒
+ hours = (seconds / 3600) % 24;
+ minutes = (seconds / 60) % 60;
+ secs = seconds % 60;
+
+ // 计算日期
+ uint32_t days = total_seconds / (24 * 3600);
+ seconds = total_seconds % (24 * 3600); // 更新seconds为剩余秒数
+
+ for (; days > 0; days--)
+ {
+ // 当前月份的天数
+ uint8_t days_in_month = 31;
+ if (month == 2)
+ {
+ days_in_month = is_leap_year(year) ? 29 : 28;
+ }
+ else if (month == 4 || month == 6 || month == 9 || month == 11)
+ {
+ days_in_month = 30;
+ }
+
+ if (++day > days_in_month)
+ {
+ day = 1;
+ if (++month > 12)
+ {
+ month = 1;
+ year++;
+ }
+ }
+ }
+
+ // 将结果存储到结构体中
+ date->year = year;
+ date->month = month;
+ date->day = day;
+ time->hour = hours;
+ time->minute = minutes;
+ time->second = secs;
+}
+
// 计算一年中的第几天
uint16_t dayOfyear(uint16_t year, uint8_t month, uint8_t day)
{
uint8_t month_days[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
uint16_t total;
total = day;
- if (month > 2 && is_leap(year))
+ if (month > 2 && is_leap_year(year))
total += 1;
for (uint8_t i = 0; i < month - 1; i++)
{
@@ -377,10 +511,10 @@ uint8_t hex_format_dec(uint8_t hex)
char buf[4];
osel_memset((uint8_t *)buf, 0, 4);
sprintf(buf, "%x", hex);
- int dec = 0;
- int weight = 1;
- int len = strlen(buf);
- for (int i = len - 1; i >= 0; i--)
+ int32_t dec = 0;
+ int32_t weight = 1;
+ int32_t len = strlen(buf);
+ for (int32_t i = len - 1; i >= 0; i--)
{
if (buf[i] >= '0' && buf[i] <= '9')
{
@@ -423,17 +557,18 @@ uint8_t dec_format_hex(uint8_t dec)
}
/**
- * @brief 北京时间转时间戳
+ * @brief 日期时间转时间戳
* @param {rtc_date_t} date
* @param {rtc_time_t} time
* @return {*}
- * @note
+ * @note 年份是从2000年开始的
*/
-uint32_t time2stamp(rtc_date_t *date, rtc_time_t *time)
+uint32_t time2stamp(const rtc_date_t *const date, const rtc_time_t *const time)
{
uint32_t result;
uint16_t year = date->year + 2000;
- result = (year - 1970) * 365 * 24 * 3600 + (_month_days[date->month - 1] + date->day - 1) * 24 * 3600 + (time->hour - 8) * 3600 + time->minute * 60 + time->second;
+ // (time->hour - 0) * 3600 中的0改成8是北京时间的时区
+ result = (year - 1970) * 365 * 24 * 3600 + (_month_days[date->month - 1] + date->day - 1) * 24 * 3600 + (time->hour - 0) * 3600 + time->minute * 60 + time->second;
result += (date->month > 2 && (year % 4 == 0) && (year % 100 != 0 || year % 400 == 0)) * 24 * 3600; // 闰月
year -= 1969;
result += (year / 4 - year / 100 + year / 400) * 24 * 3600; // 闰年
@@ -441,7 +576,7 @@ uint32_t time2stamp(rtc_date_t *date, rtc_time_t *time)
}
/**
- * @brief 时间戳转北京时间
+ * @brief 时间戳转日期时间
* @param {uint32_t} stamp
* @param {rtc_date_t} *date
* @param {rtc_time_t} *time
@@ -456,7 +591,7 @@ void stamp2time(uint32_t stamp, rtc_date_t *date, rtc_time_t *time)
time->second = stamp % 60;
stamp /= 60; // 获取分
time->minute = stamp % 60;
- stamp += 8 * 60;
+ // stamp += 8 * 60; // 不需要加8小时
stamp /= 60; // 获取小时
time->hour = stamp % 24;
days = stamp / 24;
@@ -500,11 +635,11 @@ static void swap(uint16_t *a, uint16_t *b)
*b = t;
}
-static int partition(uint16_t arr[], int low, int high)
+static int32_t partition(uint16_t arr[], int32_t low, int32_t high)
{
uint16_t pivot = arr[high];
- int i = (low - 1);
- for (int j = low; j <= high - 1; j++)
+ int32_t i = (low - 1);
+ for (int32_t j = low; j <= high - 1; j++)
{
if (arr[j] < pivot)
{
@@ -517,20 +652,20 @@ static int partition(uint16_t arr[], int low, int high)
}
// 快速排序
-void quicksort(uint16_t arr[], int low, int high)
+void quicksort(uint16_t arr[], int32_t low, int32_t high)
{
if (low < high)
{
- int pi = partition(arr, low, high);
+ int32_t pi = partition(arr, low, high);
quicksort(arr, low, pi - 1);
quicksort(arr, pi + 1, high);
}
}
// 插入排序 数据集小的时候效率高
-void insertion_sort(uint16_t arr[], uint8_t n)
+void insertion_sort(uint16_t arr[], uint16_t n)
{
- uint8_t i, j;
+ uint16_t i, j;
uint16_t key;
for (i = 1; i < n; i++)
{
@@ -546,3 +681,113 @@ void insertion_sort(uint16_t arr[], uint8_t n)
arr[j] = key;
}
}
+
+/**************************线性拟合**************************/
+/**
+ * @brief 计算平均值
+ *
+ * 根据给定的点集和指示标志,计算 X 或 Y 坐标的平均值。
+ *
+ * @param points 点集指针
+ * @param count 点集数量
+ * @param isX 是否计算 X 坐标的平均值,为 1 则计算 X 坐标的平均值,为 0 则计算 Y 坐标的平均值
+ *
+ * @return 返回计算得到的平均值
+ */
+static float32 average(const point_t *points, int32_t count, int32_t isX)
+{
+ float32 sum = 0.0f;
+ for (int32_t i = 0; i < count; ++i)
+ {
+ sum += isX ? points[i].x : points[i].y;
+ }
+ return sum / count;
+}
+
+/**
+ * @brief 计算线性回归函数值
+ *
+ * 根据给定的 x 值和线性函数参数,计算并返回线性回归函数的值。 y = a * x + b
+ *
+ * @param x 输入的 x 值
+ * @param param 线性函数参数结构体,包含斜率 a 和截距 b
+ *
+ * @return 线性回归函数的值
+ */
+static float32 calculate_linear_regression_func(float32 x, linear_func_param_t param)
+{
+ return param.a * x + param.b;
+}
+
+/**
+ * @brief 计算线性回归参数
+ *
+ * 根据给定的数据点集合,计算线性回归的参数。
+ *
+ * @param points 数据点集合指针
+ * @param count 数据点数量
+ *
+ * @return 线性回归参数结构体
+ *
+ * @note 如果数据点数量少于2,则会输出错误日志并断言失败
+ */
+linear_func_param_t calculate_linear_regression(const point_t *points, int32_t count)
+{
+ if (count < 2)
+ {
+ LOG_PRINT("参数points至少需要两组数据\n");
+ DBG_ASSERT(FALSE __DBG_LINE);
+ }
+
+ float32 xAverage = average(points, count, 1);
+ float32 yAverage = average(points, count, 0);
+ float32 sumXY = 0.0, sumXX = 0.0;
+
+ for (int32_t i = 0; i < count; ++i)
+ {
+ float32 dX = points[i].x - xAverage;
+ float32 dY = points[i].y - yAverage;
+ sumXY += dX * dY;
+ sumXX += dX * dX;
+ }
+
+ linear_func_param_t result;
+ result.a = sumXY / sumXX;
+ result.b = yAverage - result.a * xAverage;
+ return result;
+}
+
+// 求线性度 公式 dYmax / Y * 100%
+float32 get_linearity_value(const point_t *points, int32_t count, linear_func_param_t param)
+{
+ float32 dYMax = 0.0f;
+ for (int32_t i = 0; i < count; ++i)
+ {
+ float32 y = calculate_linear_regression_func(points[i].x, param);
+ float32 dY = ABS(y - points[i].y);
+ if (dY > dYMax)
+ dYMax = dY;
+ }
+
+ float32 yFirst = calculate_linear_regression_func(points[0].x, param);
+ float32 yLast = calculate_linear_regression_func(points[count - 1].x, param);
+ return dYMax / ABS(yLast - yFirst) * 100;
+}
+
+/**
+ // 示例使用
+int main()
+{
+ point_t points[] = {{1, 2}, {2, 3}, {3, 4}}; // 示例点数组
+ int count = sizeof(points) / sizeof(points[0]);
+ linear_func_param_t param = calculate_linear_regression(points, count);
+ printf("Linear Regression: y = %f * x + %f\n", param.a, param.b);
+
+ double linearity = get_linearity_value(points, count, param);
+ printf("Linearity Value: %f%%\n", linearity);
+
+ return 0;
+}
+ */
+
+/**************************线性拟合**************************/
diff --git a/User/lib/src/malloc.c b/User/hart/lib/src/malloc.c
similarity index 100%
rename from User/lib/src/malloc.c
rename to User/hart/lib/src/malloc.c
diff --git a/User/lib/src/mlist.c b/User/hart/lib/src/mlist.c
similarity index 100%
rename from User/lib/src/mlist.c
rename to User/hart/lib/src/mlist.c
diff --git a/User/lib/src/pbuf.c b/User/hart/lib/src/pbuf.c
similarity index 100%
rename from User/lib/src/pbuf.c
rename to User/hart/lib/src/pbuf.c
diff --git a/User/lib/src/sqqueue.c b/User/hart/lib/src/sqqueue.c
similarity index 100%
rename from User/lib/src/sqqueue.c
rename to User/hart/lib/src/sqqueue.c
diff --git a/User/hart/lib/src/wl_flash.c b/User/hart/lib/src/wl_flash.c
new file mode 100644
index 0000000..10cd9eb
--- /dev/null
+++ b/User/hart/lib/src/wl_flash.c
@@ -0,0 +1,314 @@
+#include "wl_flash.h"
+#include
+static BOOL flash_is_written(wl_flash_t *cfg, uint32_t address, uint16_t length);
+
+/**
+ * @brief 初始化闪存
+ *
+ * 根据给定的闪存配置信息,初始化闪存的相关参数和状态。
+ *
+ * @param cfg 闪存配置结构体指针
+ *
+ * @note 该函数会检查cfg是否为空,并断言cfg中的srand、read、write、erase_page操作均不为空。
+ * @note 同时还会检查FLASH页大小是否为2的幂次方,FLASH长度是否为页大小的整数倍,以及FLASH长度是否大于等于data_size。
+ * @note 如果data_size不是write_gran的整数倍,则会向上取整。
+ * @note 初始化完成后,将更新起始地址、起始页号、总页数、数据块所占页数和剩余大小等参数。
+ */
+void wl_flash_init(wl_flash_t *cfg)
+{
+ // 断言cfg不为空
+ DBG_ASSERT(cfg != NULL __DBG_LINE);
+
+ // 断言cfg中的srand操作不为空
+ DBG_ASSERT(cfg->ops.srand != NULL __DBG_LINE);
+ // 断言cfg中的read操作不为空
+ DBG_ASSERT(cfg->ops.read != NULL __DBG_LINE);
+ // 断言cfg中的write操作不为空
+ DBG_ASSERT(cfg->ops.write != NULL __DBG_LINE);
+ // 断言cfg中的erase_page操作不为空
+ DBG_ASSERT(cfg->ops.erase_page != NULL __DBG_LINE);
+
+ // 检查FLASH页大小是否为2的幂次方
+ // 检查FLASH页大小
+ DBG_ASSERT((cfg->page_size & (cfg->page_size - 1)) == 0 __DBG_LINE);
+
+ // 检查FLASH长度是否为页大小的整数倍
+ // 检查FLASH长度
+ DBG_ASSERT(cfg->len % cfg->page_size == 0 __DBG_LINE);
+
+ // 如果data_size不是write_gran的整数倍,则向上取整
+ if (cfg->data_size % cfg->write_gran != 0)
+ {
+ cfg->data_size = (cfg->data_size / cfg->write_gran + 1) * cfg->write_gran;
+ }
+
+ // 断言FLASH长度大于等于data_size
+ DBG_ASSERT(cfg->len >= cfg->data_size __DBG_LINE);
+
+ // 初始化起始地址、起始页号、总页数、数据块所占页数和剩余大小
+ cfg->private.current_address = cfg->addr;
+ cfg->private.start_page = cfg->addr / cfg->page_size;
+ cfg->private.page_total = cfg->len / cfg->page_size;
+ if (cfg->wl_flag == TRUE)
+ {
+ cfg->private.block_page = cfg->data_size / cfg->page_size + (cfg->data_size % cfg->page_size != 0 ? 1 : 0);
+ }
+ else
+ {
+ cfg->private.block_page = cfg->private.page_total;
+ }
+
+ cfg->private.residue_size = cfg->private.block_page * cfg->page_size;
+}
+
+/**
+ * @brief 擦除指定范围内的闪存
+ *
+ * 根据给定的闪存配置信息,擦除指定范围内的闪存页面。
+ *
+ * @param cfg 闪存配置结构体指针
+ *
+ * @note 调用此函数前,请确保 cfg 不为 NULL,并且 cfg 中的 srand、erase_page 函数指针不为 NULL,
+ * write_gran 不为 0。
+ *
+ * @see DBG_ASSERT 宏定义用于断言条件
+ */
+void wl_flash_erase(wl_flash_t *cfg)
+{
+ // 断言cfg不为空
+ DBG_ASSERT(cfg != NULL __DBG_LINE);
+ // 断言cfg->ops.srand不为空
+ DBG_ASSERT(cfg->ops.srand != NULL __DBG_LINE);
+ // 断言cfg->ops.erase_page不为空
+ DBG_ASSERT(cfg->ops.erase_page != NULL __DBG_LINE);
+ // 断言cfg->write_gran不为0
+ DBG_ASSERT(cfg->write_gran != 0 __DBG_LINE);
+ // 断言cfg->private.page_total不为0
+ DBG_ASSERT(cfg->private.page_total != 0 __DBG_LINE);
+
+ // 计算起始页号
+ uint16_t start_page = cfg->addr / cfg->page_size;
+ // 计算结束页号
+ uint16_t end_page = (cfg->addr + cfg->len) / cfg->page_size;
+
+ // 遍历起始页号到结束页号的每个页
+ for (uint16_t i = start_page; i < end_page; i++)
+ {
+ // 如果该页已被写入
+ if (flash_is_written(cfg, i * cfg->page_size, cfg->page_size) == TRUE)
+ {
+ // 擦除该页
+ cfg->ops.erase_page(i);
+ }
+ }
+
+ // 如果wl_flag为TRUE
+ if (cfg->wl_flag == TRUE)
+ {
+ // 调用srand函数
+ cfg->ops.srand();
+ // 计算最大值,这里减去一是为了防止超出范围
+ uint16_t max = cfg->private.page_total / cfg->private.block_page - 1; // 这里减去一是为了防止超出范围
+ // 计算当前地址
+ cfg->private.current_address = cfg->addr + (rand() % max) * cfg->private.block_page * cfg->page_size;
+ // 设置剩余大小为block_page个页的大小
+ cfg->private.residue_size = cfg->private.block_page * cfg->page_size;
+ }
+ else
+ {
+ // 否则,将当前地址设置为cfg->addr
+ cfg->private.current_address = cfg->addr;
+ // 设置剩余大小为block_page个页的大小
+ cfg->private.residue_size = cfg->private.block_page * cfg->page_size;
+ }
+}
+
+/**
+ * @brief 获取当前闪存地址
+ *
+ * 从给定的闪存配置结构体中获取当前闪存的地址。
+ *
+ * @param cfg 闪存配置结构体指针
+ *
+ * @return 当前闪存的地址值
+ */
+uint32_t wl_flash_get_current_address(wl_flash_t *cfg)
+{
+ return cfg->private.current_address;
+}
+
+/**
+ * @brief 设置下一个闪存地址
+ *
+ * 根据给定的闪存配置信息,设置下一个要写入数据的闪存地址。
+ *
+ * @param cfg 闪存配置指针
+ *
+ * @note 传入参数不能为空
+ */
+void wl_flash_set_next_address(wl_flash_t *cfg)
+{
+ DBG_ASSERT(cfg != NULL __DBG_LINE);
+ // 断言cfg->private.page_total不为0
+ DBG_ASSERT(cfg->private.page_total != 0 __DBG_LINE);
+ BOOL switch_page = FALSE;
+ uint16_t current_page = cfg->private.current_address / cfg->page_size;
+ if (cfg->wl_flag == TRUE)
+ {
+ // 判断是否需要换到下一个block
+ if ((cfg->private.residue_size - cfg->data_size) < cfg->data_size)
+ {
+ current_page += cfg->private.block_page;
+ cfg->private.current_address = current_page * cfg->page_size;
+ cfg->private.residue_size = cfg->private.block_page * cfg->page_size;
+ switch_page = TRUE;
+ }
+ else
+ {
+ // 有空间可以写入,当前写入地址偏移
+ cfg->private.current_address += cfg->data_size;
+ cfg->private.residue_size -= cfg->data_size;
+ }
+
+ if (cfg->private.current_address + cfg->data_size > cfg->addr + cfg->len)
+ {
+ cfg->private.current_address = cfg->addr;
+ cfg->private.residue_size = cfg->private.block_page * cfg->page_size;
+ switch_page = TRUE;
+ }
+ }
+ else
+ {
+ // 不使用平衡擦写默认都使用第一页
+ cfg->private.current_address = cfg->addr;
+ cfg->private.residue_size = cfg->private.block_page * cfg->page_size;
+ switch_page = TRUE;
+ }
+
+ // 如果写入区域切换到下一个block,则判断是否需要擦除
+ if (switch_page == TRUE)
+ {
+ // 判断准备写入的区域是否已经写入过数据
+ for (uint8_t i = 0; i < cfg->private.block_page; i++)
+ {
+ uint32_t current_address = cfg->private.current_address + (i * cfg->page_size);
+ if (flash_is_written(cfg, current_address, cfg->page_size) == TRUE)
+ {
+ cfg->ops.erase_page(current_address / cfg->page_size);
+ }
+ }
+ }
+}
+
+/**
+ * @brief 设置当前 Flash 地址
+ *
+ * 将给定的地址设置为 Flash 设备的当前地址。
+ *
+ * @param cfg Flash 配置结构体指针
+ * @param address 要设置的 Flash 地址
+ */
+void wl_flash_set_current_address(wl_flash_t *cfg, uint32_t address)
+{
+ uint16_t current_page = address / cfg->page_size;
+ uint16_t current_block_page_num = (current_page - cfg->private.start_page) / cfg->private.block_page; // 确定当前的地址在第几个block_page中
+ uint32_t current_page_start_address = cfg->addr + current_block_page_num * cfg->page_size * cfg->private.block_page; // 当前block_page的起始地址
+ cfg->private.current_address = address;
+ // 根据当前地址更新剩余可写字节
+ cfg->private.residue_size = cfg->private.block_page * cfg->page_size - (address - current_page_start_address);
+}
+
+/**
+ * @brief 写入数据到闪存
+ *
+ * 根据给定的配置,将数据写入到闪存中。
+ *
+ * @param cfg 闪存配置结构体指针
+ * @param buf 要写入的数据缓冲区指针
+ * @param size 要写入的数据大小(字节)
+ *
+ * @return 如果写入成功,则返回 TRUE;否则返回 FALSE
+ */
+BOOL wl_flash_write(wl_flash_t *cfg, const uint8_t *buf, uint16_t size)
+{
+ DBG_ASSERT(cfg != NULL __DBG_LINE);
+ DBG_ASSERT(cfg->ops.write != NULL __DBG_LINE);
+ DBG_ASSERT(cfg->write_gran != 0 __DBG_LINE);
+ DBG_ASSERT(size <= cfg->data_size __DBG_LINE);
+ // 断言cfg->private.page_total不为0
+ DBG_ASSERT(cfg->private.page_total != 0 __DBG_LINE);
+ BOOL res = FALSE;
+
+ res = cfg->ops.write(cfg->private.current_address, buf, size);
+ return res;
+}
+
+/**
+ * @brief 从指定 Flash 设备中读取数据
+ *
+ * 根据给定的 Flash 设备配置参数,从 Flash 设备的当前地址开始,读取指定长度的数据到缓冲区中。
+ *
+ * @param cfg Flash 设备配置指针
+ * @param buf 存储读取数据的缓冲区指针
+ * @param size 要读取的数据大小(以字节为单位)
+ *
+ * @return 读取操作是否成功,成功返回 TRUE,否则返回 FALSE
+ *
+ * @note 调用此函数前,需要确保 Flash 设备配置正确,并且 read 操作函数已设置
+ *
+ * @warning 请注意检查函数返回结果,以确保数据读取操作成功
+ */
+BOOL wl_flash_read(wl_flash_t *cfg, uint8_t *buf, uint16_t size)
+{
+ DBG_ASSERT(cfg != NULL __DBG_LINE);
+ // 断言cfg->private.page_total不为0
+ DBG_ASSERT(cfg->private.page_total != 0 __DBG_LINE);
+ DBG_ASSERT(cfg->ops.read != NULL __DBG_LINE);
+ return cfg->ops.read(cfg->private.current_address, buf, size);
+}
+
+static BOOL flash_is_written(wl_flash_t *cfg, uint32_t address, uint16_t length)
+{
+ DBG_ASSERT(cfg != NULL __DBG_LINE);
+ DBG_ASSERT(cfg->ops.read != NULL __DBG_LINE);
+ uint8_t *data;
+ uint16_t count = 0;
+ BOOL res = FALSE, ret = FALSE;
+ count = length / cfg->page_size;
+ if (length % cfg->page_size != 0)
+ {
+ count++;
+ }
+ data = osel_mem_alloc(cfg->page_size);
+ DBG_ASSERT(data != NULL __DBG_LINE);
+
+ for (uint16_t i = 0; i < count; i++)
+ {
+ ret = cfg->ops.read(address + i * cfg->page_size, data, cfg->page_size);
+ if (ret == TRUE)
+ {
+ for (uint16_t j = 0; j < cfg->page_size; j++)
+ {
+ if (data[j] != 0xff)
+ {
+ res = TRUE;
+ break;
+ }
+ }
+ }
+ else
+ {
+ res = FALSE;
+ break;
+ }
+
+ if (res == TRUE)
+ {
+ break;
+ }
+ res = FALSE;
+ ret = FALSE;
+ }
+ osel_mem_free(data);
+ return res;
+}
diff --git a/User/hart/master/inc/hart_master.h b/User/hart/master/inc/hart_master.h
new file mode 100644
index 0000000..b87ff72
--- /dev/null
+++ b/User/hart/master/inc/hart_master.h
@@ -0,0 +1,28 @@
+/***
+ * @Author:
+ * @Date: 2023-03-20 19:27:47
+ * @LastEditors: xxx
+ * @LastEditTime: 2023-03-30 00:31:58
+ * @FilePath: \hart\hart\inc\hart_master.h
+ * @Description: hart主机处理
+ * @email:
+ * @Copyright (c) 2023 by xxx, All Rights Reserved.
+ */
+
+#ifndef __HART_MASTER_H__
+#define __HART_MASTER_H__
+#include "lib.h"
+#include "./hart_master_frame.h"
+#pragma pack(1)
+typedef struct
+{
+ uint8_t address_bit; // 为1时表示基本主设备,为0时表示副主设备
+ response_cb response_call; // 回复消息接口
+ hart_response_t *response;
+} hart_master_init_t;
+#pragma pack()
+
+extern BOOL hart_master_init(const hart_master_init_t *const init);
+extern BOOL hart_master_handle(uint8_t *rxBuf, uint16_t len);
+extern BOOL hart_master_command_req(const hart_command_req_t *const req); // 主机请求指令接口
+#endif // __HART_MASTER_H__
diff --git a/User/hart/master/inc/hart_master_frame.h b/User/hart/master/inc/hart_master_frame.h
new file mode 100644
index 0000000..33ad6e0
--- /dev/null
+++ b/User/hart/master/inc/hart_master_frame.h
@@ -0,0 +1,8 @@
+#ifndef __HART_MASTER_FRAME_H__
+#define __HART_MASTER_FRAME_H__
+#include "../../inc/hart_frame.h"
+
+extern hart_master_attribute_t hart_master_attribute; // 主机属性
+
+extern void mock_master_attribute(void);
+#endif
diff --git a/User/hart/master/inc/hart_master_req.h b/User/hart/master/inc/hart_master_req.h
new file mode 100644
index 0000000..9d7080b
--- /dev/null
+++ b/User/hart/master/inc/hart_master_req.h
@@ -0,0 +1,7 @@
+#ifndef __HART_MASTER_REQ_H__
+#define __HART_MASTER_REQ_H__
+#include "./hart_master_frame.h"
+
+extern BOOL hart_master_req_init(const hart_master_init_t *const init);
+extern void hart_master_req_init_user(void);
+#endif // __HART_MASTER_REQ_H__
diff --git a/User/hart/master/inc/hart_master_rsp.h b/User/hart/master/inc/hart_master_rsp.h
new file mode 100644
index 0000000..20577c7
--- /dev/null
+++ b/User/hart/master/inc/hart_master_rsp.h
@@ -0,0 +1,39 @@
+#ifndef __HART_MASTER_RSP_H__
+#define __HART_MASTER_RSP_H__
+
+#include "./hart_master_frame.h"
+
+#pragma pack(1)
+typedef struct
+{
+ uint8_t card_index;
+ uint8_t channel_index;
+ io_system_device_t *device;
+} io_system_device_info_t;
+typedef union
+{
+ hart_command_75_t command_75; // 轮询子设备
+ hart_command_84_t command_84; // 读取子设备标识摘要
+ hart_command_85_t command_85; // 读取I/O通道统计信息
+ hart_command_86_t command_86; // 读取子设备统计信息
+ hart_command_87_t command_87; // 写入I/O系统主模式
+ hart_command_88_t command_88; // 写入重试计数
+} hart_command_rsp_data_u; // HART请求指令数据域
+typedef struct
+{
+ uint8_t address[HART_LONG_ADDRESS_LEN]; // 短帧地址1个字节,长帧地址5个字节,上位机发送时从低位到高位填充,例如短地址:0x01,长地址:0x00 0x00 0x00 0x00 0x01
+ uint8_t address_length; // 地址长度
+ uint32_t command; // HART命令码
+ hart_command_rsp_data_u data; // 数据域
+
+ // 以下解析数据后填充
+ hart_delimiter_u delimiter;
+ uint8_t data_length; // 数据域长度
+} hart_command_rsp_t; // 主机请求指令接口参数定义:hart_master_command_req
+
+#pragma pack()
+
+extern BOOL (*hart_command_rsp_ptr_arr[HART_COMMAND_MAX])(const hart_command_rsp_t *const data, hart_response_t *resp);
+
+extern BOOL hart_master_rsp_init(const hart_master_init_t *const init);
+#endif // __HART_MASTER_RSP_H__
diff --git a/User/hart/master/src/hart_master.c b/User/hart/master/src/hart_master.c
new file mode 100644
index 0000000..14f071c
--- /dev/null
+++ b/User/hart/master/src/hart_master.c
@@ -0,0 +1,212 @@
+/*
+ * @Author:
+ * @Date: 2023-03-20 19:27:47
+ * @LastEditors: xxx
+ * @LastEditTime: 2023-06-05 11:28:41
+ * @FilePath: \hart\hart\hart_master.c
+ * @Description:
+ * email:
+ * Copyright (c) 2023 by xxx, All Rights Reserved.
+ */
+
+#include "../inc/hart_master.h"
+#include "../inc/hart_master_req.h"
+#include "../inc/hart_master_rsp.h"
+
+#ifdef MASTER
+static hart_master_init_t *handle;
+
+// 内部状态检查
+static response_communication_code_e hart_master_state_check(uint8_t command)
+{
+ // 检查是否开启的写保护
+ if (hart_is_write_command(command))
+ {
+ if (WRITE_PROTECT_CODE_WRITE_PROTECT == hart_master_attribute.io_system.write_protect_code)
+ {
+ return RESPONSE_COMMUNICATION_CODE_7;
+ }
+ }
+ return RESPONSE_COMMUNICATION_CODE_0;
+}
+
+/**
+ * @briefhart主机处理函数
+ * @param {uint8_t} *rxBuf
+ * @param {uint16_t} len
+ * @return {*}
+ */
+BOOL hart_master_handle(uint8_t *rxBuf, uint16_t len)
+{
+ if (!DBG_ASSERT(rxBuf != NULL __DBG_LINE))
+ return FALSE;
+ if (!DBG_ASSERT(len != 0 __DBG_LINE))
+ return FALSE;
+ uint8_t xor = 0; // 异或校验
+ uint8_t front = 0;
+ uint8_t command_length = 0;
+ hart_short_address_u poll_address;
+ hart_long_address_u long_address;
+ hart_delimiter_u delimiter;
+ hart_command_rsp_t rsp;
+ uint16_t offset = 0;
+ uint8_t rsp_len = 0; // 响应数据长度
+ uint8_t xor = 0; // 异或校验
+ uint8_t preamble_def = HART_PREAMBLE_DEFAULT_LEN; // 引导码长度
+ uint8_t *data_start_p = NULL;
+
+ // 查找前导符
+ while (len > 0)
+ {
+ if (*rxBuf != HART_PREAMBLE && front == HART_PREAMBLE)
+ break;
+ else
+ {
+ front = *rxBuf;
+ rxBuf++;
+ len--;
+ }
+ }
+
+ if (len < 2) // 前导符后至少有2个字节
+ return FALSE;
+
+ xor = xor_compute(rxBuf, len - 1); // 异或校验
+
+ if (xor != rxBuf[len - 1])
+ {
+ LOG_PRINT("[hart_handle] xro error");
+ return FALSE; // 校验错误
+ }
+
+ delimiter.data = 0;
+ osel_memset((uint8_t *)&poll_address, 0, sizeof(hart_short_address_u));
+ osel_memset((uint8_t *)&long_address, 0, sizeof(hart_long_address_u));
+ osel_memset((uint8_t *)&rsp, 0, sizeof(hart_command_rsp_t));
+
+ handle->response->code = RESPONSE_COMMUNICATION_CODE_0;
+ handle->response->data_length = 0;
+ handle->response->data_p = handle->response->data;
+ osel_memset((uint8_t *)handle->response->data, 0, HART_RESPONSE_MAX_LEN);
+
+ hart_delimiter_u *delimiter_p = (hart_delimiter_u *)&rxBuf[offset];
+ rsp.delimiter.data = delimiter_p->data;
+ offset++;
+ if (delimiter_p->bits.addr_type == HART_DELIMITER_TYPE_SHORT)
+ {
+ poll_address.data = rxBuf[offset];
+ uint8_t tmp = poll_address.bits.slave;
+ rsp.address_length = HART_SHORT_ADDRESS_LEN;
+ rsp.address[0] = tmp;
+ }
+ else
+ {
+ osel_memcpy((uint8_t *)&long_address.data, &rxBuf[offset], sizeof(uint40_t));
+ uint8_t tmp[HART_LONG_ADDRESS_LEN];
+ osel_memset(tmp, 0, HART_LONG_ADDRESS_LEN);
+ tmp[0] = long_address.bits.reserved;
+ osel_memcpy(&tmp[1], (uint8_t *)&long_address.bits.slave, 4);
+ rsp.address_length = HART_LONG_ADDRESS_LEN;
+ osel_memcpy(rsp.address, tmp, HART_LONG_ADDRESS_LEN);
+ }
+ offset += rsp.address_length;
+
+ // 根据界定符中的扩展字节数量来确定命令码
+ command_length = delimiter_p->bits.ext_bytes + 1;
+ osel_memcpy((uint8_t *)&rsp.command, &rxBuf[offset], command_length);
+ offset += command_length;
+
+ rsp.data_length = rxBuf[offset++];
+
+ osel_memcpy((uint8_t *)&rsp.data, &rxBuf[offset], rsp.data_length); // 根据数据长度复制数据
+ offset += rsp.data_length;
+
+ if (hart_command_rsp_ptr_arr[rsp.command] == FALSE)
+ {
+ return FALSE;
+ }
+
+ // 填充回复数据
+ for (uint8_t i = 0; i < preamble_def; i++)
+ {
+ *handle->response->data_p++ = HART_PREAMBLE;
+ }
+ // 填充界定符
+ delimiter.bits.frame_type = HART_ACK_FRAME; // 应答帧
+ delimiter.bits.addr_type = delimiter_p->bits.addr_type;
+ *handle->response->data_p++ = delimiter.data;
+ // 填充地址
+ if (delimiter.bits.addr_type == HART_DELIMITER_TYPE_SHORT)
+ {
+ *handle->response->data_p++ = poll_address.data;
+ }
+ else
+ {
+ osel_memcpy(handle->response->data_p, (uint8_t *)&long_address.data, HART_LONG_ADDRESS_LEN); // 长地址5个字节
+ handle->response->data_p += HART_LONG_ADDRESS_LEN;
+ }
+ // 填充命令
+ osel_memcpy(handle->response->data_p, (uint8_t *)&rsp.command, command_length);
+ handle->response->data_p += command_length;
+
+ hart_frame_data_length_start(&handle->response->data_p);
+ hart_frame_response_code_start(&handle->response->data_p);
+ data_start_p = handle->response->data_p;
+
+ handle->response->code = hart_master_state_check(rsp.command); // 内部状态检查
+
+ if (RESPONSE_COMMUNICATION_CODE_0 == handle->response->code)
+ {
+ if (FALSE == hart_command_rsp_ptr_arr[rsp.command](&rsp, handle->response))
+ {
+ return FALSE;
+ }
+ }
+
+ hart_frame_data_length_end(handle->response->data_p);
+ hart_frame_response_communication_code(handle->response->code);
+ hart_frame_master_response_operate_code();
+
+ // 根据载荷区数据长度判断是否需要发送
+ if ((handle->response->data_p - data_start_p) > 0 || handle->response->code != RESPONSE_COMMUNICATION_CODE_0)
+ {
+ rsp_len = handle->response->data_p - handle->response->data;
+ xor = xor_compute(&handle->response->data[preamble_def], (rsp_len - preamble_def)); // 除前导码和校验字节外所有字节的异或之后
+ *handle->response->data_p++ = xor;
+ rsp_len++;
+ handle->response->data_length = rsp_len;
+ handle->response_call(0, handle->response->data, handle->response->data_length);
+ }
+
+ return TRUE;
+}
+
+/**
+ * @brief 主机初始化
+ * @param {hart_master_init_t} *init
+ * @return {*}
+ */
+BOOL hart_master_init(const hart_master_init_t *const init)
+{
+ if (!DBG_ASSERT(init != NULL __DBG_LINE))
+ return FALSE;
+ handle = (hart_master_init_t *)init;
+
+ osel_memset((uint8_t *)&hart_master_attribute, 0, sizeof(hart_master_attribute_t));
+ if (!DBG_ASSERT(hart_master_req_init(init) __DBG_LINE))
+ return FALSE;
+
+ if (!DBG_ASSERT(hart_master_rsp_init(init) __DBG_LINE))
+ return FALSE;
+ return TRUE;
+}
+#else
+BOOL hart_master_handle(uint8_t *rxBuf, uint16_t len)
+{
+ return TRUE;
+}
+BOOL hart_master_init(const hart_master_init_t *const init)
+{
+ return TRUE;
+}
+#endif
diff --git a/User/hart/master/src/hart_master_frame.c b/User/hart/master/src/hart_master_frame.c
new file mode 100644
index 0000000..afeaa2c
--- /dev/null
+++ b/User/hart/master/src/hart_master_frame.c
@@ -0,0 +1,39 @@
+/*
+ * @Author: wangxujie-laptop 390834610@qq.com
+ * @Date: 2024-08-28 13:47:17
+ * @LastEditors: wangxujie-laptop 390834610@qq.com
+ * @LastEditTime: 2024-08-28 14:11:53
+ * @FilePath: \controller-v2\User\hart\master\src\hart_master_frame.c
+ * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+ */
+#include "../inc/hart_master_frame.h"
+
+hart_master_attribute_t hart_master_attribute; // 主机属性
+
+static BOOL has_mock = FALSE; // 测试使用该变量判断是否重入
+void mock_master_attribute(void)
+{
+ if (TRUE == has_mock)
+ {
+ return;
+ }
+ io_system_device_t *device = &hart_master_attribute.io_system.cards[0].channels[0].devices[0];
+ device->identifier = 0xA001;
+ device->online = TRUE;
+ device->extended_device_type = EXTENDED_DEVICE_TYPE_GSDT_GPS2000;
+ device->m2s_preambles_limit_count = HART_PREAMBLE_DEFAULT_LEN;
+ device->hart_revision = HART_PROTOCOL_VERSION_7;
+ device->device_revision = 1;
+ device->device_software_revision = 1;
+ device->device_hardware_revision.bits.hardware_revision = 1;
+ device->device_hardware_revision.bits.physical_signaling_code = PHYSICAL_SIGNALS_2;
+ device->device_id[0] = 0x01;
+ device->device_id[1] = 0x02;
+ device->device_id[2] = 0x03;
+ device->s2m_preambles = HART_PREAMBLE_DEFAULT_LEN;
+ device->last_device_variable = DIN_246;
+ device->extended_device_status = EXTENDED_DEVICE_STATUS_1;
+ device->manufacturer_identification_code = MANUFACTURER_IDENTIFICATION_CODE;
+ device->private_label_distributor_code = MANUFACTURER_IDENTIFICATION_CODE;
+ device->device_profile = DEVICE_CONFIGURATION_FILE_CODE_68;
+}
diff --git a/User/hart/master/src/hart_master_req.c b/User/hart/master/src/hart_master_req.c
new file mode 100644
index 0000000..05f3ed3
--- /dev/null
+++ b/User/hart/master/src/hart_master_req.c
@@ -0,0 +1,1253 @@
+#include "../inc/hart_master.h"
+#include "../inc/hart_master_req.h"
+
+static hart_master_init_t *handle;
+
+// 主机请求指令
+
+/**
+ * @brief hart主机请求指令不需要携带数据域
+ * @param {hart_command_req_data_u} *data: 请求指令数据
+ * @param {uint8_t} **resp: 待填充数据的区间,指针的指针
+ * @return: TRUE: 处理成功
+ * FALSE: 处理失败
+ */
+BOOL hart_master_command_without_data_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ // 数据个数为0不需要填充数据域
+ return TRUE;
+}
+
+/**
+ * @brief 写入轮训地址
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+BOOL hart_master_command_6_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ *resp->data_p++ = req->data.command_6.poll_address; // 设备的轮询地址
+ if (hart_get_current_protocol_version() == HART_PROTOCOL_VERSION_7)
+ {
+ *resp->data_p++ = req->data.command_6.loop_current_mode; // 回路电流模式
+ }
+ return TRUE;
+}
+/**
+ * @brief 读取具有状态的设备变量
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+BOOL hart_master_command_9_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ *resp->data_p++ = DIN_245; // slot0
+ *resp->data_p++ = DIN_246; // slot1
+ *resp->data_p++ = DIN_247; // slot2
+ *resp->data_p++ = DIN_248; // slot3
+ *resp->data_p++ = DIN_249; // slot4
+ *resp->data_p++ = DIN_250; // slot5
+ *resp->data_p++ = DIN_250; // slot6
+ *resp->data_p++ = DIN_250; // slot7
+ return TRUE;
+}
+
+/**
+ * @brief 读取与标签关联的唯一标识符V5
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+BOOL hart_master_command_11_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ for (uint8_t i = 0; i < HART_PACKED6_LEN; i++)
+ {
+ *resp->data_p++ = req->data.command_11.tag[i];
+ }
+ return TRUE;
+}
+
+/**
+ * @brief 写入消息V5
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+BOOL hart_master_command_17_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ for (uint8_t i = 0; i < HART_PACKED24_LEN; i++)
+ {
+ *resp->data_p++ = req->data.command_17.message[i];
+ }
+ return TRUE;
+}
+
+/**
+ * @brief 写标签、描述符、日期
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+BOOL hart_master_command_18_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ for (uint8_t i = 0; i < HART_PACKED6_LEN; i++)
+ {
+ *resp->data_p++ = req->data.command_18.tag[i];
+ }
+ for (uint8_t i = 0; i < HART_PACKED12_LEN; i++)
+ {
+ *resp->data_p++ = req->data.command_18.descriptor[i];
+ }
+ for (uint8_t i = 0; i < HART_DATE_LEN; i++)
+ {
+ *resp->data_p++ = req->data.command_18.date[i];
+ }
+ return TRUE;
+}
+
+/**
+ * @brief 编写总装编号
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+BOOL hart_master_command_19_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ osel_memcpy(resp->data_p, req->data.command_19.final_assembly_number, HART_PACKED3_LEN);
+ resp->data_p += HART_PACKED3_LEN;
+ return TRUE;
+}
+
+/**
+ * @brief 读取与长标签关联的唯一标识符
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+BOOL hart_master_command_21_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ for (uint8_t i = 0; i < HART_PACKED32_LEN; i++)
+ {
+ *resp->data_p++ = req->data.command_21.long_tag[i];
+ }
+ return TRUE;
+}
+
+/**
+ * @brief 写长标签
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+BOOL hart_master_command_22_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ for (uint8_t i = 0; i < HART_PACKED32_LEN; i++)
+ {
+ *resp->data_p++ = req->data.command_22.long_tag[i];
+ }
+ return TRUE;
+}
+
+/**
+ * @brief 重置配置更改标志
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+BOOL hart_master_command_38_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ uint16_t configuration_change_counter = req->data.command_38.configuration_change_counter;
+ configuration_change_counter = B2S_UINT16(configuration_change_counter);
+ osel_memcpy(resp->data_p, (uint8_t *)&configuration_change_counter, sizeof(uint16_t));
+ resp->data_p += sizeof(uint16_t);
+ return TRUE;
+}
+
+/**
+ * @brief 读取设备变量V5
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+BOOL hart_master_command_33_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ osel_memcpy(resp->data_p, (uint8_t *)&req->data.command_33, sizeof(hart_command_33_t));
+ resp->data_p += sizeof(hart_command_33_t);
+ return TRUE;
+}
+
+/**
+ * @brief 写入主变量阻尼值V5
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+BOOL hart_master_command_34_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ float32_u tmp;
+ tmp.f = req->data.command_34.pv_damping_value;
+ tmp.c = S2B_UINT32(tmp.c);
+ osel_memcpy(resp->data_p, (uint8_t *)&tmp, sizeof(float32_u));
+ resp->data_p += sizeof(float32_u);
+ return TRUE;
+}
+
+/**
+ * @brief 写入主变量范围值V5
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+BOOL hart_master_command_35_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ float32_u tmp;
+ *resp->data_p++ = req->data.command_35.pv_upper_and_lower_range_values_units_code;
+
+ tmp.f = req->data.command_35.pv_upper_range_value;
+ tmp.c = S2B_UINT32(tmp.c);
+ osel_memcpy(resp->data_p, (uint8_t *)&tmp, sizeof(float32_u));
+ resp->data_p += sizeof(float32_u);
+
+ tmp.f = req->data.command_35.pv_lower_range_value;
+ tmp.c = S2B_UINT32(tmp.c);
+ osel_memcpy(resp->data_p, (uint8_t *)&tmp, sizeof(float32_u));
+ resp->data_p += sizeof(float32_u);
+ return TRUE;
+}
+
+/**
+ * @brief EEPROM控制V5
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+BOOL hart_master_command_39_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ *resp->data_p++ = req->data.command_39.control_code;
+ return TRUE;
+}
+
+/**
+ * @brief 进入/退出固定电流模式V5
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+BOOL hart_master_command_40_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ float32_u tmp;
+ tmp.f = req->data.command_40.pv_fixed_current_level;
+ tmp.c = S2B_UINT32(tmp.c);
+ osel_memcpy(resp->data_p, (uint8_t *)&tmp, sizeof(float32_u));
+ resp->data_p += sizeof(float32_u);
+ return TRUE;
+}
+
+/**
+ * @brief 编写主变量单元V5
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+BOOL hart_master_command_44_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ *resp->data_p++ = req->data.command_44.pv_units_code;
+ return TRUE;
+}
+
+/**
+ * @brief 微调回路电流归零
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+BOOL hart_master_command_45_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ float32_u tmp;
+ tmp.f = req->data.command_45.pv_loop_current_level;
+ tmp.c = S2B_UINT32(tmp.c);
+ osel_memcpy(resp->data_p, (uint8_t *)&tmp, sizeof(float32_u));
+ resp->data_p += sizeof(float32_u);
+ return TRUE;
+}
+
+/**
+ * @brief 微调回路电流增益
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+BOOL hart_master_command_46_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ float32_u tmp;
+ tmp.f = req->data.command_46.pv_loop_current_level;
+ tmp.c = S2B_UINT32(tmp.c);
+ osel_memcpy(resp->data_p, (uint8_t *)&tmp, sizeof(float32_u));
+ resp->data_p += sizeof(float32_u);
+ return TRUE;
+}
+
+/**
+ * @brief 编写主变量传递函数V5
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+BOOL hart_master_command_47_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ *resp->data_p++ = req->data.command_47.pv_transfer_function_code;
+ return TRUE;
+}
+
+/**
+ * @brief 写入主变量传感器序列号V5
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+BOOL hart_master_command_49_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ osel_memcpy(resp->data_p, req->data.command_49.pv_transducer_serial_number.bs, sizeof(uint24_t));
+ resp->data_p += sizeof(uint24_t);
+ return TRUE;
+}
+
+/**
+ * @brief 编写动态变量赋值V5
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+BOOL hart_master_command_51_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ for (uint8_t i = 0; i < ARRAY_LEN(req->data.command_51.device_ariables); i++)
+ {
+ *resp->data_p++ = req->data.command_51.device_ariables[i];
+ }
+
+ return TRUE;
+}
+
+/**
+ * @brief 设置设备变量零V5
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+BOOL hart_master_command_52_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ *resp->data_p++ = req->data.command_52.device_ariable;
+ return TRUE;
+}
+
+/**
+ * @brief 写入设备变量单位V5
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+BOOL hart_master_command_53_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ osel_memcpy(resp->data_p, (uint8_t *)&req->data.command_53.device_ariable, sizeof(hart_command_53_t));
+ resp->data_p += sizeof(hart_command_53_t);
+ return TRUE;
+}
+
+/**
+ * @brief 读取设备变量信息V5
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+BOOL hart_master_command_54_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ *resp->data_p++ = req->data.command_54.device_ariable;
+ return TRUE;
+}
+
+/**
+ * @brief 写入设备可变阻尼值V5
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+BOOL hart_master_command_55_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ float32_u tmp;
+ *resp->data_p++ = req->data.command_55.device_ariable;
+ tmp.f = req->data.command_55.damping_value;
+ tmp.c = S2B_UINT32(tmp.c);
+ osel_memcpy(resp->data_p, (uint8_t *)&tmp, sizeof(float32_u)); // 设备可变阻尼值
+ resp->data_p += sizeof(float32_u);
+ return TRUE;
+}
+
+/**
+ * @brief 写入设备可变传感器序列号V5
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+BOOL hart_master_command_56_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ osel_memcpy(resp->data_p, (uint8_t *)&req->data.command_56, sizeof(hart_command_56_t));
+ resp->data_p += sizeof(hart_command_56_t);
+ return TRUE;
+}
+
+/**
+ * @brief 编写单位标签、描述符、日期V5
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+BOOL hart_master_command_58_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ osel_memcpy(resp->data_p, (uint8_t *)&req->data.command_58, sizeof(hart_command_58_t));
+ resp->data_p += sizeof(hart_command_58_t);
+ return TRUE;
+}
+
+/**
+ * @brief 写入响应序码数V5
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+BOOL hart_master_command_59_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ *resp->data_p++ = req->data.command_59.s2m_preambles;
+ return TRUE;
+}
+
+/**
+ * @brief读取模拟通道和范围百分比V5
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+BOOL hart_master_command_60_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ *resp->data_p++ = req->data.command_60.analog_channel_number_code;
+ return TRUE;
+}
+
+/**
+ * @brief 读取模拟通道V5
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+BOOL hart_master_command_62_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ osel_memcpy(resp->data_p, (uint8_t *)&req->data.command_62, sizeof(hart_command_62_t));
+ resp->data_p += sizeof(hart_command_62_t);
+ return TRUE;
+}
+
+/**
+ * @brief 读取模拟通道信息V5
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+BOOL hart_master_command_63_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ *resp->data_p++ = req->data.command_63.analog_channel_number_code;
+ return TRUE;
+}
+
+/**
+ * @brief 写入模拟通道附加阻尼值V5
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+BOOL hart_master_command_64_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ float32_u tmp;
+ *resp->data_p++ = req->data.command_64.analog_channel_number_code;
+ tmp.f = req->data.command_64.damping_value;
+ tmp.c = S2B_UINT32(tmp.c);
+ osel_memcpy(resp->data_p, (uint8_t *)&tmp, sizeof(float32_u)); // 模拟通道附加阻尼值
+ resp->data_p += sizeof(float32_u);
+ return TRUE;
+}
+
+/**
+ * @brief 写入模拟通道范围值V5
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+BOOL hart_master_command_65_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ float32_u tmp;
+ *resp->data_p++ = req->data.command_65.analog_channel_number_code;
+ *resp->data_p++ = req->data.command_65.upper_and_lower_range_values_units_code;
+
+ tmp.f = req->data.command_65.upper_range_value;
+ tmp.c = S2B_UINT32(tmp.c);
+ osel_memcpy(resp->data_p, (uint8_t *)&tmp, sizeof(float32_u)); // 模拟通道上限值
+ resp->data_p += sizeof(float32_u);
+
+ tmp.f = req->data.command_65.lower_range_value;
+ tmp.c = S2B_UINT32(tmp.c);
+ osel_memcpy(resp->data_p, (uint8_t *)&tmp, sizeof(float32_u)); // 模拟通道下限值
+ resp->data_p += sizeof(float32_u);
+ return TRUE;
+}
+
+/**
+ * @brief 进入/退出固定模拟通道模式V5
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+BOOL hart_master_command_66_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ float32_u tmp;
+ *resp->data_p++ = req->data.command_66.analog_channel_number_code;
+ *resp->data_p++ = req->data.command_66.units_code;
+ osel_memcpy((uint8_t *)&tmp.c, (uint8_t *)&req->data.command_66.fixed_analog_channel_level, sizeof(int32_t));
+ tmp.c = S2B_UINT32(tmp.c);
+ osel_memcpy(resp->data_p, (uint8_t *)&tmp, sizeof(float32_u));
+ resp->data_p += sizeof(float32_u);
+ return TRUE;
+}
+
+/**
+ * @brief 调整模拟通道零V5
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+BOOL hart_master_command_67_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ float32_u tmp;
+ *resp->data_p++ = req->data.command_67.analog_channel_number_code;
+ *resp->data_p++ = req->data.command_67.units_code;
+ osel_memcpy((uint8_t *)&tmp.c, (uint8_t *)&req->data.command_67.actual_analog_channel_level, sizeof(int32_t));
+ tmp.c = S2B_UINT32(tmp.c);
+ osel_memcpy(resp->data_p, (uint8_t *)&tmp, sizeof(float32_u));
+ resp->data_p += sizeof(float32_u);
+ return TRUE;
+}
+
+/**
+ * @brief 微调模拟通道增益V5
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+BOOL hart_master_command_68_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ float32_u tmp;
+ *resp->data_p++ = req->data.command_68.analog_channel_number_code;
+ *resp->data_p++ = req->data.command_68.units_code;
+ osel_memcpy((uint8_t *)&tmp.c, (uint8_t *)&req->data.command_68.externally_measured_analog_channel_level, sizeof(int32_t));
+ tmp.c = S2B_UINT32(tmp.c);
+ osel_memcpy(resp->data_p, (uint8_t *)&tmp, sizeof(float32_u));
+ resp->data_p += sizeof(float32_u);
+ return TRUE;
+}
+
+/**
+ * @brief 写入模拟通道传递函数V5
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+BOOL hart_master_command_69_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ *resp->data_p++ = req->data.command_69.analog_channel_number_code;
+ *resp->data_p++ = req->data.command_69.transfer_function_code;
+ return TRUE;
+}
+
+/**
+ * @brief 读取模拟通道端点值V5
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+BOOL hart_master_command_70_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ *resp->data_p++ = req->data.command_70.analog_channel_number_code;
+ return TRUE;
+}
+
+/**
+ * @brief 锁定装置
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+BOOL hart_master_command_71_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ *resp->data_p++ = req->data.command_71.lock_code;
+ return TRUE;
+}
+
+/**
+ * @brief 呼叫
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+BOOL hart_master_command_72_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ *resp->data_p++ = req->data.command_72.squawk_control_code;
+ return TRUE;
+}
+
+/**
+ * @brief 读取I/O系统功能
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+BOOL hart_master_command_74_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ // 判断是否是广播地址
+ if (!is_broadcast_address((uint8_t *)&req->address, HART_LONG_ADDRESS_LEN))
+ {
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/**
+ * @brief 轮询子设备
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+BOOL hart_master_command_75_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ if (!is_broadcast_address((uint8_t *)&req->address, HART_LONG_ADDRESS_LEN))
+ {
+ return FALSE;
+ }
+ *resp->data_p++ = req->data.command_75.card;
+ *resp->data_p++ = req->data.command_75.channel;
+ *resp->data_p++ = req->data.command_75.poll_address;
+ return TRUE;
+}
+
+/**
+ * @brief 向子设备发送命令
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+BOOL hart_master_command_77_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ return TRUE;
+}
+
+BOOL hart_master_command_78_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ return TRUE;
+}
+
+/**
+ * @brief 写入设备变量
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+BOOL hart_master_command_79_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ float32_u tmp;
+ *resp->data_p++ = req->data.command_79.device_ariable;
+ *resp->data_p++ = req->data.command_79.device_ariable_command_code;
+ *resp->data_p++ = req->data.command_79.device_ariable_unit_code;
+
+ tmp.f = req->data.command_79.device_ariable_value;
+ tmp.c = S2B_UINT32(tmp.c);
+ osel_memcpy(resp->data_p, (uint8_t *)&tmp, sizeof(float32_u));
+ resp->data_p += sizeof(float32_u);
+
+ *resp->data_p++ = req->data.command_79.status;
+ return TRUE;
+}
+
+/**
+ * @brief 读取设备可变微调点
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+BOOL hart_master_command_80_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ *resp->data_p++ = req->data.command_80.device_ariable;
+ return TRUE;
+}
+
+/**
+ * @brief 读取设备变量调整指南
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+BOOL hart_master_command_81_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ *resp->data_p++ = req->data.command_81.device_ariable;
+ return TRUE;
+}
+
+/**
+ * @brief 写入设备可变微调点
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+BOOL hart_master_command_82_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ float32_u tmp;
+ *resp->data_p++ = req->data.command_82.device_ariable;
+ *resp->data_p++ = req->data.command_82.trim_points;
+ *resp->data_p++ = req->data.command_82.units_code;
+
+ tmp.f = req->data.command_82.value;
+ tmp.c = S2B_UINT32(tmp.c);
+ osel_memcpy(resp->data_p, (uint8_t *)&tmp, sizeof(float32_u));
+ resp->data_p += sizeof(float32_u);
+ return TRUE;
+}
+
+/**
+ * @brief 重置设备变量调整
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+BOOL hart_master_command_83_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ *resp->data_p++ = req->data.command_83.device_ariable;
+ return TRUE;
+}
+
+/**
+ * @brief 读取子设备标识摘要
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+BOOL hart_master_command_84_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ // 判断是否是广播地址
+ if (!is_broadcast_address((uint8_t *)&req->address, HART_LONG_ADDRESS_LEN))
+ {
+ return FALSE;
+ }
+ *resp->data_p++ = HI_UINT16(req->data.command_84.identifier);
+ *resp->data_p++ = LO_UINT16(req->data.command_84.identifier);
+ return TRUE;
+}
+
+/**
+ * @brief 读取I/O通道统计信息
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+BOOL hart_master_command_85_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ // 判断是否是广播地址
+ if (!is_broadcast_address((uint8_t *)&req->address, HART_LONG_ADDRESS_LEN))
+ {
+ return FALSE;
+ }
+ *resp->data_p++ = req->data.command_85.card;
+ *resp->data_p++ = req->data.command_85.channel;
+ return TRUE;
+}
+
+/**
+ * @brief 读取子设备统计信息
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+BOOL hart_master_command_86_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ // 判断是否是广播地址
+ if (!is_broadcast_address((uint8_t *)&req->address, HART_LONG_ADDRESS_LEN))
+ {
+ return FALSE;
+ }
+ *resp->data_p++ = HI_UINT16(req->data.command_86.identifier);
+ *resp->data_p++ = LO_UINT16(req->data.command_86.identifier);
+ return TRUE;
+}
+
+/**
+ * @brief 写入I/O系统主模式
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+BOOL hart_master_command_87_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ // 判断是否是广播地址
+ if (!is_broadcast_address((uint8_t *)&req->address, HART_LONG_ADDRESS_LEN))
+ {
+ return FALSE;
+ }
+ *resp->data_p++ = req->data.command_87.master_mode;
+ return TRUE;
+}
+
+/**
+ * @brief 写入I/O系统重试计数
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+BOOL hart_master_command_88_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ // 判断是否是广播地址
+ if (!is_broadcast_address((uint8_t *)&req->address, HART_LONG_ADDRESS_LEN))
+ {
+ return FALSE;
+ }
+ *resp->data_p++ = req->data.command_88.retry_count;
+ return TRUE;
+}
+
+/**
+ * @brief 设置实时时钟
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+BOOL hart_master_command_89_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ uint32_t time = 0;
+ *resp->data_p++ = req->data.command_89.time_set_code;
+ osel_memcpy(resp->data_p, (uint8_t *)&req->data.command_89.date, HART_DATE_LEN);
+ resp->data_p += HART_DATE_LEN;
+ time = S2B_UINT32(req->data.command_89.time);
+ osel_memcpy(resp->data_p, (uint8_t *)&time, sizeof(uint32_t));
+ resp->data_p += sizeof(uint32_t);
+ *resp->data_p++ = HI_UINT16(req->data.command_89.transmission_time);
+ *resp->data_p++ = LO_UINT16(req->data.command_89.transmission_time);
+ return TRUE;
+}
+
+/**
+ * @brief 读取趋势配置
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+BOOL hart_master_command_91_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ *resp->data_p++ = req->data.command_91.trend_number;
+ return TRUE;
+}
+
+/**
+ * @brief 写入趋势配置
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+BOOL hart_master_command_92_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ uint32_t time = 0;
+ *resp->data_p++ = req->data.command_92.trend_number;
+ *resp->data_p++ = req->data.command_92.trend_code;
+ *resp->data_p++ = req->data.command_92.device_variable_code;
+ time = req->data.command_92.trend_sample_interval;
+ time = S2B_UINT32(time);
+ osel_memcpy(resp->data_p, (uint8_t *)&time, sizeof(uint32_t));
+ resp->data_p += sizeof(uint32_t);
+ return TRUE;
+}
+
+/**
+ * @brief 读取趋势
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+BOOL hart_master_command_93_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ *resp->data_p++ = req->data.command_93.trend_number;
+ return TRUE;
+}
+
+/**
+ * @brief 读取同步操作
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+BOOL hart_master_command_96_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ *resp->data_p++ = req->data.command_96.action_number;
+ return TRUE;
+}
+
+BOOL hart_master_command_97_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ uint32_t time = 0;
+ *resp->data_p++ = req->data.command_97.action_number; // 动作号
+ *resp->data_p++ = req->data.command_97.action_control_code; // 动作控制码
+ *resp->data_p++ = req->data.command_97.device_variable_code; // 设备变量代码
+ *resp->data_p++ = HI_UINT16(req->data.command_97.command_number); // 命令号
+ *resp->data_p++ = LO_UINT16(req->data.command_97.command_number);
+ osel_memcpy(resp->data_p, (uint8_t *)&req->data.command_97.trigger_date, HART_DATE_LEN); // 命令数据
+ resp->data_p += HART_DATE_LEN;
+ time = S2B_UINT32(req->data.command_97.trigger_time);
+ osel_memcpy(resp->data_p, (uint8_t *)&time, sizeof(uint32_t));
+ resp->data_p += sizeof(uint32_t);
+ return TRUE;
+}
+
+/**
+ * @brief读取命令操作
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+BOOL hart_master_command_98_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ *resp->data_p++ = req->data.command_98.action_number;
+ return TRUE;
+}
+
+/**
+ * @brief 配置命令操作
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+BOOL hart_master_command_99_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ *resp->data_p++ = req->data.command_99.action_number;
+ *resp->data_p++ = HI_UINT16(req->data.command_99.command_number); // 命令号
+ *resp->data_p++ = LO_UINT16(req->data.command_99.command_number);
+ *resp->data_p++ = req->data.command_99.command_data_length;
+ osel_memcpy(resp->data_p, (uint8_t *)req->data.command_99.command_data, req->data.command_99.command_data_length);
+ resp->data_p += req->data.command_99.command_data_length;
+ return TRUE;
+}
+
+/**
+ * @brief 写入主变量报警码
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+BOOL hart_master_command_100_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ *resp->data_p++ = req->data.command_100.pv_alarm_selection_code;
+ return TRUE;
+}
+/**
+ * @brief 读取子设备到突发消息映射
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+BOOL hart_master_command_101_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ *resp->data_p++ = req->data.command_101.burst_message;
+ return TRUE;
+}
+/**
+ * @brief将子设备映射到突发信息
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+BOOL hart_master_command_102_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ *resp->data_p++ = req->data.command_102.burst_message;
+ *resp->data_p++ = HI_UINT16(req->data.command_102.sub_device_index);
+ *resp->data_p++ = LO_UINT16(req->data.command_102.sub_device_index);
+ return TRUE;
+}
+/**
+ * @brief 写入突发周期
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+BOOL hart_master_command_103_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ uint32_t time = 0;
+ *resp->data_p++ = req->data.command_103.burst_message;
+ time = S2B_UINT32(req->data.command_103.update_period_time);
+ osel_memcpy(resp->data_p, (uint8_t *)&time, sizeof(uint32_t));
+ resp->data_p += sizeof(uint32_t);
+ time = S2B_UINT32(req->data.command_103.max_update_period_time);
+ osel_memcpy(resp->data_p, (uint8_t *)&time, sizeof(uint32_t));
+ resp->data_p += sizeof(uint32_t);
+ return TRUE;
+}
+/**
+ * @brief 写入突发触发器
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+BOOL hart_master_command_104_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ float32_u f;
+ f.f = req->data.command_104.trigger_level;
+ f.c = S2B_UINT32(f.c);
+ *resp->data_p++ = req->data.command_104.burst_message; // 突发消息编号
+ *resp->data_p++ = req->data.command_104.burst_message_trigger_code; // 突发触发器代码
+ *resp->data_p++ = req->data.command_104.device_variable_vlassification_for_trigger_level; // 触发器级别的设备变量分类
+ *resp->data_p++ = req->data.command_104.units_code; // 突发触发器单位代码
+ osel_memcpy(resp->data_p, (uint8_t *)&f, sizeof(float32_u)); // 触发电平
+ resp->data_p += sizeof(float32_u);
+ return TRUE;
+}
+
+BOOL hart_master_command_105_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ *resp->data_p++ = req->data.command_105.burst_message;
+ return TRUE;
+}
+
+BOOL hart_master_command_107_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ osel_memcpy(resp->data_p, (uint8_t *)&req->data.command_107, sizeof(hart_command_107_t));
+ resp->data_p += sizeof(hart_command_107_t);
+ return TRUE;
+}
+
+BOOL hart_master_command_513_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ *resp->data_p++ = HI_UINT16(req->data.command_513.country_code);
+ *resp->data_p++ = LO_UINT16(req->data.command_513.country_code);
+ *resp->data_p++ = req->data.command_513.si_units_control_code;
+ return TRUE;
+}
+
+// 结束:主机请求指令
+
+/**
+ * @brief 主机请求指令接口
+ * @param {hart_command_req_t} *req: 请求参数
+ * @return: TRUE: 请求成功
+ * FALSE: 请求失败
+ */
+BOOL hart_master_command_req(const hart_command_req_t *const req)
+{
+ uint8_t rsp_len = 0; // 响应数据长度
+ uint8_t xor = 0; // 异或校验
+ uint8_t preamble_def = HART_PREAMBLE_DEFAULT_LEN; // 引导码默认长度
+ hart_delimiter_u delimiter; // 界定符
+ hart_short_address_u poll_address;
+ hart_long_address_u long_address;
+ uint8_t *data_len_p = NULL; // 数据长度指针
+
+ handle->response->data_length = 0;
+ handle->response->data_p = handle->response->data;
+ osel_memset((uint8_t *)handle->response->data, 0, HART_RESPONSE_MAX_LEN);
+
+ delimiter.data = 0;
+ osel_memset(&poll_address.data, 0, HART_SHORT_ADDRESS_LEN);
+ osel_memset((uint8_t *)&long_address.data, 0, HART_LONG_ADDRESS_LEN);
+
+ // 检查参数
+ if (!DBG_ASSERT(handle->response_call != NULL __DBG_LINE))
+ return FALSE;
+
+ // 检查请求命令
+ if (req->command > HART_COMMAND_MAX)
+ return FALSE;
+
+ if (FALSE == hart_is_support_command(req->command)) // 当前模式使用的版本号,请求命令是否支持
+ return FALSE;
+
+ // 检查界定符和命令关系: HART协议规定只有0号通用命令支持短帧格式,其他命令发送之前通过发送命令0获取设备长地址,除非使用长地址发送命令
+ if (req->command > HART_COMMAND_0)
+ {
+ if (!DBG_ASSERT(req->delimiter_type != HART_DELIMITER_TYPE_SHORT __DBG_LINE)) // 除命令0以外的数据帧都是长帧格式
+ return FALSE;
+ }
+
+ // 填充请求数据
+
+ // 填充引导码
+ if (req->delimiter_type == HART_DELIMITER_TYPE_SHORT && req->command == HART_COMMAND_0)
+ {
+ // 一般是5-20个0xFF, 它是一组同步传输的同步信号, 用以保证信息的同步。在开始通讯的时候,使用的是20个FF引导码,用以保证通讯的同步。
+ preamble_def = 20;
+ }
+ for (uint8_t i = 0; i < preamble_def; i++)
+ {
+ *handle->response->data_p++ = HART_PREAMBLE;
+ }
+
+ // 填充界定符。如果命令大于0xFF,填充界定符中的扩展字节数量
+ delimiter.bits.frame_type = HART_STX_FRAME;
+ delimiter.bits.addr_type = req->delimiter_type;
+ if (req->command < 0xFF)
+ {
+ delimiter.bits.ext_bytes = 0;
+ }
+ else
+ {
+ delimiter.bits.ext_bytes = 1;
+ }
+ *handle->response->data_p++ = delimiter.data;
+
+ // 填充地址
+ if (req->delimiter_type == HART_DELIMITER_TYPE_SHORT)
+ {
+ poll_address.bits.master = handle->address_bit;
+ poll_address.bits.slave = req->address[0];
+ *handle->response->data_p++ = poll_address.data;
+ }
+ else
+ {
+ long_address.bits.master = handle->address_bit;
+ long_address.bits.reserved = req->address[0];
+ // long_address.data.bs[0] = req->address[0];
+ osel_memcpy((uint8_t *)&long_address.bits.slave, &req->address[1], HART_LONG_ADDRESS_LEN - 1);
+ osel_memcpy(handle->response->data_p, (uint8_t *)&long_address.data, HART_LONG_ADDRESS_LEN); // 长地址5个字节
+ handle->response->data_p += HART_LONG_ADDRESS_LEN;
+ }
+
+ // 填充命令
+ if (delimiter.bits.ext_bytes == 0)
+ {
+ *handle->response->data_p++ = req->command;
+ }
+ else
+ {
+ // 目前为止扩展字节只有1个,所以只考虑1个的情况
+ uint16_t command = (uint16_t)(req->command);
+ *handle->response->data_p++ = HI_UINT16(command);
+ *handle->response->data_p++ = LO_UINT16(command);
+ }
+
+ if (hart_command_ptr_arr[req->command] != NULL)
+ {
+ // 检查数据域,并填充数据长度和数据
+ data_len_p = handle->response->data_p;
+ hart_frame_data_length_start(&data_len_p);
+ handle->response->data_p++;
+ if (!hart_command_ptr_arr[req->command](req, handle->response))
+ {
+ // TODO
+ return FALSE;
+ }
+ else
+ {
+ hart_frame_data_length_end(handle->response->data_p);
+ // 填充校验码
+ rsp_len = handle->response->data_p - handle->response->data;
+ xor = xor_compute(&handle->response->data[preamble_def], (rsp_len - preamble_def)); // 除前导码和校验字节外所有字节的异或之后
+ *handle->response->data_p++ = xor;
+ rsp_len++;
+ handle->response->data_length = rsp_len;
+
+ if (handle->response->data_length > 0)
+ {
+ handle->response_call(0, handle->response->data, handle->response->data_length);
+ }
+ return TRUE;
+ }
+ }
+ else
+ {
+ return FALSE;
+ }
+}
+
+BOOL hart_master_req_init(const hart_master_init_t *const init)
+{
+ if (!DBG_ASSERT(init != NULL __DBG_LINE))
+ return FALSE;
+
+ handle = (hart_master_init_t *)init;
+ // 初始化指令处理函数,指向hart_master_command_without_data_req,不需要携带数据域
+ for (uint16_t i = 0; i < HART_COMMAND_MAX; i++)
+ {
+ hart_command_ptr_arr[i] = hart_master_command_without_data_req;
+ }
+ // 需要携带数据域的指令处理函数,指向对应的处理函数
+ hart_command_ptr_arr[HART_COMMAND_6] = hart_master_command_6_req;
+ hart_command_ptr_arr[HART_COMMAND_9] = hart_master_command_9_req;
+ hart_command_ptr_arr[HART_COMMAND_11] = hart_master_command_11_req;
+ hart_command_ptr_arr[HART_COMMAND_17] = hart_master_command_17_req;
+ hart_command_ptr_arr[HART_COMMAND_18] = hart_master_command_18_req;
+ hart_command_ptr_arr[HART_COMMAND_19] = hart_master_command_19_req;
+ hart_command_ptr_arr[HART_COMMAND_21] = hart_master_command_21_req;
+ hart_command_ptr_arr[HART_COMMAND_22] = hart_master_command_22_req;
+ hart_command_ptr_arr[HART_COMMAND_38] = hart_master_command_38_req;
+
+ hart_command_ptr_arr[HART_COMMAND_33] = hart_master_command_33_req;
+ hart_command_ptr_arr[HART_COMMAND_34] = hart_master_command_34_req;
+ hart_command_ptr_arr[HART_COMMAND_35] = hart_master_command_35_req;
+ hart_command_ptr_arr[HART_COMMAND_39] = hart_master_command_39_req;
+ hart_command_ptr_arr[HART_COMMAND_40] = hart_master_command_40_req;
+ hart_command_ptr_arr[HART_COMMAND_44] = hart_master_command_44_req;
+ hart_command_ptr_arr[HART_COMMAND_45] = hart_master_command_45_req;
+ hart_command_ptr_arr[HART_COMMAND_46] = hart_master_command_46_req;
+ hart_command_ptr_arr[HART_COMMAND_47] = hart_master_command_47_req;
+ hart_command_ptr_arr[HART_COMMAND_49] = hart_master_command_49_req;
+ hart_command_ptr_arr[HART_COMMAND_51] = hart_master_command_51_req;
+ hart_command_ptr_arr[HART_COMMAND_52] = hart_master_command_52_req;
+ hart_command_ptr_arr[HART_COMMAND_53] = hart_master_command_53_req;
+ hart_command_ptr_arr[HART_COMMAND_54] = hart_master_command_54_req;
+ hart_command_ptr_arr[HART_COMMAND_55] = hart_master_command_55_req;
+ hart_command_ptr_arr[HART_COMMAND_56] = hart_master_command_56_req;
+ hart_command_ptr_arr[HART_COMMAND_58] = hart_master_command_58_req;
+ hart_command_ptr_arr[HART_COMMAND_59] = hart_master_command_59_req;
+ hart_command_ptr_arr[HART_COMMAND_60] = hart_master_command_60_req;
+ hart_command_ptr_arr[HART_COMMAND_62] = hart_master_command_62_req;
+ hart_command_ptr_arr[HART_COMMAND_63] = hart_master_command_63_req;
+ hart_command_ptr_arr[HART_COMMAND_64] = hart_master_command_64_req;
+ hart_command_ptr_arr[HART_COMMAND_65] = hart_master_command_65_req;
+ hart_command_ptr_arr[HART_COMMAND_66] = hart_master_command_66_req;
+ hart_command_ptr_arr[HART_COMMAND_67] = hart_master_command_67_req;
+ hart_command_ptr_arr[HART_COMMAND_68] = hart_master_command_68_req;
+ hart_command_ptr_arr[HART_COMMAND_69] = hart_master_command_69_req;
+ hart_command_ptr_arr[HART_COMMAND_70] = hart_master_command_70_req;
+ hart_command_ptr_arr[HART_COMMAND_71] = hart_master_command_71_req;
+ hart_command_ptr_arr[HART_COMMAND_72] = hart_master_command_72_req;
+ hart_command_ptr_arr[HART_COMMAND_74] = hart_master_command_74_req;
+ hart_command_ptr_arr[HART_COMMAND_75] = hart_master_command_75_req;
+ hart_command_ptr_arr[HART_COMMAND_77] = hart_master_command_77_req;
+ hart_command_ptr_arr[HART_COMMAND_78] = hart_master_command_78_req;
+ hart_command_ptr_arr[HART_COMMAND_79] = hart_master_command_79_req;
+ hart_command_ptr_arr[HART_COMMAND_80] = hart_master_command_80_req;
+ hart_command_ptr_arr[HART_COMMAND_81] = hart_master_command_81_req;
+ hart_command_ptr_arr[HART_COMMAND_82] = hart_master_command_82_req;
+ hart_command_ptr_arr[HART_COMMAND_83] = hart_master_command_83_req;
+ hart_command_ptr_arr[HART_COMMAND_84] = hart_master_command_84_req;
+ hart_command_ptr_arr[HART_COMMAND_85] = hart_master_command_85_req;
+ hart_command_ptr_arr[HART_COMMAND_86] = hart_master_command_86_req;
+ hart_command_ptr_arr[HART_COMMAND_87] = hart_master_command_87_req;
+ hart_command_ptr_arr[HART_COMMAND_88] = hart_master_command_88_req;
+ hart_command_ptr_arr[HART_COMMAND_89] = hart_master_command_89_req;
+ hart_command_ptr_arr[HART_COMMAND_91] = hart_master_command_91_req;
+ hart_command_ptr_arr[HART_COMMAND_92] = hart_master_command_92_req;
+ hart_command_ptr_arr[HART_COMMAND_93] = hart_master_command_93_req;
+ hart_command_ptr_arr[HART_COMMAND_96] = hart_master_command_96_req;
+ hart_command_ptr_arr[HART_COMMAND_97] = hart_master_command_97_req;
+ hart_command_ptr_arr[HART_COMMAND_98] = hart_master_command_98_req;
+ hart_command_ptr_arr[HART_COMMAND_99] = hart_master_command_99_req;
+ hart_command_ptr_arr[HART_COMMAND_100] = hart_master_command_100_req;
+ hart_command_ptr_arr[HART_COMMAND_101] = hart_master_command_101_req;
+ hart_command_ptr_arr[HART_COMMAND_102] = hart_master_command_102_req;
+ hart_command_ptr_arr[HART_COMMAND_103] = hart_master_command_103_req;
+ hart_command_ptr_arr[HART_COMMAND_104] = hart_master_command_104_req;
+ hart_command_ptr_arr[HART_COMMAND_105] = hart_master_command_105_req;
+ hart_command_ptr_arr[HART_COMMAND_107] = hart_master_command_107_req;
+ hart_command_ptr_arr[HART_COMMAND_513] = hart_master_command_513_req;
+
+ hart_master_req_init_user();
+ return TRUE;
+}
diff --git a/User/hart/master/src/hart_master_req_user.c b/User/hart/master/src/hart_master_req_user.c
new file mode 100644
index 0000000..9d9d70d
--- /dev/null
+++ b/User/hart/master/src/hart_master_req_user.c
@@ -0,0 +1,94 @@
+#include "../inc/hart_master.h"
+#include "log.h"
+
+BOOL hart_master_command_31_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ osel_memcpy(resp->data_p, (uint8_t *)&req->data.command_31, sizeof(hart_command_31_t));
+ resp->data_p += sizeof(hart_command_31_t);
+ return TRUE;
+}
+
+BOOL hart_master_command_129_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ uint8_t len = sizeof(hart_command_129_t);
+ uint8_t *index = (uint8_t *)&req->data.command_129 + len - 1;
+ while (*index-- == 251) // 251用来判断来自python的数据是否结束,python的数据是特殊处理的,载荷部分不会有251
+ {
+ len--;
+ }
+ osel_memcpy(resp->data_p, req->data.command_129.pbuf, len);
+ resp->data_p += len;
+ return TRUE;
+}
+
+BOOL hart_master_command_130_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ uint8_t len = sizeof(hart_command_130_t);
+ uint8_t *index = (uint8_t *)&req->data.command_130 + len - 1;
+ while (*index-- == 251) // 251用来判断来自python的数据是否结束,python的数据是特殊处理的,载荷部分不会有251
+ {
+ len--;
+ }
+ osel_memcpy(resp->data_p, (uint8_t *)&req->data.command_130, len);
+ resp->data_p += len;
+ return TRUE;
+}
+
+BOOL hart_master_command_134_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ uint16_t offset = B2S_UINT16(req->data.command_134.file_offset);
+ *resp->data_p++ = req->data.command_134.file_index;
+ osel_memcpy(resp->data_p, (uint8_t *)&offset, sizeof(uint16_t));
+ resp->data_p += sizeof(uint16_t);
+ *resp->data_p++ = req->data.command_134.read_length;
+ return TRUE;
+}
+
+BOOL hart_master_command_142_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ *resp->data_p++ = req->data.command_142.code;
+ return TRUE;
+}
+
+BOOL hart_master_command_155_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ osel_memcpy(resp->data_p, (uint8_t *)&req->data.command_155, sizeof(hart_command_155_t));
+ resp->data_p += sizeof(hart_command_155_t);
+ return TRUE;
+}
+
+BOOL hart_master_command_167_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ hart_command_167_t tmp_req;
+ osel_memcpy((uint8_t *)&tmp_req, (uint8_t *)&req->data.command_167, sizeof(hart_command_167_t));
+ tmp_req.operation_time = S2B_UINT32(tmp_req.operation_time);
+ osel_memcpy(resp->data_p, (uint8_t *)&tmp_req, sizeof(hart_command_167_t));
+ resp->data_p += sizeof(hart_command_167_t);
+
+ // LOG_PRINT("%u\n", req->data.command_167.operation_time);
+ // LOG_PRINT("%s\n", req->data.command_167.operator);
+ return TRUE;
+}
+
+BOOL hart_master_command_170_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ *resp->data_p++ = req->data.command_170.code;
+ return TRUE;
+}
+
+/**
+ * @brief 用户自定义指令初始化
+ * @return {*}
+ */
+void hart_master_req_init_user(void)
+{
+ hart_command_ptr_arr[HART_COMMAND_31] = hart_master_command_31_req;
+
+ hart_command_ptr_arr[HART_COMMAND_129] = hart_master_command_129_req;
+ hart_command_ptr_arr[HART_COMMAND_130] = hart_master_command_130_req;
+ hart_command_ptr_arr[HART_COMMAND_134] = hart_master_command_134_req;
+ hart_command_ptr_arr[HART_COMMAND_142] = hart_master_command_142_req;
+ hart_command_ptr_arr[HART_COMMAND_155] = hart_master_command_155_req;
+ hart_command_ptr_arr[HART_COMMAND_167] = hart_master_command_167_req;
+ hart_command_ptr_arr[HART_COMMAND_170] = hart_master_command_170_req;
+}
diff --git a/User/hart/master/src/hart_master_rsp.c b/User/hart/master/src/hart_master_rsp.c
new file mode 100644
index 0000000..9bcde57
--- /dev/null
+++ b/User/hart/master/src/hart_master_rsp.c
@@ -0,0 +1,468 @@
+#include "../inc/hart_master.h"
+#include "../inc/hart_master_rsp.h"
+
+static hart_master_init_t *handle;
+BOOL(*hart_command_rsp_ptr_arr[HART_COMMAND_MAX])
+(const hart_command_rsp_t *const data, hart_response_t *resp);
+
+// 统计在线设备数量
+static uint16_t hart_master_online_device_count(void)
+{
+ uint16_t count = 0;
+ for (uint8_t i = 0; i < HART_IO_MAXIMUM_NUMBER_CARDS; i++)
+ {
+ io_system_card_t *card = &hart_master_attribute.io_system.cards[i];
+ for (uint8_t j = 0; j < HART_IO_MAXIMUM_NUMBER_CHANNELS_CARD; j++)
+ {
+ io_system_channel_t *channel = &card->channels[j];
+ for (uint8_t k = 0; k < HART_IO_MAXIMUM_NUMBER_DEVICES_CHANNEL; k++)
+ {
+ io_system_device_t *device = &channel->devices[k];
+ if (device->online)
+ count++;
+ }
+ }
+ }
+ return count;
+}
+
+// 获取设备
+static io_system_device_t *hart_master_get_device(uint8_t card_index, uint8_t channel_index, uint8_t device_index)
+{
+ if (card_index >= HART_IO_MAXIMUM_NUMBER_CARDS)
+ return NULL;
+ if (channel_index >= HART_IO_MAXIMUM_NUMBER_CHANNELS_CARD)
+ return NULL;
+ if (device_index >= HART_IO_MAXIMUM_NUMBER_DEVICES_CHANNEL)
+ return NULL;
+ io_system_card_t *card = &hart_master_attribute.io_system.cards[card_index];
+ io_system_channel_t *channel = &card->channels[channel_index];
+ io_system_device_t *device = &channel->devices[device_index];
+ return device;
+}
+
+// 获取通道消息计数
+static io_system_message_count_t *hart_master_get_channel_message_count(uint8_t card_index, uint8_t channel_index)
+{
+ if (card_index >= HART_IO_MAXIMUM_NUMBER_CARDS)
+ return NULL;
+ if (channel_index >= HART_IO_MAXIMUM_NUMBER_CHANNELS_CARD)
+ return NULL;
+ io_system_card_t *card = &hart_master_attribute.io_system.cards[card_index];
+ io_system_channel_t *channel = &card->channels[channel_index];
+ return &channel->message_count;
+}
+
+// 获取设备通过索引
+static io_system_device_info_t *hart_master_get_device_by_identifier(uint16_t identifier)
+{
+ io_system_device_info_t *device_info = osel_mem_alloc(sizeof(io_system_device_info_t));
+ for (uint8_t i = 0; i < HART_IO_MAXIMUM_NUMBER_CARDS; i++)
+ {
+ io_system_card_t *card = &hart_master_attribute.io_system.cards[i];
+ for (uint8_t j = 0; j < HART_IO_MAXIMUM_NUMBER_CHANNELS_CARD; j++)
+ {
+ io_system_channel_t *channel = &card->channels[j];
+ for (uint8_t k = 0; k < HART_IO_MAXIMUM_NUMBER_DEVICES_CHANNEL; k++)
+ {
+ io_system_device_t *device = &channel->devices[k];
+ if (device->identifier == identifier)
+ {
+ device_info->card_index = i;
+ device_info->channel_index = j;
+ device_info->device = device;
+ return device_info;
+ }
+ }
+ }
+ }
+ return NULL;
+}
+
+static BOOL hart_master_command_undef_rsp(const hart_command_rsp_t *const data, hart_response_t *resp)
+{
+ return FALSE;
+}
+
+/**
+ * @brief 读取I/O系统功能
+ * @param {hart_command_rsp_t} *data
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+BOOL hart_master_command_74_rsp(const hart_command_rsp_t *const data, hart_response_t *resp)
+{
+ if (data->delimiter.bits.frame_type == HART_STX_FRAME) // 请求帧, 主->从
+ {
+ if (FALSE == is_broadcast_address((uint8_t *)data->address, data->address_length))
+ {
+ return FALSE;
+ }
+
+ *resp->data_p++ = HART_IO_MAXIMUM_NUMBER_CARDS; // I/O卡的最大数量
+ *resp->data_p++ = HART_IO_MAXIMUM_NUMBER_CHANNELS_CARD; // 每个I/O卡的最大通道数
+ // 每个通道的最大子设备数
+ *resp->data_p++ = HART_IO_MAXIMUM_NUMBER_DEVICES_CHANNEL; // 每个通道最大设备数
+ // 检测到的设备数量(计数包括I/O系统本身)
+ uint16_t count = hart_master_online_device_count();
+ *resp->data_p++ = HI_UINT16(count + 1);
+ *resp->data_p++ = LO_UINT16(count + 1);
+ // I/O系统支持的最大延迟响应数
+ *resp->data_p++ = HART_IO_MAXIMUM_NUMBER_DELAY_RESPONSE;
+ // 信道通信的主模式。0=二级主机;1=主控形状(默认)
+ if (count == 0)
+ {
+ *resp->data_p++ = 250; // 如果I/0系统没有到子设备的物理HART通信通道,则主模式必须返回250“未使用
+ }
+ else
+ {
+ *resp->data_p++ = handle->address_bit;
+ }
+
+ // 向子设备发送命令时要使用的重试计数。有效范围为2到5。默认情况下重试3次。
+ *resp->data_p++ = HART_IO_MAXIMUM_NUMBER_RETRY_COUNT;
+ }
+ else
+ {
+ }
+ return TRUE;
+}
+
+/**
+ * @brief 轮询子设备
+ * @param {hart_command_rsp_t} *data
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+BOOL hart_master_command_75_rsp(const hart_command_rsp_t *const data, hart_response_t *resp)
+{
+ if (data->delimiter.bits.frame_type == HART_STX_FRAME) // 请求帧, 主->从
+ {
+ if (data->data_length < sizeof(hart_command_75_t))
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_5;
+ return TRUE;
+ }
+ if (FALSE == is_broadcast_address((uint8_t *)data->address, data->address_length))
+ {
+ return FALSE;
+ }
+
+ uint8_t card_index, channel_index, device_index;
+ io_system_device_t *device;
+ card_index = data->data.command_75.card;
+ channel_index = data->data.command_75.channel;
+ device_index = data->data.command_75.poll_address;
+
+ if (card_index >= HART_IO_MAXIMUM_NUMBER_CARDS)
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_21;
+ return TRUE;
+ }
+
+ if (channel_index >= HART_IO_MAXIMUM_NUMBER_CHANNELS_CARD)
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_22;
+ return TRUE;
+ }
+
+ device = hart_master_get_device(card_index, channel_index, device_index);
+ if (device == NULL)
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_9;
+ return TRUE;
+ }
+
+ if (device->online == FALSE)
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_9;
+ return TRUE;
+ }
+
+ *resp->data_p++ = 254; // 默认254
+ *resp->data_p++ = HI_UINT16(device->extended_device_type); // 扩展设备类型
+ *resp->data_p++ = LO_UINT16(device->extended_device_type);
+ *resp->data_p++ = device->m2s_preambles_limit_count; // 主设备到从设备的最少同步前导码数量
+ *resp->data_p++ = device->hart_revision; // 本设备实施的HART协议主要版本号。对于HART版本7。该值必须是数字7
+ *resp->data_p++ = device->device_revision; // 设备版本
+ *resp->data_p++ = device->device_software_revision; // 设备软件版本,254,255保留
+ *resp->data_p++ = device->device_hardware_revision.version; // (高5bits)硬件版本号,31保留;(低3bits)5.10 物理信号
+ resp->data_p++; // 保留
+ osel_memcpy(resp->data_p, device->device_id, 3); // 设备ID,长ID的后3个字节
+ resp->data_p += 3;
+ if (device->hart_revision == HART_PROTOCOL_VERSION_7)
+ {
+ *resp->data_p++ = device->s2m_preambles; // 从设备到主设备的响应前导码个数
+ *resp->data_p++ = device->last_device_variable; // 上一个设备变量,这表示应用程序应在现场设备中找到的最后一个设备变量代码(在执行Command 54时读取设备的变量)
+ *resp->data_p++ = HI_UINT16(device->configuration_update_count); // 配置被更新的次数
+ *resp->data_p++ = LO_UINT16(device->configuration_update_count);
+ *resp->data_p++ = device->extended_device_status; // 扩展现场设备状态未指定的任何位都是未定义的,必须设置为零。
+ *resp->data_p++ = HI_UINT16(device->manufacturer_identification_code); // 制造商标识码
+ *resp->data_p++ = LO_UINT16(device->manufacturer_identification_code);
+ *resp->data_p++ = HI_UINT16(device->private_label_distributor_code); // 私有标签分销商代码
+ *resp->data_p++ = LO_UINT16(device->private_label_distributor_code);
+ *resp->data_p++ = device->device_profile; // 设备配置文件
+ }
+ }
+ else
+ {
+ }
+ return TRUE;
+}
+
+/**
+ * @brief 读取子设备标识摘要
+ * @param {hart_command_rsp_t} *data
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+BOOL hart_master_command_84_rsp(const hart_command_rsp_t *const data, hart_response_t *resp)
+{
+ uint16_t identifier;
+ if (data->delimiter.bits.frame_type == HART_STX_FRAME) // 请求帧, 主->从
+ {
+ if (data->data_length < sizeof(hart_command_84_t))
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_5;
+ return TRUE;
+ }
+ if (FALSE == is_broadcast_address((uint8_t *)data->address, data->address_length))
+ {
+ return FALSE;
+ }
+
+ io_system_device_info_t *info;
+ identifier = B2S_UINT16(data->data.command_84.identifier);
+ info = hart_master_get_device_by_identifier(identifier);
+ if (info == NULL)
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_9;
+ return TRUE;
+ }
+ // 回复数据
+ *resp->data_p++ = HI_UINT16(info->device->identifier);
+ *resp->data_p++ = LO_UINT16(info->device->identifier);
+ *resp->data_p++ = info->card_index;
+ *resp->data_p++ = info->channel_index;
+ *resp->data_p++ = HI_UINT16(info->device->manufacturer_identification_code);
+ *resp->data_p++ = LO_UINT16(info->device->manufacturer_identification_code);
+ *resp->data_p++ = HI_UINT16(info->device->extended_device_type);
+ *resp->data_p++ = LO_UINT16(info->device->extended_device_type);
+ osel_memcpy(resp->data_p, info->device->device_id, 3);
+ resp->data_p += 3;
+ *resp->data_p++ = 0; // 保留
+ osel_memcpy(resp->data_p, info->device->long_tag, HART_PACKED32_LEN);
+ resp->data_p += HART_PACKED32_LEN;
+ *resp->data_p++ = info->device->device_revision;
+ *resp->data_p++ = info->device->device_profile;
+ *resp->data_p++ = HI_UINT16(info->device->private_label_distributor_code);
+ *resp->data_p++ = LO_UINT16(info->device->private_label_distributor_code);
+ osel_mem_free(info);
+ }
+ else
+ {
+ }
+ return TRUE;
+}
+
+/**
+ * @brief 读取I/O通道统计信息
+ * @param {hart_command_rsp_t} *data
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+BOOL hart_master_command_85_rsp(const hart_command_rsp_t *const data, hart_response_t *resp)
+{
+ if (data->delimiter.bits.frame_type == HART_STX_FRAME) // 请求帧, 主->从
+ {
+ io_system_message_count_t *message_count;
+ if (data->data_length < sizeof(hart_command_85_t))
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_5;
+ return TRUE;
+ }
+ if (FALSE == is_broadcast_address((uint8_t *)data->address, data->address_length))
+ {
+ return FALSE;
+ }
+ if (data->data.command_85.card >= HART_IO_MAXIMUM_NUMBER_CARDS)
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_21;
+ return TRUE;
+ }
+
+ if (data->data.command_85.channel >= HART_IO_MAXIMUM_NUMBER_CHANNELS_CARD)
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_22;
+ return TRUE;
+ }
+ message_count = hart_master_get_channel_message_count(data->data.command_85.card, data->data.command_85.channel);
+ if (message_count == NULL)
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_2;
+ return TRUE;
+ }
+
+ *resp->data_p++ = data->data.command_85.card;
+ *resp->data_p++ = data->data.command_85.channel;
+ *resp->data_p++ = HI_UINT16(message_count->stx);
+ *resp->data_p++ = LO_UINT16(message_count->stx);
+ *resp->data_p++ = HI_UINT16(message_count->ack);
+ *resp->data_p++ = LO_UINT16(message_count->ack);
+ *resp->data_p++ = HI_UINT16(message_count->ostx);
+ *resp->data_p++ = LO_UINT16(message_count->ostx);
+ *resp->data_p++ = HI_UINT16(message_count->oack);
+ *resp->data_p++ = LO_UINT16(message_count->oack);
+ *resp->data_p++ = HI_UINT16(message_count->back);
+ *resp->data_p++ = LO_UINT16(message_count->back);
+ }
+ else
+ {
+ }
+ return TRUE;
+}
+
+/**
+ * @brief 读取子设备统计信息
+ * @param {hart_command_rsp_t} *data
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+BOOL hart_master_command_86_rsp(const hart_command_rsp_t *const data, hart_response_t *resp)
+{
+ if (data->delimiter.bits.frame_type == HART_STX_FRAME) // 请求帧, 主->从
+ {
+ uint16_t identifier;
+ if (data->data_length < sizeof(hart_command_86_t))
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_5;
+ return TRUE;
+ }
+ if (FALSE == is_broadcast_address((uint8_t *)data->address, data->address_length))
+ {
+ return FALSE;
+ }
+ io_system_device_info_t *info;
+ identifier = B2S_UINT16(data->data.command_86.identifier);
+ info = hart_master_get_device_by_identifier(identifier);
+ if (info == NULL)
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_2;
+ return TRUE;
+ }
+
+ *resp->data_p++ = HI_UINT16(info->device->identifier);
+ *resp->data_p++ = LO_UINT16(info->device->identifier);
+ *resp->data_p++ = HI_UINT16(info->device->message_count.stx);
+ *resp->data_p++ = LO_UINT16(info->device->message_count.stx);
+ *resp->data_p++ = HI_UINT16(info->device->message_count.ack);
+ *resp->data_p++ = LO_UINT16(info->device->message_count.ack);
+ *resp->data_p++ = HI_UINT16(info->device->message_count.back);
+ *resp->data_p++ = LO_UINT16(info->device->message_count.back);
+
+ osel_mem_free(info);
+ }
+ else
+ {
+ }
+ return TRUE;
+}
+
+/**
+ * @brief 写入I/O系统重试计数
+ * @param {hart_command_rsp_t} *data
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+BOOL hart_master_command_87_rsp(const hart_command_rsp_t *const data, hart_response_t *resp)
+{
+ if (data->delimiter.bits.frame_type == HART_STX_FRAME) // 请求帧, 主->从
+ {
+ uint8_t master_mode = 0;
+ if (data->data_length < sizeof(hart_command_87_t))
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_5;
+ return TRUE;
+ }
+ if (FALSE == is_broadcast_address((uint8_t *)data->address, data->address_length))
+ {
+ return FALSE;
+ }
+ master_mode = data->data.command_87.master_mode;
+ if (master_mode != HART_IO_PRIMARY_MODE && master_mode != HART_IO_SECONDARY_MODE)
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_2;
+ return TRUE;
+ }
+ hart_master_attribute.io_system.master_mode = master_mode;
+
+ // 回复数据
+ *resp->data_p++ = master_mode;
+ }
+ else
+ {
+ }
+ return TRUE;
+}
+
+/**
+ * @brief 写入I/O系统重试计数
+ * @param {hart_command_rsp_t} *data
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+BOOL hart_master_command_88_rsp(const hart_command_rsp_t *const data, hart_response_t *resp)
+{
+ if (data->delimiter.bits.frame_type == HART_STX_FRAME) // 请求帧, 主->从
+ {
+ uint8_t retry_count = 0;
+ if (data->data_length < sizeof(hart_command_88_t))
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_5;
+ return TRUE;
+ }
+ if (FALSE == is_broadcast_address((uint8_t *)data->address, data->address_length))
+ {
+ return FALSE;
+ }
+ retry_count = data->data.command_88.retry_count;
+ if (retry_count < 2)
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_4;
+ return TRUE;
+ }
+ if (retry_count > 5)
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_3;
+ return TRUE;
+ }
+ hart_master_attribute.io_system.retry_count = retry_count;
+
+ // 回复数据
+ *resp->data_p++ = retry_count;
+ }
+ else
+ {
+ }
+ return TRUE;
+}
+
+BOOL hart_master_rsp_init(const hart_master_init_t *const init)
+{
+ if (!DBG_ASSERT(init != NULL __DBG_LINE))
+ return FALSE;
+
+ handle = (hart_master_init_t *)init;
+ for (uint16_t i = 0; i < HART_COMMAND_MAX; i++)
+ {
+ hart_command_rsp_ptr_arr[i] = hart_master_command_undef_rsp;
+ }
+ hart_command_rsp_ptr_arr[HART_COMMAND_74] = hart_master_command_74_rsp;
+ hart_command_rsp_ptr_arr[HART_COMMAND_75] = hart_master_command_75_rsp;
+ hart_command_rsp_ptr_arr[HART_COMMAND_84] = hart_master_command_84_rsp;
+ hart_command_rsp_ptr_arr[HART_COMMAND_85] = hart_master_command_85_rsp;
+ hart_command_rsp_ptr_arr[HART_COMMAND_86] = hart_master_command_86_rsp;
+ hart_command_rsp_ptr_arr[HART_COMMAND_87] = hart_master_command_87_rsp;
+ hart_command_rsp_ptr_arr[HART_COMMAND_88] = hart_master_command_88_rsp;
+ return TRUE;
+}
diff --git a/User/hart/public/img/HART加入.png b/User/hart/public/img/HART加入.png
new file mode 100644
index 0000000..9b1d97c
Binary files /dev/null and b/User/hart/public/img/HART加入.png differ
diff --git a/User/hart/public/img/头文件.png b/User/hart/public/img/头文件.png
new file mode 100644
index 0000000..7d3add1
Binary files /dev/null and b/User/hart/public/img/头文件.png differ
diff --git a/User/hart/public/img/宏定义.png b/User/hart/public/img/宏定义.png
new file mode 100644
index 0000000..52650fc
Binary files /dev/null and b/User/hart/public/img/宏定义.png differ
diff --git a/User/hart/public/img/架构.png b/User/hart/public/img/架构.png
new file mode 100644
index 0000000..e35e706
Binary files /dev/null and b/User/hart/public/img/架构.png differ
diff --git a/User/hart/public/img/组织结构.png b/User/hart/public/img/组织结构.png
new file mode 100644
index 0000000..fc70d8b
Binary files /dev/null and b/User/hart/public/img/组织结构.png differ
diff --git a/User/hart/readme.md b/User/hart/readme.md
new file mode 100644
index 0000000..39100b2
--- /dev/null
+++ b/User/hart/readme.md
@@ -0,0 +1,546 @@
+# 介绍
+
+HART 协议模块是 C 语言编写的,使用者无需对 HART 协议了解,通过接口文档可以快速完成应用层协议开发。
+模块可以分别被主机和从机使用,调用少量接口完成开发,模块接口测试覆盖率 100%。
+
+# 架构
+
+
+
+## 架构说明
+
+HART 协议模块是设备与主机之间的通信协议,主机和从机之间通过串口通信,主机通过串口发送命令,从机接收命令并返回响应数据。因此,主机和从机都需要使用 HART 协议模块,主机和从机的接口不同,主机接口主要是发送命令,从机接口主要是接收命令并返回响应数据。
+
+考虑到移植性在设计阶段模块因避免使用操作系统相关的接口,模块接口使用回调函数的方式实现,主机和从机需要实现不同的回调函数,主机需要实现发送数据的回调函数,从机需要实现接收数据的回调函数。
+
+# 内容说明
+
+1. 7.9 版本认证支持命令 78、79、534
+2. safeHART 数字化安全连锁,一种通讯协议,主要是对数据部分增加了 CRC 校验和序列号,打开 Burst-Mode 后发送的命令发送的是 safeHART 命令。
+ https://library.fieldcommgroup.org/20085/TS20085/4.0/#page=36
+3. 2024 年 3 月 8 日后提交测试必须是 3.8 版本测试
+4. 新增 548-553 指令
+
+# 软件设计
+
+## 结构图
+
+│ hart.c
+│ hart_cache.c
+│ hart_frame.c
+│ readme.md
+├─inc
+│ hart.h
+│ hart_common_tables_specification.h
+│ hart_frame.h
+│ hart_frame_user.h
+│
+├─lib
+│ ├─flow
+│ │ example.c
+│ │ flow.h
+│ │ flow_core.c
+│ │ flow_core.h
+│ │ flow_def.h
+│ │ flow_sem.h
+│ │ README.md
+│ │
+│ ├─inc
+│ │ data_type_def.h
+│ │ debug.h
+│ │ lib.h
+│ │ log.h
+│ │ malloc.h
+│ │ osel_arch.h
+│ │ sqqueue.h
+│ │
+│ └─src
+│ debug.c
+│ lib.c
+│ malloc.c
+│ sqqueue.c
+│
+├─master
+│ ├─inc
+│ │ hart_master.h
+│ │ hart_master_frame.h
+│ │ hart_master_req.h
+│ │ hart_master_rsp.h
+│ │
+│ └─src
+│ hart_master.c
+│ hart_master_frame.c
+│ hart_master_req.c
+│ hart_master_req_user.c
+│ hart_master_rsp.c
+│
+├─public
+│
+└─slave
+├─inc
+│ hart_slave.h
+│ hart_slave_frame.h
+│ hart_slave_req.h
+│
+└─src
+hart_slave.c
+hart_slave_frame.c
+hart_slave_req.c
+hart_slave_req_user.c
+
+## 组织结构
+
+
+
+## 模块说明
+
+| 文件 | 路径 | 说明
|
+| :-------------------- | :------ | :-------------------------------------------------------------------------------------------------------------------------------------- |
+| hart.c | ./ | 用于处理 HART(高阶实时通信技术)模块的接口。这个文件包含了模块的初始化、数据处理、Flash 读写等函数,以及一个用于处理用户事件的回调函数 |
+| hart_cache.c | ./ | 一个缓存消息模块,用于处理设备操作需要时间暂时不回复消息的情况 |
+| hart_frame.c | ./ | 包含了用于处理帧数据结构、响应码、RTC 时间转换、日期检测等功能 |
+| hart_slave.c | ./slave | Hart 从机处理函数,用于处理主机的请求并返回相应的响应 |
+| hart_slave_req.c | ./slave | 从机命令响应的处理函数 |
+| hart_slave_req_user.c | ./slave | 从机命令响应用户自定义指令的处理函数 |
+
+> 主机模块说明暂时省略
+
+### hart.c
+
+1. hart_init 函数:用于初始化 Hart 模块,根据传入的参数配置模块的工作模式(主模块或从模块)和接口。
+2. hart_handle 函数:用于处理接收到的数据,根据模块的工作模式将数据分发给对应的主机或从机处理。
+3. hart_storage_write 和 hart_storage_read 函数:用于实现 Flash 的读写操作。
+4. perform_self_test 和 perform_self_test_finish 函数:用于自检设备。
+5. device_reset 函数:用于设备复位。
+6. squawk_control 函数:用于呼叫,根据传入的参数打开或关闭呼叫功能。
+7. armed 函数:用于判断是否有技术人员按下一个特殊的按钮或按钮组合。
+8. common_event 函数:用于处理用户自定义的事件。
+
+### hart_cache.c
+
+1. 全局变量:sqqueue_ctrl_t cache,这是一个队列控制结构体,用于控制缓存队列的属性。
+2. 缓存消息结构体:hart_cache_t,这个结构体包含了一个 uuid 字段,用于存储消息的唯一标识。还有其他一些与具体设备相关的字段,例如设备状态、操作结果等。
+3. hart_cache_init(),用于初始化缓存队列。
+4. hart_cache_add(),用于向缓存中添加一条消息。首先检查缓存是否已满,如果满则返回。然后分配内存,拷贝数据,并设置 uuid。最后将数据入队。
+5. hart_cache_free(),用于释放缓存中一条消息的内存。
+6. hart_cache_get(),用于根据 uuid 获取缓存中一条消息。首先检查缓存是否为空,如果为空则返回 NULL。然后遍历缓存中的消息,如果找到匹配的 uuid,则返回该消息。否则将当前消息出队,然后重新入队。
+
+### hart_frame.c
+
+1. hart_frame_data_length_start 和 hart_frame_data_length_end 函数用于在处理请求开始和结束时记录帧数据长度位置。
+2. hart_frame_response_code_start 和 hart_frame_response_code_end 函数用于在处理请求开始和结束时记录帧响应码起始位置。
+3. hart_frame_response_communication_code 和 hart_frame_master_response_operate_code 函数用于设置和获取响应码第一个字节和第二个字节。
+4. hart_is_write_command 函数用于判断指令是否是写。
+5. hart_is_support_command 函数用于判断版本是否支持当前指令。
+6. rtc_to_timestamp 函数用于将 RTC 时间转时间戳。
+7. get_rtc_date 函数用于获取 RTC 的日期。
+8. check_date 函数用于检测日期是否有效。
+9. is_broadcast_address 函数用于判断地址是否为广播地址。
+10. timestamp_to_hmsms 函数用于将时间戳转换为小时:分钟:秒:毫秒的格式。
+
+### hart_slave.c
+
+1. hart_slave_state_check 来检查命令是否合法。如果命令合法,它将调用相应的处理函数 hart_command_ptr_arr[command]来处理命令。如果处理成功,它将返回 True,否则返回 False。
+ 在处理完命令后,函数将响应数据的长度存储在 handle->response->cache_data.payload_length 中。如果响应数据长度不为 0,它将分配内存来存储响应数据,并将数据复制到分配的内存中。最后,它将响应数据结构 handle->response->cache_data 添加到缓存中,并发送响应数据。
+
+2. hart_slave_handle 函数,该函数用于处理从机的请求。
+
+- 首先,检查输入参数是否有效。
+- 获取从机的地址。
+- 比较主机请求的地址和从机地址是否一致。如果不一致,返回错误。
+- 获取命令码。
+- 根据命令码查找对应的处理函数。如果找不到对应的处理函数,返回错误。
+- 执行处理函数,并将结果存储在 handle->response 结构体中。
+- 计算响应数据的长度。
+- 如果响应数据长度不为 0,为响应数据分配内存。
+- 将响应数据结构体添加到缓存中。
+- 返回处理成功。
+
+3. hart_slave_init 函数,用于初始化从机。
+
+- 检查输入参数是否有效。
+- 初始化从机的请求处理结构体。
+- 返回处理成功
+
+4. hart_slave_device_send 函数,用于发送响应帧给一个 HART 从设备
+
+- 定义一些变量,如响应数据长度、异或校验、数据长度指针、响应码指针等。
+- 填充响应帧的数据,包括前导码、地址、命令、负载等。
+- 计算响应帧的数据长度,并将结果存储在 data_len_p 中。
+- 计算响应帧的校验码,并将结果存储在 response_code_p 中。
+- 更新响应帧的长度字段和响应码字段。
+- 如果响应帧的数据长度大于 0,调用 handle->response_call 函数将响应帧发送给指定的 UART 索引。同时,增加设备属性的消息计数器。
+
+5. hart_slave_device_attribute_init 函数,用于从机设备属性初始化
+
+### hart_slave_req.c
+
+1. hart_slave_req_init 函数,用于初始化哈希表,用于注册从端发送给主端的命令的处理函数。
+
+- hart_command_ptr_arr 数组,用于存储命令码和处理函数的映射关系。因为命令码的使用不是连续的,因此占用了大量的空间,但是提高了查找效率。
+
+### hart_slave_req_user.c
+
+实现方式上同 hart_slave_req.c,和通用命令做区分
+
+# 移植步骤
+
+这里以 STM32 为例,介绍如何移植 HART 协议模块。
+
+1. 将 HART 协议模块的源码添加到工程中。
+ HART 协议模块中用到的 lib 也一并加入到工程中。
+
+
+2. 添加宏定义和头文件
+ 宏定义:STM32,SLAVE
+
+ 头文件路径
+
+
+3. HART 协议和应用层的中间层
+ 该文件主要实现 HART 模块需要的和 MCU 相关的接口,例如串口发送、Flash 读写等。
+
+hart_user_data_refush(): 刷新用户实时数据,包括模拟量和数字量。
+response(uint8_t uart_index, uint8_t *data, uint16_t len): 发送数据(hart 协议数据帧)。
+flash_read(uint32_t addr, uint8_t *data, uint16_t len): flash 读取接口。
+flash_write(uint32_t addr, uint8_t *data, uint16_t len): flash 写入接口。
+perform_self_test(void): 执行自检。
+device_reset(void): 设备复位。
+squawk_control(BOOL open, uint8_t second): 设备呼叫,0 一直呼叫,1-255 秒。
+armed(void): 技术人员按下一个特殊的按钮或按钮组合,指示从机应响应 command74。
+set_dynamics(device_variable_dynamics_t *const dynamics): 设置动态变量。
+hart_rx_cb(uint8_t uart_index, uint8_t \*data, uint16_t len): 串口 1、5 接收中断回调函数。
+hart_tx_complete_cb(void): 串口 1 发送完成回调函数。
+hart_uart_init(void): 串口 1 初始化。
+hart_uart_dinit(void): 串口 1 去初始化。
+hart_ble_init(void): BLE 初始化。
+hart_ble_dinit(void): BLE 去初始化。
+hart_init(void): HART 初始化。
+hart_dinit(void): HART 去初始化。
+hart_task(void): HART 任务。
+
+源码实现:
+
+```
+/*
+ * @Author: xxx
+ * @Date: 2023-08-02 08:28:36
+ * @LastEditors: xxx
+ * @LastEditTime: 2023-08-23 14:15:44
+ * @Description: 此文件主要实现板卡的HART功能
+ * Copyright (c) 2023 by xxx, All Rights Reserved.
+ */
+
+#include "app.h"
+#include "hart.h"
+#include "hart_frame.h"
+#include "uarts.h"
+#include "test_bsp.h"
+
+#define HART_UART1 USART1
+#define HART_UART2 USART5
+
+#define UART_RXSIZE (240u)
+#define UART_TXSIZE (240u)
+uart_t *uarts[APP_UART_MAX];
+
+app_dynamics_t app_dynamics;
+static __IO BOOL hart_idle = TRUE;
+
+static void hart_user_data_refush(void)
+{
+ app_analog_quantity_t *analog_quantity = &app_dynamics.analog_quantity;
+ app_digital_quantity_t *digital_quantity = &app_dynamics.digital_quantity;
+
+ // 模拟量
+ analog_quantity->input_current = adc_raw[ADC_LOOP_CHANNEL]; // 输入电流
+ analog_quantity->valve_feedback = adc_raw[ADC_PSB_CHANNEL]; // 阀门反馈
+ analog_quantity->atmospheric_pressure_source = adc_raw[ADC_BP_CHANNEL]; // 气压源压力
+ analog_quantity->pressure_at_port_a = 0; // A口压力
+ analog_quantity->pressure_at_port_b = 0; // B口压力
+ analog_quantity->amplifier_circuit = adc_raw[ADC_IPSB_CHANNEL]; // 放大器回路
+ analog_quantity->built_in_temperature = 0; // 内置温度
+ analog_quantity->ip_output_detection = rt_data.ip_output; // IP输出检测
+ analog_quantity->valve_percentage = actual_travel; // 阀位百分比
+
+ // 数字量
+ digital_quantity->input_current = loop_current; // 输入电流
+ digital_quantity->valve_feedback = adc_raw[ADC_PSB_CHANNEL]; // 阀门反馈
+ digital_quantity->atmospheric_pressure_source = adc_raw[ADC_BP_CHANNEL]; // 气压源压力
+ digital_quantity->pressure_at_port_a = 0; // A口压力
+ digital_quantity->pressure_at_port_b = 0; // B口压力
+ digital_quantity->amplifier_circuit = adc_raw[ADC_IPSB_CHANNEL]; // 放大器回路
+ digital_quantity->built_in_temperature = 0; // 内置温度
+ digital_quantity->ip_output_detection = rt_data.ip_output; // IP输出检测
+
+ digital_quantity->target_row = target_travel; // 目标行程
+ digital_quantity->current_row = actual_travel; // 实际行程
+ digital_quantity->friction = 0; // 摩擦力
+ digital_quantity->spring_force = 0; // 弹簧力
+}
+
+/**
+ * @brief 发送数据(hart协议数据帧)
+ * @param {uint8_t} *txBuf
+ * @param {uint16_t} len
+ * @return {*}
+ */
+static void response(uint8_t uart_index, uint8_t *data, uint16_t len)
+{
+#ifdef STM32
+ if (uart_index == APP_UART_1)
+ {
+ HART_CD_OFF(); // 因为DMA发送调用uart_send_data接口后会立即退出,不需要等待发送是否成功,因此HART_CD_ON需要在DMA发送完成中断中调用
+ }
+
+ uart_send_data(uarts[uart_index], data, len);
+#else
+ LOG_HEX(data, len);
+#endif
+}
+
+/**
+ * @brief flash读取接口
+ * @param {uint32_t} addr
+ * @param {uint8_t} *data
+ * @param {uint16_t} len
+ * @return {*}
+ */
+static BOOL flash_read(uint32_t addr, uint8_t *data, uint16_t len)
+{
+ m95_1_normal_read(addr, data, len);
+ return TRUE;
+}
+
+/**
+ * @brief flash写入接口
+ * @param {uint32_t} addr
+ * @param {uint8_t} *data
+ * @param {uint16_t} len
+ * @return {*}
+ */
+static BOOL flash_write(uint32_t addr, uint8_t *data, uint16_t len)
+{
+ m95_1_normal_write(addr, data, len);
+ return TRUE;
+}
+
+/**
+ * @brief 执行自检
+ * @param {*}
+ * @return {*}
+ */
+static void perform_self_test(void)
+{
+}
+
+/**
+ * @brief 设备复位
+ * @param {*}
+ * @return {*}
+ */
+static void device_reset(void)
+{
+}
+
+/**
+ * @brief 设备呼叫,0一直呼叫,1-255秒
+ * @param {*}
+ * @return {*}
+ */
+static void squawk_control(BOOL open, uint8_t second)
+{
+}
+
+/**
+ * @brief 技术人员按下一个特殊的按钮或按钮组合,指示从机应响应command74
+ * @param {*}
+ * @return {*}
+ */
+static BOOL armed(void)
+{
+ return TRUE;
+}
+
+/**
+ * @brief 设置动态变量
+ * @return {*}
+ */
+static BOOL set_dynamics(device_variable_dynamics_t *const dynamics)
+{
+ app_analog_quantity_t *analog_quantity = &app_dynamics.analog_quantity;
+ app_digital_quantity_t *digital_quantity = &app_dynamics.digital_quantity;
+
+ // 模拟量
+ dynamics->dynamics_user.analog_quantity.input_current = &analog_quantity->input_current; // 输入电流
+ dynamics->dynamics_user.analog_quantity.valve_feedback = &analog_quantity->valve_feedback; // 阀门反馈
+ dynamics->dynamics_user.analog_quantity.atmospheric_pressure_source = &analog_quantity->atmospheric_pressure_source; // 大气压力源
+ dynamics->dynamics_user.analog_quantity.pressure_at_port_a = &analog_quantity->pressure_at_port_a; // A口压力
+ dynamics->dynamics_user.analog_quantity.pressure_at_port_b = &analog_quantity->pressure_at_port_b; // B口压力
+ dynamics->dynamics_user.analog_quantity.amplifier_circuit = &analog_quantity->amplifier_circuit; // 放大器电路
+ dynamics->dynamics_user.analog_quantity.built_in_temperature = &analog_quantity->built_in_temperature; // 内置温度
+ dynamics->dynamics_user.analog_quantity.ip_output_detection = &analog_quantity->ip_output_detection; // IP输出检测
+ dynamics->dynamics_user.analog_quantity.valve_percentage = &analog_quantity->valve_percentage; // 阀位百分比
+
+ // 数字量
+ dynamics->dynamics_user.digital_quantity.input_current = &digital_quantity->input_current; // 输入电流
+ dynamics->dynamics_user.digital_quantity.valve_feedback = &digital_quantity->valve_feedback; // 阀门反馈
+ dynamics->dynamics_user.digital_quantity.atmospheric_pressure_source = &digital_quantity->atmospheric_pressure_source; // 大气压力源
+ dynamics->dynamics_user.digital_quantity.pressure_at_port_a = &digital_quantity->pressure_at_port_a; // A口压力
+ dynamics->dynamics_user.digital_quantity.pressure_at_port_b = &digital_quantity->pressure_at_port_b; // B口压力
+ dynamics->dynamics_user.digital_quantity.amplifier_circuit = &digital_quantity->amplifier_circuit; // 放大器电路
+ dynamics->dynamics_user.digital_quantity.built_in_temperature = &digital_quantity->built_in_temperature; // 内置温度
+ dynamics->dynamics_user.digital_quantity.ip_output_detection = &digital_quantity->ip_output_detection; // IP输出检测
+ dynamics->dynamics_user.digital_quantity.target_row = &digital_quantity->target_row; // 目标行程
+ dynamics->dynamics_user.digital_quantity.current_row = &digital_quantity->current_row; // 当前行程
+ dynamics->dynamics_user.digital_quantity.friction = &digital_quantity->friction; // 摩擦力
+ dynamics->dynamics_user.digital_quantity.spring_force = &digital_quantity->spring_force; // 弹簧力
+
+ return TRUE;
+}
+
+static BOOL common_event(hart_interface_user_event_e event, const void *const data)
+{
+ switch (event)
+ {
+ case HART_COMMAND_257_EVENT:
+ // 寻找、计算P / I / D
+ break;
+ case HART_COMMAND_258_EVENT:
+ // 计算 摩擦力
+ break;
+ case HART_COMMAND_259_EVENT:
+ // 计算 弹簧力
+ break;
+ case HART_COMMAND_UPDATE_EVENT:
+ // 刷新用户实时数据
+ hart_user_data_refush();
+ break;
+ case HART_COMMAND_500_EVENT:
+ // 测试命令
+ return hart_user_test((hart_user_req_t *)data);
+ default:
+ return FALSE;
+ }
+ return TRUE;
+}
+
+// 串口1、5接收中断回调函数
+static void hart_rx_cb(uint8_t uart_index, uint8_t *data, uint16_t len)
+{
+ DBG_ASSERT(uart_index < APP_UART_MAX __DBG_LINE);
+ hart_idle = FALSE;
+ // 串口1接收HART数据,因为是空闲中断处理这里只过滤掉前导码
+ hart_handle(uart_index, data, len);
+ hart_idle = TRUE;
+}
+
+static void hart_tx_complete_cb(void)
+{
+ // 串口1发送完成回调函数
+ HART_CD_ON();
+}
+
+void hart_uart_init(void)
+{
+ LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_USART1);
+ GPIO_SET_OUTPUT(HART_EN_GPIO_Port, HART_EN_Pin);
+ GPIO_SET_OUTPUT(HART_RST_GPIO_Port, HART_RST_Pin);
+ GPIO_SET_OUTPUT(HART_CD_GPIO_Port, HART_CD_Pin);
+ GPIO_SET_ALTERNATE(HART_TX_GPIO_Port, HART_TX_Pin);
+ GPIO_SET_ALTERNATE(HART_RX_GPIO_Port, HART_RX_Pin);
+ delay_ms(10);
+ // 串口1初始化开始
+ HART_CD_ON();
+ HART_RST_OFF();
+ delay_ms(20);
+ HART_RST_ON();
+ HART_EN_DISABLE();
+ HART_EN_ENABLE();
+ HART_CD_ON();
+
+ if (uarts[APP_UART_1] == NULL)
+ {
+ uarts[APP_UART_1] = uart_create(HART_UART1, TRUE, UART_RXSIZE, hart_rx_cb, TRUE, UART_TXSIZE, hart_tx_complete_cb);
+ uarts[APP_UART_1]->uart_index = APP_UART_1;
+ uarts[APP_UART_1]->dma = DMA1;
+ uarts[APP_UART_1]->dma_rx_channel = LL_DMA_CHANNEL_3;
+ uarts[APP_UART_1]->dma_tx_channel = LL_DMA_CHANNEL_2;
+ uart_recv_en(uarts[APP_UART_1]);
+ }
+ // 串口1初始化结束
+}
+
+void hart_uart_dinit(void)
+{
+ HART_EN_DISABLE();
+ LL_APB2_GRP1_DisableClock(LL_APB2_GRP1_PERIPH_USART1);
+ LL_USART_Disable(USART1);
+ GPIO_SET_ANALOG(HART_EN_GPIO_Port, HART_EN_Pin);
+ GPIO_SET_ANALOG(HART_RST_GPIO_Port, HART_RST_Pin);
+ GPIO_SET_ANALOG(HART_CD_GPIO_Port, HART_CD_Pin);
+ GPIO_SET_ANALOG(HART_TX_GPIO_Port, HART_TX_Pin);
+ GPIO_SET_ANALOG(HART_RX_GPIO_Port, HART_RX_Pin);
+}
+
+void hart_ble_init(void)
+{
+ LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_USART5);
+ GPIO_SET_OUTPUT(BLE_PWR_GPIO_Port, BLE_PWR_Pin);
+ GPIO_SET_INPUT(BLE_STATE_GPIO_Port, BLE_STATE_Pin);
+ GPIO_SET_ALTERNATE(BLE_TX_GPIO_Port, BLE_TX_Pin);
+ GPIO_SET_ALTERNATE(BLE_RX_GPIO_Port, BLE_RX_Pin);
+ BLE_EN_ENABLE();
+ delay_ms(100);
+ if (uarts[APP_UART_2] == NULL)
+ {
+ uarts[APP_UART_2] = uart_create(HART_UART2, TRUE, UART_RXSIZE, hart_rx_cb, TRUE, UART_TXSIZE, NULL);
+ uarts[APP_UART_2]->uart_index = APP_UART_2;
+ uarts[APP_UART_2]->dma = DMA1;
+ uarts[APP_UART_2]->dma_rx_channel = LL_DMA_CHANNEL_6;
+ uarts[APP_UART_2]->dma_tx_channel = LL_DMA_CHANNEL_7;
+ uart_recv_en(uarts[APP_UART_2]);
+ }
+}
+
+void hart_ble_dinit(void)
+{
+ BLE_EN_DISABLE();
+ LL_APB1_GRP1_DisableClock(LL_APB1_GRP1_PERIPH_USART5);
+ LL_USART_Disable(USART5);
+ GPIO_SET_ANALOG(BLE_PWR_GPIO_Port, BLE_PWR_Pin);
+ GPIO_SET_ANALOG(BLE_STATE_GPIO_Port, BLE_STATE_Pin);
+ GPIO_SET_ANALOG(BLE_TX_GPIO_Port, BLE_TX_Pin);
+ GPIO_SET_ANALOG(BLE_RX_GPIO_Port, BLE_RX_Pin);
+}
+
+BOOL app_hart_is_idle(void)
+{
+ return hart_idle;
+}
+
+BOOL app_hart_init(void)
+{
+ hart_init_t init;
+ init.hart_protocol_version = HART_PROTOCOL_VERSION_7;
+ init.dir = MODULE_SLAVE;
+ init.interface.response = response;
+ init.interface.flash_read = flash_read;
+ init.interface.flash_write = flash_write;
+ init.interface.perform_self_test = perform_self_test;
+ init.interface.device_reset = device_reset;
+ init.interface.squawk_control = squawk_control;
+ init.interface.armed = armed;
+ init.interface.set_dynamics = set_dynamics;
+ init.interface.common_event = common_event;
+
+ uarts[APP_UART_1] = NULL;
+ uarts[APP_UART_2] = NULL;
+ // 判断当前电流 >=8mA启动蓝牙 >=3.8mA启动uart
+ // 注:串口初始化移动到all_flow
+ // hart_uart_init();
+ // hart_ble_init();
+ return hart_init(&init);
+}
+
+```
diff --git a/User/hart/slave/inc/hart_slave.h b/User/hart/slave/inc/hart_slave.h
new file mode 100644
index 0000000..57f94b9
--- /dev/null
+++ b/User/hart/slave/inc/hart_slave.h
@@ -0,0 +1,29 @@
+/***
+ * @Author:
+ * @Date: 2023-03-20 19:27:47
+ * @LastEditors: xxx
+ * @LastEditTime: 2023-03-30 00:32:16
+ * @FilePath: \hart\hart\inc\hart_slave.h
+ * @Description: hart从机处理
+ * @email:
+ * @Copyright (c) 2023 by xxx, All Rights Reserved.
+ */
+
+#ifndef __HART_SLAVE_H__
+#define __HART_SLAVE_H__
+#include "lib.h"
+#include "./hart_slave_req.h"
+
+#pragma pack(1)
+typedef struct
+{
+ response_cb response_call; // 回复消息接口
+ hart_response_t *response;
+} hart_slave_init_t;
+#pragma pack()
+
+extern BOOL hart_slave_init(const hart_slave_init_t *const init);
+extern BOOL hart_slave_handle(uint8_t uart_index, uint8_t *rxBuf, uint16_t len);
+extern void hart_slave_device_attribute_init(void);
+extern BOOL hart_slave_device_send(hart_cache_t *cache_data);
+#endif // __HART_SLAVE_H__
diff --git a/User/hart/slave/inc/hart_slave_frame.h b/User/hart/slave/inc/hart_slave_frame.h
new file mode 100644
index 0000000..becd836
--- /dev/null
+++ b/User/hart/slave/inc/hart_slave_frame.h
@@ -0,0 +1,54 @@
+#ifndef __HART_SLAVE_FRAME_H__
+#define __HART_SLAVE_FRAME_H__
+#include "../../inc/hart_frame.h"
+#include "../../inc/hart_storage.h"
+typedef struct
+{
+ BOOL is_present;
+ uint8_t index;
+} variable_sort_t;
+
+typedef enum
+{
+ VARIABLE, // 变量
+ CONSTANT, // 常量
+ STANDARD_VARIABLE, // 标准变量
+} variable_e;
+
+typedef struct
+{
+ uint8_t preamble; // 前导码
+ uint8_t delimiter; // 分隔符
+ uint8_t command; // 命令
+ uint8_t data_start; // 数据
+ uint8_t data_end; // 数据
+ uint8_t check; // 校验
+
+ uint16_t command_count;
+ uint16_t data_count;
+ uint16_t check_count;
+} hart_frame_index_t; // hart帧中Command, Data Byte,Check Byte在frame中的位置
+
+extern hart_device_attribute_t hart_device_attribute; // 设备属性
+extern hart_device_variable_t hart_device_variable_invalid; // 无效的设备变量
+extern void hart_additional_device_status_crc_init(void); // 附加设备状态CRC初始化
+extern void get_address(uint8_t address_type, uint8_t *address, uint8_t *len); // 获取设备的地址
+extern hart_device_variable_t *get_device_variable(uint8_t code); // 获取设备变量
+extern void set_device_variable(hart_device_variable_t *cmd, uint8_t *data); // 设置设备变量
+extern hart_device_constant_t *get_device_constant(uint8_t code); // 获取设备常量
+extern void set_device_constant(hart_device_constant_t *cmd, uint8_t *data); // 设置设备常量
+extern BOOL set_trim_point(hart_device_variable_t *variable, response_communication_code_e *cod); // 设置校准点
+extern hart_device_standard_variable_t *get_device_standard_variable(uint8_t code); // 获取设备标准变量
+extern hart_device_variable_t *get_device_variable_by_standard_code(uint8_t code); // 根据标准代码获取设备变量
+extern analog_channel_t *get_analog_channel(analog_channel_number_codes_e code); // 获取模拟通道
+extern BOOL copy_device_dynamic_variable(uint8_t set_code, uint8_t dynamic_code); // 设置设备动态变量
+extern variable_e get_variable_type(uint8_t code); // 获取变量类型
+extern void mock_data(void);
+extern void hart_device_variable_sort(void); // 排序设备变量
+extern void hart_device_constant_sort(void); // 排序设备常量
+extern void hart_device_status_set_operational_state(device_operational_state_e state); // 设置设备状态
+extern void hart_device_status_clr_operational_state(device_operational_state_e state); // 清除设备状态
+extern void hart_device_status_set_communication_code(response_error_communication_code_e code); // 设置设备通信状态
+extern void hart_device_status_clr_communication_code(response_error_communication_code_e code); // 清除设备通信状态
+extern BOOL hart_device_status_communication_code_is_error(void); // 判断设备通信状态是否为错误
+#endif
diff --git a/User/hart/slave/inc/hart_slave_req.h b/User/hart/slave/inc/hart_slave_req.h
new file mode 100644
index 0000000..7d167e7
--- /dev/null
+++ b/User/hart/slave/inc/hart_slave_req.h
@@ -0,0 +1,9 @@
+#ifndef __HART_SLAVE_REQ_H__
+#define __HART_SLAVE_REQ_H__
+#include "lib.h"
+#include "./hart_slave_frame.h"
+
+extern void hart_slave_req_init(void);
+extern void hart_slave_req_init_user(void);
+
+#endif // __HART_SLAVE_REQ_H__
diff --git a/User/hart/slave/src/hart_slave.c b/User/hart/slave/src/hart_slave.c
new file mode 100644
index 0000000..70f4d0e
--- /dev/null
+++ b/User/hart/slave/src/hart_slave.c
@@ -0,0 +1,605 @@
+/*
+ * @Author:
+ * @Date: 2023-03-20 19:27:47
+ * @LastEditors: xxx
+ * @LastEditTime: 2023-08-16 09:15:39
+ * @FilePath: \hart\hart\hart_slave.c
+ * @Description:
+ * email:
+ * Copyright (c) 2023 by xxx, All Rights Reserved.
+ */
+
+#include "../inc/hart_slave.h"
+#include "../inc/hart_slave_frame.h"
+static hart_slave_init_t *handle;
+hart_frame_index_t frame_index; // 帧索引
+// 内部状态检查
+static response_communication_code_e hart_slave_state_check(uint8_t command, BOOL is_master)
+{
+ // 检查是否自检过程中
+ if (TRUE == hart_device_attribute.device_status.busy)
+ {
+ return RESPONSE_COMMUNICATION_CODE_32;
+ }
+
+ // 检查是否开启的写保护
+ if (TRUE == hart_is_write_command(command))
+ {
+ if (WRITE_PROTECT_CODE_WRITE_PROTECT == hart_device_attribute.flash_variable.write_protect_code)
+ {
+ return RESPONSE_COMMUNICATION_CODE_7;
+ }
+ }
+
+ if (FALSE == hart_is_support_command(command)) // 当前模式使用的版本号,请求命令是否支持
+ return RESPONSE_COMMUNICATION_CODE_64; // RESPONSE_COMMUNICATION_CODE_13;ZKBW
+
+ // 检查是否锁定
+ if (TRUE == hart_is_write_command(command))
+ {
+ if (LOCK_DEVICE_CODE_0 != hart_device_attribute.flash_variable.lock_code)
+ {
+ return RESPONSE_COMMUNICATION_CODE_16;
+ }
+ }
+ return RESPONSE_COMMUNICATION_CODE_0;
+}
+
+static BOOL hart_slave_command_check(uint32_t command, hart_command_req_t *req)
+{
+ if (hart_command_ptr_arr[command] == FALSE)
+ {
+ handle->response->code = RESPONSE_COMMUNICATION_CODE_64;
+ return TRUE;
+ }
+ else
+ {
+ return hart_command_ptr_arr[command](req, handle->response); // 执行命令
+ }
+}
+
+/**
+ * @brief HART 从机 UART 错误处理函数
+ *
+ * 当 UART 发生错误时,调用此函数进行处理。
+ *
+ */
+static BOOL hart_slave_uart_error(uint8_t uart_index)
+{
+ uint16_t error_count = 0;
+ uint16_t rx_index = 0;
+ hart_uart_error_t *errors = NULL;
+ BOOL ret = TRUE;
+ error_count = hart_uart_error_count(uart_index);
+ if (error_count != 0)
+ {
+ errors = (hart_uart_error_t *)osel_mem_alloc(error_count * sizeof(hart_uart_error_t));
+ DBG_ASSERT(errors != NULL __DBG_LINE);
+ hart_uart_errors(uart_index, errors);
+
+ for (uint16_t i = 0; i < error_count; i++)
+ {
+ rx_index = errors[i].rx_index;
+ if (rx_index == frame_index.command ||
+ rx_index == frame_index.check ||
+ (rx_index >= frame_index.data_start && rx_index <= frame_index.data_end && frame_index.data_end != frame_index.data_start))
+ {
+ switch (errors[i].uart_error)
+ {
+ case HART_UART_PARITY_ERROR: // 奇偶校验错误中断
+ hart_device_status_set_communication_code(RESPONSE_ERROR_COMMUNICATION_CODE_6);
+ break;
+ case HART_UART_FRAME_ERROR: // 帧错误中断
+ hart_device_status_set_communication_code(RESPONSE_ERROR_COMMUNICATION_CODE_4);
+ break;
+ case HART_UART_OVERRUN_ERROR: // 串口溢出中断
+ hart_device_status_set_communication_code(RESPONSE_ERROR_COMMUNICATION_CODE_5);
+ break;
+ default:
+ DBG_ASSERT(FALSE __DBG_LINE);
+ break;
+ }
+
+ if (rx_index == frame_index.command)
+ {
+ frame_index.command_count++;
+ }
+ else if (rx_index == frame_index.check)
+ {
+ frame_index.check_count++;
+ }
+ else
+ {
+ frame_index.data_count++;
+ }
+ }
+ else
+ {
+ if (rx_index >= frame_index.preamble)
+ {
+ ret = FALSE;
+ break;
+ }
+ }
+ }
+ osel_mem_free(errors);
+ }
+
+ return ret;
+}
+BOOL macth_delimiter(uint8_t delimiter)
+{
+ if ((delimiter & 0x07) != 0x02)
+ {
+ return FALSE;
+ }
+ else if (delimiter & 0x60) // 0x78 = (0x60 | 0x18) 0x60 扩展字节 0x18 FSK orPSK
+ {
+ return FALSE;
+ }
+ else
+ {
+ return TRUE;
+ }
+}
+
+/**
+ * @brief hart从机处理函数
+ * @param {uint8_t} uart_index: 串口索引
+ * @param {uint8_t} uart_error: 串口错误码
+ * @param {uint8_t} *rxBuf: 接收到的数据
+ * @param {uint16_t} len: 接收到的数据长度
+ * @return: TRUE: 处理成功
+ * FALSE: 处理失败
+ */
+BOOL hart_slave_handle(uint8_t uart_index, uint8_t *rxBuf, uint16_t len)
+{
+ if (!DBG_ASSERT(rxBuf != NULL __DBG_LINE))
+ return FALSE;
+ if (!DBG_ASSERT(len != 0 __DBG_LINE))
+ return FALSE;
+ uint8_t xor = 0; // 异或校验
+ // uint8_t front = 0;
+ uint8_t rsp_len = 0; // 响应数据长度
+ uint16_t offset = 0;
+ uint8_t address_length = 0;
+ hart_short_address_u poll_address;
+ hart_long_address_u long_address;
+ hart_long_address_u long_address_tmp;
+ uint8_t *origin_address = NULL;
+ uint8_t preamble_count = 0; // ZKBW
+ hart_command_req_t req;
+ hart_delimiter_u delimiter;
+ uint32_t command = 0;
+ BOOL ret = FALSE;
+
+ // 清除响应码 ZKBW
+ hart_device_attribute.device_status.communication_code = 0x00;
+ frame_index.preamble = 0;
+ // 前导码和校验码检查
+ {
+ // 查找前导符
+
+ while (len > 0)
+ {
+ if (rxBuf[offset] == HART_PREAMBLE)
+ {
+ preamble_count++;
+ }
+ else
+ {
+ if (preamble_count >= 2)
+ {
+ if (macth_delimiter(rxBuf[offset]) == TRUE)
+ {
+ break;
+ }
+ else
+ {
+ preamble_count = 0;
+ frame_index.preamble = 0;
+ }
+ }
+ }
+ if (preamble_count != 0)
+ {
+ if (frame_index.preamble == 0)
+ {
+ frame_index.preamble = offset;
+ }
+ }
+
+ offset++;
+ len--;
+ }
+
+ if (len < 2) // 前导符后至少有2个字节
+ return FALSE;
+ }
+
+ if (preamble_count < 2)
+ {
+ return FALSE;
+ }
+
+ hart_device_attribute.message_count.stx++;
+ delimiter.data = 0;
+ osel_memset((uint8_t *)&poll_address, 0, sizeof(hart_short_address_u));
+ osel_memset((uint8_t *)&long_address, 0, sizeof(hart_long_address_u));
+ osel_memset((uint8_t *)&long_address_tmp, 0, sizeof(hart_long_address_u));
+
+ handle->response->code = RESPONSE_COMMUNICATION_CODE_0;
+ handle->response->data_length = 0;
+ handle->response->data_p = handle->response->data;
+ osel_memset((uint8_t *)handle->response->data, 0, HART_RESPONSE_MAX_LEN);
+ osel_memset((uint8_t *)&req, 0, sizeof(hart_command_req_t));
+
+ // 判断是否来自主机的请求
+ hart_delimiter_u *delimiter_p = (hart_delimiter_u *)&rxBuf[offset];
+ frame_index.delimiter = offset;
+ if (delimiter_p->bits.frame_type != HART_STX_FRAME)
+ {
+ return FALSE;
+ }
+
+ // if (delimiter_p->bits.physical_layer != 0) // ZKBW
+ // {
+ // return FALSE;
+ // }
+
+ // if (delimiter_p->bits.ext_bytes > 3)
+ // {
+ // return FALSE;
+ // }
+
+ req.delimiter_type = delimiter_p->bits.addr_type;
+ offset++;
+
+ get_address(req.delimiter_type, req.address, &address_length); // 获取本机的地址
+ // 比较主机请求的地址和本地地址是否一致
+ if (delimiter_p->bits.addr_type == HART_DELIMITER_TYPE_SHORT)
+ {
+ poll_address.data = rxBuf[offset] & 0xbf;
+ uint8_t tmp = poll_address.data & 0x3f;
+ origin_address = &tmp;
+ if (*origin_address != req.address[0])
+ {
+ LOG_PRINT("short origin_address!=address,origin_address=%d,address=%d\n", *origin_address, req.address[0]);
+ return FALSE;
+ }
+ req.master = poll_address.bits.master;
+ }
+ else
+ {
+ osel_memcpy((uint8_t *)&long_address.data, &rxBuf[offset], sizeof(uint40_t));
+ uint8_t tmp1[HART_LONG_ADDRESS_LEN], tmp2[HART_LONG_ADDRESS_LEN];
+ osel_memset(tmp1, 0, HART_LONG_ADDRESS_LEN);
+ osel_memset(tmp2, 0, HART_LONG_ADDRESS_LEN);
+ tmp1[0] = long_address.data.bs[0] & 0x3f;
+ osel_memcpy(&tmp1[1], (uint8_t *)&long_address.bits.slave, 4);
+ origin_address = tmp1;
+
+ // long_address_tmp.bits.reserved = req.address[0];
+ osel_memcpy((uint8_t *)&long_address_tmp.data, &req.address[0], HART_LONG_ADDRESS_LEN);
+ tmp2[0] = long_address_tmp.data.bs[0] & 0x3f;
+ osel_memcpy(&tmp2[1], (uint8_t *)&long_address_tmp.bits.slave, 4);
+
+// 比较两个地址是否相等
+#if (HART_REQUEST_ADDRESS_CHECK == TRUE)
+ uint8_t *origin_address_tmp = tmp2;
+ uint8_t broadcast[5] = {0x00, 0x00, 0x00, 0x00, 0x00}; // ZKBW
+ if (osel_memcmp(origin_address, origin_address_tmp, HART_LONG_ADDRESS_LEN) != 0)
+ {
+ if (osel_memcmp(origin_address, broadcast, HART_LONG_ADDRESS_LEN) != 0)
+ {
+ LOG_PRINT("long origin_address!=address\n");
+ return FALSE;
+ }
+ }
+#endif
+
+ req.master = long_address.bits.master;
+ }
+ offset += address_length;
+
+ req.command = rxBuf[offset];
+ frame_index.command = offset;
+ offset++;
+
+ // if (req.command == HART_COMMAND_31)
+ // {
+ // __NOP();
+ // }
+
+ req.data_length = rxBuf[offset++]; // 数据长度
+
+ // ZKBW STRAT
+ // req.expansion = req.command == HART_COMMAND_31 ? TRUE : FALSE; // 是否扩展命令
+
+ // if (req.expansion == TRUE)
+ // {
+ // req.data_length -= 2; // 31命令的数据长度需要减去2个字节的扩展字节
+ // osel_memcpy((uint8_t *)&req.expansion_command, &rxBuf[offset], 2); // 31命令的扩展字节
+ // offset += 2;
+ // req.expansion_command = B2S_UINT16(req.expansion_command);
+ // command = req.expansion_command;
+ // }
+ // else //ZKBW END
+ {
+ command = req.command;
+ }
+ if (delimiter_p->bits.addr_type == HART_DELIMITER_TYPE_SHORT)
+ {
+ if (command != 0)
+ {
+ return FALSE;
+ }
+ }
+ if (req.data_length > 0)
+ {
+ // 载荷+校验+当前偏移-前导符数目 = 界定符到校验码总长度
+ if (req.data_length + 1 + offset - frame_index.delimiter <= len) // ZKBW
+ {
+ if (req.data_length > sizeof(hart_command_req_data_u))
+ {
+ return FALSE;
+ }
+
+ osel_memcpy((uint8_t *)&req.data, &rxBuf[offset], req.data_length); // 根据数据长度复制数据
+ frame_index.data_start = offset;
+ frame_index.data_end = offset + req.data_length - 1;
+ offset += req.data_length;
+ }
+ else
+ {
+ return FALSE;
+ }
+ }
+
+ // 异或校验
+ xor = xor_compute(&rxBuf[frame_index.delimiter], offset - frame_index.delimiter);
+ frame_index.check = offset;
+ if (xor != rxBuf[offset])
+ {
+ hart_device_status_set_communication_code(RESPONSE_ERROR_COMMUNICATION_CODE_3); // ZKBW
+ LOG_PRINT("[hart_handle] xro error");
+ }
+
+ // 数据组包解析超时判断开始
+ frame_data_parse_time_start(HART_DATA_PARSE_TIME);
+
+ // delimiter.bits.frame_type = HART_ACK_FRAME; // 应答帧
+ // delimiter.bits.addr_type = delimiter_p->bits.addr_type;
+ // delimiter.bits.ext_bytes = delimiter_p->bits.ext_bytes;
+ // delimiter.bits.physical_layer = delimiter_p->bits.physical_layer;
+ // 填充缓存数据结构
+ handle->response->cache_data.delimiter.data = delimiter.data;
+ handle->response->cache_data.command = req.command;
+ handle->response->cache_data.expansion_command = req.expansion_command;
+ handle->response->cache_data.expansion = req.expansion;
+ handle->response->cache_data.address_length = address_length;
+
+ // 填充地址
+ if (req.delimiter_type == HART_DELIMITER_TYPE_SHORT)
+ {
+ delimiter.data = 0x06;
+ if (req.master == HART_MASTER) // 第一主站请求报文 ZKBW
+ {
+ handle->response->cache_data.address[0] = poll_address.data & 0xbf;
+ }
+ else // 第二主站请求报文 ZKBW
+ {
+ handle->response->cache_data.address[0] = poll_address.data & 0x3f;
+ }
+ }
+ else
+ {
+ delimiter.data = 0x86;
+ if (req.master == HART_MASTER) // 第一主站请求报文 ZKBW
+ {
+ handle->response->cache_data.address[0] = long_address.data.bs[0] & 0xbf;
+ }
+ else // 第二主站请求报文 ZKBW
+ {
+ handle->response->cache_data.address[0] = long_address.data.bs[0] & 0x3f;
+ }
+ // handle->response->cache_data.address[0] = long_address.data.bs[0]& 0x3f;
+ osel_memcpy(&handle->response->cache_data.address[1], (uint8_t *)&long_address.data.bs[1], HART_LONG_ADDRESS_LEN - 1); // 长地址5个字节
+ }
+ hart_device_attribute.host = req.master;
+
+ handle->response->cache_data.delimiter.data = delimiter.data; // ZKBW
+ handle->response->code = RESPONSE_COMMUNICATION_CODE_0;
+ if (hart_device_status_communication_code_is_error() == FALSE)
+ {
+ handle->response->code = hart_slave_state_check(command, (req.master == HART_MASTER ? TRUE : FALSE)); // 内部状态检查
+ if (RESPONSE_COMMUNICATION_CODE_0 == handle->response->code)
+ {
+
+ ret = hart_slave_command_check(command, &req);
+
+ if (ret == FALSE)
+ {
+ if (handle->response->code == RESPONSE_COMMUNICATION_CODE_127)
+ {
+ // 需要将回复的消息缓存起来,等待下次发送,UUID在每个处理指令的函数中赋值
+ rsp_len = handle->response->data_p - handle->response->data;
+ handle->response->cache_data.payload_length = rsp_len;
+ if (rsp_len != 0)
+ {
+ handle->response->data_p = handle->response->data;
+ handle->response->cache_data.payload = osel_mem_alloc(rsp_len);
+ osel_memcpy(handle->response->cache_data.payload, handle->response->data, rsp_len);
+ }
+ handle->response->cache_data.code = RESPONSE_COMMUNICATION_CODE_0;
+ handle->response->cache_data.uart_index = uart_index;
+ hart_cache_add(handle->response->cache_data);
+ }
+ return FALSE;
+ }
+ }
+ }
+ rsp_len = handle->response->data_p - handle->response->data;
+ handle->response->cache_data.payload_length = rsp_len;
+
+ if (rsp_len != 0)
+ {
+ handle->response->data_p = handle->response->data;
+ handle->response->cache_data.payload = osel_mem_alloc(rsp_len);
+ osel_memcpy(handle->response->cache_data.payload, handle->response->data, rsp_len);
+ }
+ handle->response->cache_data.code = handle->response->code;
+ handle->response->cache_data.uart_index = uart_index;
+
+ // 串口通讯错误检查
+ if (hart_slave_uart_error(uart_index) == FALSE)
+ {
+ return FALSE;
+ }
+
+ handle->response->cache_data.code |= hart_device_attribute.device_status.communication_code;
+
+ return hart_slave_device_send(&handle->response->cache_data);
+}
+
+/**
+ * @brief 从机初始化
+ * @return {*}
+ */
+BOOL hart_slave_init(const hart_slave_init_t *const init)
+{
+ if (!DBG_ASSERT(init != NULL __DBG_LINE))
+ return FALSE;
+ handle = (hart_slave_init_t *)init;
+ handle->response->code = RESPONSE_COMMUNICATION_CODE_0;
+ hart_slave_req_init(); // 从机请求初始化
+
+ return TRUE;
+}
+
+/**
+ * @brief 发送响应帧给一个HART从设备
+ * @param {hart_cache_t} *cache_data:缓存数据指针
+ * @return {*}
+ * @note 该函数用于向HART从设备发送响应帧。
+ */
+BOOL hart_slave_device_send(hart_cache_t *cache_data)
+{
+ uint8_t rsp_len = 0; // 响应数据长度
+ uint8_t xor = 0; // 异或校验
+ uint8_t *data_len_p = NULL; // 数据长度指针
+ uint8_t *response_code_p = NULL;
+ uint8_t preamble_def = hart_device_attribute.flash_variable.s2m_preambles; // 引导码长度
+ DBG_ASSERT(cache_data != NULL __DBG_LINE);
+ if (cache_data->payload_length > 0)
+ {
+ handle->response->data_p = handle->response->data;
+ }
+
+ // 填充回复数据
+ // 填充引导码
+ for (uint8_t i = 0; i < preamble_def; i++)
+ {
+ *handle->response->data_p++ = HART_PREAMBLE;
+ }
+ // 填充界定符
+ *handle->response->data_p++ = cache_data->delimiter.data;
+ // 填充地址
+ osel_memcpy(handle->response->data_p, (uint8_t *)&cache_data->address, cache_data->address_length); // 长地址5个字节
+ handle->response->data_p += cache_data->address_length;
+ // 填充命令
+ *handle->response->data_p++ = cache_data->command;
+
+ data_len_p = handle->response->data_p;
+ hart_frame_data_length_start(&data_len_p);
+ handle->response->data_p++;
+ response_code_p = handle->response->data_p;
+ hart_frame_response_code_start(&response_code_p);
+ handle->response->data_p += 2;
+
+ if (cache_data->expansion == TRUE)
+ {
+ cache_data->expansion_command = S2B_UINT16(cache_data->expansion_command);
+ osel_memcpy(handle->response->data_p, (uint8_t *)&cache_data->expansion_command, 2);
+ handle->response->data_p += 2;
+ }
+
+ // 填充载荷
+ if (cache_data->payload_length != 0)
+ {
+
+ osel_memcpy(handle->response->data_p, cache_data->payload, cache_data->payload_length);
+ handle->response->data_p += cache_data->payload_length;
+ osel_mem_free(cache_data->payload);
+ }
+
+ hart_frame_data_length_end(handle->response->data_p);
+ hart_frame_response_communication_code(cache_data->code);
+ hart_frame_slave_response_operate_code(&hart_device_attribute);
+
+ // 填充校验码
+ rsp_len = handle->response->data_p - handle->response->data;
+ xor = xor_compute(&handle->response->data[preamble_def], (rsp_len - preamble_def)); // 除前导码和校验字节外所有字节的异或之后
+ *handle->response->data_p++ = xor;
+ rsp_len++;
+ handle->response->data_length = rsp_len;
+
+ // 数据组包解析超时判断结束
+ if (hart_timeout_compare() == FALSE)
+ {
+ return FALSE;
+ }
+
+ if (handle->response->data_length > 0)
+ {
+ handle->response_call(cache_data->uart_index, handle->response->data, handle->response->data_length);
+ hart_device_attribute.message_count.ack++;
+
+ // 发送完第一帧后,需要清理设备状态
+ {
+ if (hart_device_attribute.message_count.ack == 1)
+ {
+ hart_device_status_clr_operational_state(DEVICE_OPERATIONAL_STATE_6);
+ }
+ }
+ }
+
+ return TRUE;
+}
+
+/**
+ * @brief 从机设备属性初始化
+ * @return {*}
+ */
+void hart_slave_device_attribute_init(void)
+{
+ real_time_clock_t *pd = &hart_device_attribute.real_time_clock;
+ // 锁定状态
+ if (LOCK_DEVICE_CODE_1 == hart_device_attribute.flash_variable.lock_code)
+ {
+ hart_device_attribute.flash_variable.lock_code = LOCK_DEVICE_CODE_0;
+ }
+
+ // 设置rtc标志
+ if (pd->time == 0)
+ {
+ pd->rtc_flags = REAL_TIME_CLOCK_FLAGS_2;
+ }
+ else
+ {
+ pd->rtc_flags = REAL_TIME_CLOCK_FLAGS_1;
+ }
+
+ // 设备状态
+ osel_memset((uint8_t *)&hart_device_attribute.device_status, 0, sizeof(hart_device_status_t));
+ hart_device_attribute.device_status.operational_state = DEVICE_OPERATIONAL_STATE_0;
+ hart_device_attribute.device_status.additional_device_status.extended_device_status = EXTENDED_DEVICE_STATUS_0;
+ hart_device_attribute.device_status.additional_device_status.device_operating_mode = OPERATING_MODE_CODES_0;
+ hart_device_attribute.device_status.additional_device_status.standardized_status0 = STANDARDIZED_STATUS0_2;
+ hart_device_attribute.device_status.additional_device_status.standardized_status1 = STANDARDIZED_STATUS1_3;
+ // hart_device_attribute.device_status.additional_device_status.analog_channel_saturated = ANALOG_CHANNEL_SATURATED_1;
+ // hart_device_attribute.device_status.additional_device_status.standardized_status2 = STANDARDIZED_STATUS2_0;
+ // hart_device_attribute.device_status.additional_device_status.standardized_status3 = STANDARDIZED_STATUS3_5;
+ // hart_device_attribute.device_status.additional_device_status.analog_channel_fixed = ANALOG_CHANNEL_FIXED_1;
+ hart_additional_device_status_crc_init();
+}
diff --git a/User/hart/slave/src/hart_slave_frame.c b/User/hart/slave/src/hart_slave_frame.c
new file mode 100644
index 0000000..58625fc
--- /dev/null
+++ b/User/hart/slave/src/hart_slave_frame.c
@@ -0,0 +1,563 @@
+#include "../inc/hart_slave_frame.h"
+
+hart_device_attribute_t hart_device_attribute; // 设备属性
+const uint32_t invalid_value = HART_INVALID_VALUE;
+// 无效的设备变量
+hart_device_variable_t hart_device_variable_invalid = {
+ // ZKBW
+ .code = DIN_250,
+ .classification = DEVICE_VARIABLE_CLASSIFICATION_CODE_0,
+ .units_code = DIN_250,
+ .value = (float32 *)&invalid_value,
+ .status = {
+ .bits.device_family_specific_status = 0,
+ .bits.more_device_variable_status_available = 0,
+ .bits.limit_status = DEVICE_VARIABLE_STATUS_CONSTANT,
+ .bits.process_data_status = DEVICE_VARIABLE_STATUS_BAD,
+ },
+ .user_param.type = USER_FLOAT,
+};
+
+// 无效的设备常量
+hart_device_constant_t hart_device_constant_invalid = {
+ // ZKBW
+ .code = DIN_250,
+ .classification = DEVICE_VARIABLE_CLASSIFICATION_CODE_0,
+ .units_code = DIN_250,
+ .value = (float32 *)&invalid_value,
+};
+
+static void hart_configuration_count_update(void)
+{
+ if (hart_device_attribute.host == HART_MASTER)
+ {
+ hart_device_attribute.flash_variable.master_cfg_update_count++;
+ hart_storage_write_item(HART_STORAGE_PARAMS, HPB_MASTER_CFG_UPDATE_COUNT,
+ (uint8_t *)&hart_device_attribute.flash_variable.master_cfg_update_count);
+ }
+ else
+ {
+ hart_device_attribute.flash_variable.slave_cfg_update_count++;
+ hart_storage_write_item(HART_STORAGE_PARAMS, HPB_SLAVE_CFG_UPDATE_COUNT,
+ (uint8_t *)&hart_device_attribute.flash_variable.slave_cfg_update_count);
+ }
+}
+
+/**
+ * @brief 设置HART设备的操作状态
+ *
+ * 根据传入的设备操作状态,更新设备的操作状态。
+ *
+ * @param state 设备操作状态,类型为device_operational_state_e
+ */
+void hart_device_status_set_operational_state(device_operational_state_e state)
+{
+ if (state == DEVICE_OPERATIONAL_STATE_0)
+ {
+ hart_device_attribute.device_status.operational_state = DEVICE_OPERATIONAL_STATE_0;
+ }
+ else
+ {
+ BIT_SET(hart_device_attribute.device_status.operational_state, state);
+ if (state == DEVICE_OPERATIONAL_STATE_7)
+ {
+ hart_configuration_count_update();
+ }
+ }
+}
+
+/**
+ * @brief 设置HART设备状态通信代码
+ *
+ * 此函数用于设置HART设备的状态通信代码。
+ *
+ * @note 该函数当前为空实现,具体实现需要根据实际需求进行编写。
+ */
+void hart_device_status_set_communication_code(response_error_communication_code_e code)
+{
+ BIT_SET(hart_device_attribute.device_status.communication_code, RESPONSE_ERROR_COMMUNICATION_CODE_7 | code);
+}
+
+/**
+ * @brief 判断HART设备通信代码是否出错
+ *
+ * 检查HART设备的通信代码是否包含指定的错误代码。
+ *
+ * @return 如果通信代码包含错误代码,则返回TRUE;否则返回FALSE。
+ */
+BOOL hart_device_status_communication_code_is_error(void)
+{
+ return BIT_IS_SET(hart_device_attribute.device_status.communication_code, RESPONSE_ERROR_COMMUNICATION_CODE_7);
+}
+
+/**
+ * @brief 清除HART设备的操作状态
+ *
+ * 该函数用于清除HART设备的操作状态。
+ *
+ * @param state 操作状态枚举值
+ * - DEVICE_OPERATIONAL_STATE_0: 设备操作状态0
+ *
+ * @return 无返回值
+ */
+void hart_device_status_clr_operational_state(device_operational_state_e state)
+{
+ if (state == DEVICE_OPERATIONAL_STATE_0)
+ {
+ hart_device_attribute.device_status.operational_state = DEVICE_OPERATIONAL_STATE_0;
+ }
+ else
+ {
+ BIT_CLR(hart_device_attribute.device_status.operational_state, state);
+ if (state == DEVICE_OPERATIONAL_STATE_7)
+ {
+ hart_configuration_count_update();
+ }
+ }
+}
+
+/**
+ * @brief 清除HART设备通信状态码
+ *
+ * 清除指定的HART设备通信状态码。
+ *
+ * @param code 要清除的通信状态码
+ */
+void hart_device_status_clr_communication_code(response_error_communication_code_e code)
+{
+ BIT_CLR(hart_device_attribute.device_status.communication_code, code);
+ if (hart_device_attribute.device_status.communication_code == RESPONSE_ERROR_COMMUNICATION_CODE_7)
+ {
+ hart_device_attribute.device_status.communication_code = 0;
+ }
+}
+
+/**
+ * @brief 对设备变量进行排序
+ *
+ * 将设备变量按照其代码进行排序,并更新设备属性中的设备变量数组。
+ *
+ * @note 此函数会对设备属性中的设备变量数组进行修改,以按照代码进行排序。
+ */
+void hart_device_variable_sort(void)
+{
+ uint8_t i = 0;
+ uint8_t index = 0;
+ variable_sort_t sorts[DIN_250];
+ osel_memset((uint8_t *)sorts, 0, sizeof(variable_sort_t) * DIN_250);
+ hart_device_variable_t *sorted_device_variable = osel_mem_alloc(sizeof(hart_device_variable_t) * ARRAY_LEN(hart_device_attribute.device_variable));
+ DBG_ASSERT(sorted_device_variable != NULL __DBG_LINE);
+
+ index = 0;
+ for (i = 0; i < ARRAY_LEN(hart_device_attribute.device_variable); i++)
+ {
+ uint8_t code = hart_device_attribute.device_variable[i].code;
+ if (code != DIN_250)
+ {
+ sorts[code].is_present = TRUE;
+ sorts[code].index = index;
+ osel_memcpy((uint8_t *)&sorted_device_variable[index], (uint8_t *)&hart_device_attribute.device_variable[i], sizeof(hart_device_variable_t));
+ index++;
+ }
+ }
+ index = 0;
+ for (i = 0; i < DIN_250; i++)
+ {
+ if (sorts[i].is_present)
+ {
+ osel_memcpy((uint8_t *)&hart_device_attribute.device_variable[index], (uint8_t *)&sorted_device_variable[sorts[i].index], sizeof(hart_device_variable_t));
+ index++;
+ }
+ }
+
+ osel_mem_free(sorted_device_variable);
+}
+
+void hart_device_constant_sort(void)
+{
+ uint8_t i = 0;
+ uint8_t index = 0;
+ variable_sort_t sorts[DIN_250];
+ osel_memset((uint8_t *)sorts, 0, sizeof(variable_sort_t) * DIN_250);
+ hart_device_constant_t *sorted_device_constant = osel_mem_alloc(sizeof(hart_device_constant_t) * ARRAY_LEN(hart_device_attribute.device_constant));
+ DBG_ASSERT(sorted_device_constant != NULL __DBG_LINE);
+
+ index = 0;
+ for (i = 0; i < ARRAY_LEN(hart_device_attribute.device_constant); i++)
+ {
+ uint8_t code = hart_device_attribute.device_constant[i].code;
+ if (code != DIN_250)
+ {
+ sorts[code].is_present = TRUE;
+ sorts[code].index = index;
+ osel_memcpy((uint8_t *)&sorted_device_constant[index], (uint8_t *)&hart_device_attribute.device_constant[i], sizeof(hart_device_constant_t));
+ index++;
+ }
+ }
+ index = 0;
+ for (i = 0; i < DIN_250; i++)
+ {
+ if (sorts[i].is_present)
+ {
+ osel_memcpy((uint8_t *)&hart_device_attribute.device_constant[index], (uint8_t *)&sorted_device_constant[sorts[i].index], sizeof(hart_device_constant_t));
+ index++;
+ }
+ }
+ osel_mem_free(sorted_device_constant);
+}
+
+/**
+ * @brief 设备初始化、设备状态也设置完成后,调用改接口更新crc字段记录附加设备状态初始值
+ * @return {*}
+ */
+void hart_additional_device_status_crc_init(void)
+{
+ hart_device_attribute.device_status.additional_device_status_crc = crc16_compute((uint8_t *)&hart_device_attribute.device_status.additional_device_status, sizeof(additional_device_status_t));
+}
+
+// 获取当前模块正在使用的协议版本号
+uint8_t hart_get_current_protocol_version(void)
+{
+ return *hart_device_attribute.hart_protocol_version;
+}
+
+/**
+ * @brief 根据代码值获取变量类型
+ *
+ * 根据给定的代码值(code),返回对应的变量类型。
+ *
+ * @param code 代码值
+ * @return 根据代码值返回对应的变量类型
+ */
+variable_e get_variable_type(uint8_t code)
+{
+ if (code <= DIN_PRIMARY_FEEDBACK)
+ {
+ return VARIABLE;
+ }
+ else if (code > DIN_PRIMARY_FEEDBACK && code < DIN_242)
+ {
+ return CONSTANT;
+ }
+ else
+ {
+ return STANDARD_VARIABLE;
+ }
+}
+
+// 获取设备常量
+hart_device_constant_t *get_device_constant(uint8_t code)
+{
+ // 遍历常量
+ hart_device_constant_t *p = hart_device_attribute.device_constant;
+ uint8_t low = 0;
+ uint8_t high = HART_DEVICE_CONSTANT_LEN - 1;
+
+ if (code <= DIN_PRIMARY_FEEDBACK || code >= DIN_242)
+ {
+ DBG_ASSERT(FALSE __DBG_LINE); // 变量单位代码不应当在本函数中传入,使用本函数之前应当先判断是否是变量
+ }
+
+ // 查找速度优化,使用二分查找
+ while (low <= high)
+ {
+ uint8_t mid = (uint8_t)((low + high) * 0.5f);
+ if (p[mid].code == code)
+ {
+ return &p[mid];
+ }
+ else if (p[mid].code < code)
+ {
+ low = mid + 1;
+ }
+ else
+ {
+ high = mid - 1;
+ }
+ }
+ // 未找到匹配的code,返回无效的设备变量
+ return &hart_device_constant_invalid;
+}
+
+// 获取设备变量
+hart_device_variable_t *get_device_variable(uint8_t code)
+{
+ if (code != DIN_250 && code != DIN_251)
+ {
+ hart_device_variable_t *p = hart_device_attribute.device_variable;
+ for (uint8_t i = 0; i < HART_DEVICE_VARIABLE_LEN; i++)
+ {
+ if (p->code == code)
+ {
+ return p;
+ }
+ p++;
+ }
+ }
+
+ // 未找到匹配的code,返回无效的设备变量
+ return &hart_device_variable_invalid;
+}
+
+// 获取设备标准变量
+hart_device_standard_variable_t *get_device_standard_variable(uint8_t code)
+{
+ hart_device_standard_variable_t *p = hart_device_attribute.device_standard_variable;
+ for (uint8_t i = 0; i < HART_DEVICE_STANDARD_VARIABLE_LEN; i++)
+ {
+ if (p->code == code)
+ {
+ return p;
+ }
+ p++;
+ }
+ return NULL;
+}
+
+// 获取设备标准变量
+hart_device_variable_t *get_device_variable_by_standard_code(uint8_t code)
+{
+ hart_device_standard_variable_t *standard_variable = NULL;
+ standard_variable = get_device_standard_variable(code);
+ if (standard_variable == NULL)
+ {
+ return &hart_device_variable_invalid;
+ }
+ else
+ {
+ return get_device_variable(standard_variable->dynamic_variable_code);
+ }
+}
+
+// 设置设备变量
+void set_device_variable(hart_device_variable_t *cmd, uint8_t *data)
+{
+ hart_device_variable_t *variable = cmd;
+ uint8_t *hart_device_variable_data = (uint8_t *)variable->value;
+ uint8_t *payload = data;
+ uint8_t len = 0;
+ uint16_t tmp_word = 0;
+ uint32_t tmp_uint32 = 0;
+ float32 tmp_float = 0;
+
+ while (len < variable->user_param.len)
+ {
+ switch (variable->user_param.type)
+ {
+ case USER_BYTE:
+ osel_memcpy(hart_device_variable_data, payload, sizeof(uint8_t));
+ hart_device_variable_data += sizeof(uint8_t);
+ payload += sizeof(uint8_t);
+ len += sizeof(uint8_t);
+ break;
+ case USER_WORD:
+ osel_memcpy((uint8_t *)&tmp_word, payload, sizeof(uint16_t));
+ tmp_word = B2S_UINT16(tmp_word);
+ osel_memcpy(hart_device_variable_data, (uint8_t *)&tmp_word, sizeof(uint16_t));
+ hart_device_variable_data += sizeof(uint16_t);
+ payload += sizeof(uint16_t);
+ len += sizeof(uint16_t);
+ break;
+ case USER_UINT32:
+ osel_memcpy((uint8_t *)&tmp_uint32, payload, sizeof(uint32_t));
+ tmp_uint32 = B2S_UINT32(tmp_uint32);
+ osel_memcpy(hart_device_variable_data, (uint8_t *)&tmp_uint32, sizeof(uint32_t));
+ hart_device_variable_data += sizeof(uint32_t);
+ payload += sizeof(uint32_t);
+ len += sizeof(uint32_t);
+ break;
+ case USER_FLOAT:
+ osel_memcpy((uint8_t *)&tmp_float, payload, sizeof(float32));
+ tmp_float = B2S_FLOAT32(tmp_float);
+ osel_memcpy(hart_device_variable_data, (uint8_t *)&tmp_float, sizeof(float32));
+ hart_device_variable_data += sizeof(float32);
+ payload += sizeof(float32);
+ len += sizeof(float32);
+ break;
+ default:
+ return;
+ }
+ }
+}
+
+// 设置设备常量
+void set_device_constant(hart_device_constant_t *cmd, uint8_t *data)
+{
+ hart_device_constant_t *constant = cmd;
+ uint8_t *hart_device_constant_data = (uint8_t *)constant->value;
+ uint8_t *payload = data;
+ uint8_t len = 0;
+ uint16_t tmp_word = 0;
+ uint32_t tmp_uint32 = 0;
+ float32 tmp_float = 0;
+
+ while (len < constant->user_param.len)
+ {
+ switch (constant->user_param.type)
+ {
+ case USER_BYTE:
+ osel_memcpy(hart_device_constant_data, payload, sizeof(uint8_t));
+ hart_device_constant_data += sizeof(uint8_t);
+ payload += sizeof(uint8_t);
+ len += sizeof(uint8_t);
+ break;
+ case USER_WORD:
+ osel_memcpy((uint8_t *)&tmp_word, payload, sizeof(uint16_t));
+ tmp_word = B2S_UINT16(tmp_word);
+ osel_memcpy(hart_device_constant_data, (uint8_t *)&tmp_word, sizeof(uint16_t));
+ hart_device_constant_data += sizeof(uint16_t);
+ payload += sizeof(uint16_t);
+ len += sizeof(uint16_t);
+ break;
+ case USER_UINT32:
+ osel_memcpy((uint8_t *)&tmp_uint32, payload, sizeof(uint32_t));
+ tmp_uint32 = B2S_UINT32(tmp_uint32);
+ osel_memcpy(hart_device_constant_data, (uint8_t *)&tmp_uint32, sizeof(uint32_t));
+ hart_device_constant_data += sizeof(uint32_t);
+ payload += sizeof(uint32_t);
+ len += sizeof(uint32_t);
+ break;
+ case USER_FLOAT:
+ osel_memcpy((uint8_t *)&tmp_float, payload, sizeof(float32));
+ tmp_float = B2S_FLOAT32(tmp_float);
+ osel_memcpy(hart_device_constant_data, (uint8_t *)&tmp_float, sizeof(float32));
+ hart_device_constant_data += sizeof(float32);
+ payload += sizeof(float32);
+ len += sizeof(float32);
+ break;
+ default:
+ return;
+ }
+ }
+}
+
+// 设置微调点
+BOOL set_trim_point(hart_device_variable_t *variable, response_communication_code_e *code)
+{
+ if (variable->trim_point.trim_points == TRIM_POINTS_0)
+ {
+ return FALSE;
+ }
+ float32 tmp_float = 0;
+ float32 old_value = 0;
+ uint8_t *hart_device_variable_data = (uint8_t *)variable->value;
+
+ // Establish sensor input close to zero measurement, The value must be close enoughto the zero measurement to allow the device to re-zero its calibration but greater than 1 percent of its normal measurement span from its present calibration.
+ float32 limit = (variable->transducer.upper_limit.f - variable->transducer.lower_limit.f) * 0.01f;
+
+ // 目前可以设置微调点的变量都是浮点数值
+ if (variable->user_param.type != USER_FLOAT)
+ {
+ return FALSE;
+ }
+ else
+ {
+ osel_memcpy((uint8_t *)&tmp_float, hart_device_variable_data, sizeof(float32));
+
+ // 传感器 下限值高于传感器上限或超出其他物理设备限制
+ if (tmp_float > variable->transducer.upper_limit.f)
+ {
+ *code = RESPONSE_COMMUNICATION_CODE_9;
+ return FALSE;
+ }
+
+ // 传感器 下限值低于传感器下限或超出某些其他物理设备限制
+ if (tmp_float < variable->transducer.lower_limit.f)
+ {
+ *code = RESPONSE_COMMUNICATION_CODE_10;
+ return FALSE;
+ }
+
+ // 传感器 设置输入接近零测量值,该值必须足够接近零测试量值,但必须大于其当前校准的正常测量范围的1%
+ if ((tmp_float - variable->transducer.lower_limit.f) > limit)
+ {
+ old_value = variable->trim_point.value;
+ variable->trim_point.value = tmp_float - variable->transducer.lower_limit.f;
+
+ if (variable->trim_point.value == old_value) // 微调点没有变化
+ {
+ return FALSE;
+ }
+ else
+ {
+ return TRUE;
+ }
+ }
+ else
+ {
+ return FALSE;
+ }
+ }
+}
+
+/**
+ * @brief 获取模拟通道
+ * @param {analog_channel_number_codes_e} code
+ * @return {*}
+ */
+analog_channel_t *get_analog_channel(analog_channel_number_codes_e code)
+{
+ // analog_channel_t *analog_channel = hart_device_attribute.flash_variable.analog_channel;
+ // for (uint8_t i = 0; i < HART_ANALOG_CHANNEL_LEN; i++)
+ // {
+ // if (analog_channel->code == code)
+ // {
+ // return analog_channel;
+ // }
+ // analog_channel++;
+ // }
+ return NULL;
+}
+
+/**
+ * @brief 获取设备的地址
+ * @param {uint8_t} address_type 短帧地址1个字节,长帧地址5个字节,上位机发送时从低位到高位填充,例如短地址:0x01,长地址:0x00 0x00 0x00 0x00 0x01
+ * @param {uint8_t} *address 设备地址
+ * @param {uint8_t} *len 设备地址长度
+ * @return {*}
+ */
+void get_address(uint8_t address_type, uint8_t *address, uint8_t *len)
+{
+ if (address_type == HART_DELIMITER_TYPE_SHORT)
+ {
+ *len = HART_SHORT_ADDRESS_LEN;
+ address[0] = hart_device_attribute.flash_variable.poll_address;
+ }
+ else
+ {
+ *len = HART_LONG_ADDRESS_LEN;
+ osel_memcpy(address, hart_device_attribute.flash_variable.long_address, HART_LONG_ADDRESS_LEN);
+ }
+}
+
+/**
+ * @brief 设置动态变量(主变量、次要变量 、三级变量、四级变量)
+ * @param {uint8_t} set_code 主变量、次要变量 、三级变量、四级变量 码
+ * @param {uint8_t} dynamic_code 动态变量码
+ * @return {BOOL} 是否设置成功
+ * @note
+ */
+BOOL copy_device_dynamic_variable(uint8_t set_code, uint8_t dynamic_code)
+{
+ hart_device_variable_t *variable = NULL;
+ hart_device_standard_variable_t *set_variable = NULL;
+ if (dynamic_code != DIN_250)
+ {
+ variable = get_device_variable(dynamic_code);
+ if (variable->code == DIN_250)
+ {
+ return FALSE;
+ }
+ }
+
+ set_variable = get_device_standard_variable(set_code);
+ if (set_variable->code == DIN_250)
+ {
+ return FALSE;
+ }
+ else
+ {
+ set_variable->dynamic_variable_code = dynamic_code;
+ return TRUE;
+ }
+}
diff --git a/User/hart/slave/src/hart_slave_frame_mock.c b/User/hart/slave/src/hart_slave_frame_mock.c
new file mode 100644
index 0000000..49a490c
--- /dev/null
+++ b/User/hart/slave/src/hart_slave_frame_mock.c
@@ -0,0 +1,256 @@
+#include "../inc/hart_slave_frame.h"
+static BOOL has_mock = FALSE; // 测试使用该变量判断是否重入
+
+// 模拟用户自定义动态变量
+static void mock_user_dynamics(void)
+{
+}
+
+// 模拟用户自定义属性
+static void mock_user_attribute(void)
+{
+}
+
+// 模拟设备属性
+static void mock_device_attribute(void)
+{
+ static uint8_t poll_address = 0x00;
+ static float32 primary_variable_loop_current = 4.0;
+ static float32 primary_variable_range_percentage = 10.0;
+ static float32 battery_day = 10.0; // 电池寿命
+ static float32 default_value = 355.75;
+ static uint32_t default_cnt = 88;
+ static float32 upper_range_value = 20.0f;
+ static float32 lower_range_value = 4.0f;
+ static uint8_t dev_work_mode = 3;
+ static uint8_t transducer_serial_number[3] = {0x01, 0xE2, 0x40};
+ static uint8_t final_assembly_number[3] = {0xA0, 0x00, 0x01};
+ static uint8_t last_code = DIN_246;
+
+ uint64_t address = HART_LONG_ADDRESS;
+ uint8_t *long_address_p = (uint8_t *)&address;
+ uint8_t tag[HART_PACKED8_LEN] = "GSDT";
+ uint8_t long_tag[HART_PACKED32_LEN] = "GSDT-LONG";
+ uint8_t descriptor[HART_PACKED16_LEN] = "GSDT-01";
+ uint8_t message[HART_PACKED32_LEN] = "DEVICE RESTART!";
+ analog_channel_t *analog_channel = NULL;
+
+ // flash变量
+ osel_memset((uint8_t *)&hart_device_attribute.flash_variable, 0, sizeof(hart_storage_variable_t));
+ hart_device_attribute.flash_variable.write_protect_code = WRITE_PROTECT_CODE_NOT_WRITE_PROTECT;
+ hart_device_attribute.flash_variable.s2m_preambles = HART_PREAMBLE_DEFAULT_LEN;
+ osel_memcpy(hart_device_attribute.flash_variable.tag, tag, ARRAY_LEN(tag));
+ osel_memcpy(hart_device_attribute.flash_variable.long_tag, long_tag, ARRAY_LEN(long_tag));
+ osel_memcpy(hart_device_attribute.flash_variable.descriptor, descriptor, ARRAY_LEN(descriptor));
+ hart_device_attribute.flash_variable.date[0] = 2023 - 1900;
+ hart_device_attribute.flash_variable.date[1] = 05;
+ hart_device_attribute.flash_variable.date[2] = 10;
+
+ osel_memcpy(hart_device_attribute.flash_variable.message, message, sizeof(message));
+ osel_memcpy(hart_device_attribute.flash_variable.final_assembly_number, final_assembly_number, HART_PACKED3_LEN);
+ hart_device_attribute.flash_variable.extended_device_type = EXTENDED_DEVICE_TYPE_GSDT_GPS2000;
+ hart_device_attribute.flash_variable.manufacturer_identification_code = MANUFACTURER_IDENTIFICATION_CODE;
+ hart_device_attribute.flash_variable.private_label_distributor_code = MANUFACTURER_IDENTIFICATION_CODE;
+ hart_device_attribute.flash_variable.device_profile = DEVICE_CONFIGURATION_FILE_CODE_68;
+ hart_device_attribute.flash_variable.device_revision = 1;
+ hart_device_attribute.flash_variable.device_software_revision = 1;
+ hart_device_attribute.flash_variable.device_hardware_revision.bits.hardware_revision = 1;
+ hart_device_attribute.flash_variable.device_hardware_revision.bits.physical_signaling_code = PHYSICAL_SIGNALS_2;
+ osel_memcpy(hart_device_attribute.flash_variable.unit_device.tag, "tm001", HART_PACKED6_LEN);
+ osel_memcpy(hart_device_attribute.flash_variable.unit_device.descriptor, "temperature", HART_PACKED12_LEN);
+ hart_device_attribute.flash_variable.unit_device.date[0] = 10;
+ hart_device_attribute.flash_variable.unit_device.date[1] = 05;
+ hart_device_attribute.flash_variable.unit_device.date[2] = 2023 - 1900;
+ hart_device_attribute.flash_variable.country_code = 86;
+
+ // 趋势配置
+ // trend_configuration_t *trend_configuration = &hart_device_attribute.flash_variable.trend_configurations[0];
+ // trend_configuration->device_variable_code = 0;
+ // trend_configuration->device_variable_classification = DEVICE_VARIABLE_CLASSIFICATION_CODE_64;
+ // trend_configuration->device_variable_unit_code = UNITS_CODE_TEMPERATURE_CELSIUS;
+ // trend_configuration->trend_code = TREND_CONTROL_CODE_1;
+ // trend_configuration->trend_sample_interval = 3600 * 1000;
+ // trend_configuration->trend_value_date[0] = 10;
+ // trend_configuration->trend_value_date[1] = 05;
+ // trend_configuration->trend_value_date[2] = 2023 - 1900;
+ // trend_configuration->trend_value_time = (12 * 3600 + 1 * 60 + 0) * 1000;
+
+ // 设备状态
+ osel_memset((uint8_t *)&hart_device_attribute.device_status, 0, sizeof(hart_device_status_t));
+ hart_device_attribute.device_status.operational_state = DEVICE_OPERATIONAL_STATE_0;
+ hart_device_attribute.device_status.additional_device_status.extended_device_status = EXTENDED_DEVICE_STATUS_1;
+ hart_device_attribute.device_status.additional_device_status.device_operating_mode = OPERATING_MODE_CODES_0;
+ hart_device_attribute.device_status.additional_device_status.standardized_status0 = STANDARDIZED_STATUS0_2;
+ hart_device_attribute.device_status.additional_device_status.standardized_status1 = STANDARDIZED_STATUS1_3;
+ // hart_device_attribute.device_status.additional_device_status.analog_channel_saturated = ANALOG_CHANNEL_SATURATED_1;
+ // hart_device_attribute.device_status.additional_device_status.standardized_status2 = STANDARDIZED_STATUS2_0;
+ // hart_device_attribute.device_status.additional_device_status.standardized_status3 = STANDARDIZED_STATUS3_5;
+ // hart_device_attribute.device_status.additional_device_status.analog_channel_fixed = ANALOG_CHANNEL_FIXED_1;
+ hart_additional_device_status_crc_init();
+
+ // 设备变量
+ hart_device_variable_t *hart_device_variable_p = hart_device_attribute.device_variable;
+
+ // 设备温度
+ hart_device_variable_p->code = DIN_INTERNAL_TEMPERATURE;
+ hart_device_variable_p->value = &default_value;
+ hart_device_variable_p->user_param.len = sizeof(float32);
+ hart_device_variable_p->user_param.type = USER_FLOAT;
+ hart_device_variable_p->user_param.access = USER_READ_ONLY;
+ hart_device_variable_p++;
+ // 回路电流
+ hart_device_variable_p->code = DIN_ANALOG_INPUT;
+ hart_device_variable_p->value = &default_value;
+ hart_device_variable_p->user_param.len = sizeof(float32);
+ hart_device_variable_p->user_param.type = USER_FLOAT;
+ hart_device_variable_p->user_param.access = USER_READ_ONLY;
+ hart_device_variable_p++;
+ // 目标行程
+ hart_device_variable_p->code = DIN_IMPLIED_VALVE_POSITION;
+ hart_device_variable_p->value = &default_value;
+ hart_device_variable_p->user_param.len = sizeof(float32);
+ hart_device_variable_p->user_param.type = USER_FLOAT;
+ hart_device_variable_p->user_param.access = USER_READ_WRITE;
+ hart_device_variable_p++;
+ // 实际行程
+ hart_device_variable_p->code = DIN_PRIMARY_FEEDBACK;
+ hart_device_variable_p->value = &default_value;
+ hart_device_variable_p->user_param.len = sizeof(float32);
+ hart_device_variable_p->user_param.type = USER_FLOAT;
+ hart_device_variable_p->user_param.access = USER_READ_ONLY;
+ hart_device_variable_p++;
+ // 气源压力
+ hart_device_variable_p->code = DIN_SUPPLY_PRESSURE;
+ hart_device_variable_p->value = &default_value;
+ hart_device_variable_p->user_param.len = sizeof(float32);
+ hart_device_variable_p->user_param.type = USER_FLOAT;
+ hart_device_variable_p->user_param.access = USER_READ_ONLY;
+ hart_device_variable_p++;
+ // A路压力
+ hart_device_variable_p->code = DIN_PRESSURE_PORT_A;
+ hart_device_variable_p->value = &default_value;
+ hart_device_variable_p->user_param.len = sizeof(float32);
+ hart_device_variable_p->user_param.type = USER_FLOAT;
+ hart_device_variable_p->user_param.access = USER_READ_ONLY;
+ hart_device_variable_p++;
+ // B路压力
+ hart_device_variable_p->code = DIN_PRESSURE_PORT_B;
+ hart_device_variable_p->value = &default_value;
+ hart_device_variable_p->user_param.len = sizeof(float32);
+ hart_device_variable_p->user_param.type = USER_FLOAT;
+ hart_device_variable_p->user_param.access = USER_READ_ONLY;
+ hart_device_variable_p++;
+ /************************************************************************************/
+
+ hart_device_variable_p->code = DIN_242; // 电池电压
+ hart_device_variable_p->classification = DEVICE_VARIABLE_CLASSIFICATION_CODE_0;
+ hart_device_variable_p->family = DEVICE_VARIABLE_FAMILY_CODE_250;
+ hart_device_variable_p->units_code = UNITS_CODE_ELECTROMOTANCE_VOLTS;
+ hart_device_variable_p->acquisition_period = 1000;
+ hart_device_variable_p->value = &default_value;
+ hart_device_variable_p++;
+ hart_device_variable_p->code = DIN_243; // 电池寿命
+ hart_device_variable_p->classification = DEVICE_VARIABLE_CLASSIFICATION_CODE_0;
+ hart_device_variable_p->family = DEVICE_VARIABLE_FAMILY_CODE_250;
+ hart_device_variable_p->units_code = UNITS_CODE_TIME_D;
+ hart_device_variable_p->acquisition_period = 1000;
+ hart_device_variable_p->value = &battery_day;
+ hart_device_variable_p++;
+ hart_device_variable_p->code = DIN_244; // 百分百
+ hart_device_variable_p->classification = DEVICE_VARIABLE_CLASSIFICATION_CODE_0;
+ hart_device_variable_p->family = DEVICE_VARIABLE_FAMILY_CODE_250;
+ hart_device_variable_p->units_code = UNITS_CODE_OTHER_PERCENT;
+ hart_device_variable_p->value = &primary_variable_range_percentage;
+ hart_device_variable_p++;
+
+ hart_device_variable_p->code = DIN_245; // 回路电流
+ hart_device_variable_p->classification = DEVICE_VARIABLE_CLASSIFICATION_CODE_0;
+ hart_device_variable_p->family = DEVICE_VARIABLE_FAMILY_CODE_250;
+ hart_device_variable_p->units_code = UNITS_CODE_CURRENT_MA;
+ hart_device_variable_p->acquisition_period = 1000;
+ hart_device_variable_p->value = &primary_variable_loop_current;
+ hart_device_variable_p++;
+
+ // 主变量-回路电流
+ hart_device_variable_p->code = DIN_246;
+ hart_device_variable_p->write_device_variable_command_code = WRITE_DEVICE_VARIABLE_COMMAND_CODE_0;
+ hart_device_variable_p->dynamic_variable_code = DIN_250;
+ hart_device_variable_p->classification = DEVICE_VARIABLE_CLASSIFICATION_CODE_64;
+ hart_device_variable_p->family = DEVICE_VARIABLE_FAMILY_CODE_4;
+ hart_device_variable_p->units_code = UNITS_CODE_UNDEFINE;
+ hart_device_variable_p->properties = DEVICE_VARIABLE_PROPERTY_FLAGS_8;
+ hart_device_variable_p->acquisition_period = 1000;
+ hart_device_variable_p->value = &default_value;
+ hart_device_variable_p->status.data = 0;
+ hart_device_variable_p->attribute.alarm_selection_code = ALARM_CODE_NOT_USED;
+ hart_device_variable_p->attribute.transfer_function_code = TRANSMISSION_FUNCTION_CODE_NOT_USED;
+ hart_device_variable_p->transducer.upper_and_lower_range_values_units_code = UNITS_CODE_CURRENT_MA;
+ hart_device_variable_p->transducer.upper_limit.f = upper_range_value;
+ hart_device_variable_p->transducer.lower_limit.f = lower_range_value;
+ hart_device_variable_p->attribute.damping_value = 0.0;
+ hart_device_variable_p->attribute.write_protect_code = WRITE_PROTECT_CODE_WRITE_PROTECT;
+ hart_device_variable_p->attribute.analog_channel_flags = ANALOG_CHANNEL_CODE_1;
+ hart_device_variable_p++;
+ // 次要变量-目标行程
+ hart_device_variable_p->code = DIN_247;
+ hart_device_variable_p->dynamic_variable_code = DIN_250;
+ hart_device_variable_p->classification = DEVICE_VARIABLE_CLASSIFICATION_CODE_65;
+ hart_device_variable_p->family = DEVICE_VARIABLE_FAMILY_CODE_5;
+ hart_device_variable_p->acquisition_period = 1000;
+ hart_device_variable_p->units_code = UNITS_CODE_PRESSURE_KPA;
+ hart_device_variable_p->value = &default_value;
+ // analog_channel = &hart_device_attribute.flash_variable.analog_channel[ANALOG_CHANNEL_NUMBER_CODES_1];
+ // analog_channel->code = ANALOG_CHANNEL_NUMBER_CODES_1;
+ // analog_channel->units_code = UNITS_CODE_PRESSURE_KPA;
+ // analog_channel->level.f = 0;
+ // analog_channel->percent_range.f = 0;
+
+ hart_device_variable_p++;
+ hart_device_variable_p->code = DIN_248; // 三级变量
+ hart_device_variable_p->dynamic_variable_code = DIN_250;
+ hart_device_variable_p->classification = DEVICE_VARIABLE_CLASSIFICATION_CODE_66;
+ hart_device_variable_p->family = DEVICE_VARIABLE_FAMILY_CODE_6;
+ hart_device_variable_p->acquisition_period = 1000;
+ hart_device_variable_p->units_code = UNITS_CODE_VOLUMETRIC_FLOW_RATE_M3S;
+ hart_device_variable_p->value = &default_value;
+ // analog_channel = &hart_device_attribute.flash_variable.analog_channel[ANALOG_CHANNEL_NUMBER_CODES_2];
+ // analog_channel->code = ANALOG_CHANNEL_NUMBER_CODES_2;
+ // analog_channel->units_code = UNITS_CODE_VOLUMETRIC_FLOW_RATE_M3S;
+ // analog_channel->level.f = 0;
+ // analog_channel->percent_range.f = 0;
+
+ hart_device_variable_p++;
+ hart_device_variable_p->code = DIN_249; // 四级变量
+ hart_device_variable_p->dynamic_variable_code = DIN_250;
+ hart_device_variable_p->classification = DEVICE_VARIABLE_CLASSIFICATION_CODE_67;
+ hart_device_variable_p->family = DEVICE_VARIABLE_FAMILY_CODE_12;
+ hart_device_variable_p->acquisition_period = 1000;
+ hart_device_variable_p->units_code = UNITS_CODE_SPEED_MS;
+ hart_device_variable_p->value = &default_value;
+ // analog_channel = &hart_device_attribute.flash_variable.analog_channel[ANALOG_CHANNEL_NUMBER_CODES_3];
+ // analog_channel->code = ANALOG_CHANNEL_NUMBER_CODES_3;
+ // analog_channel->units_code = UNITS_CODE_SPEED_MS;
+ // analog_channel->level.f = 0;
+ // analog_channel->percent_range.f = 0;
+
+ hart_device_variable_p++;
+
+ hart_device_attribute.last_device_variable = &last_code;
+
+ hart_device_attribute.flash_variable.poll_address = poll_address;
+ osel_memcpy(hart_device_attribute.flash_variable.long_address, long_address_p, HART_LONG_ADDRESS_LEN);
+ REVERSE_ARRAY(hart_device_attribute.flash_variable.long_address, HART_LONG_ADDRESS_LEN);
+ hart_device_attribute.actual_pv_current_level = &default_value;
+}
+
+void mock_data(void)
+{
+ if (TRUE == has_mock)
+ {
+ return;
+ }
+ has_mock = TRUE;
+ mock_device_attribute();
+ mock_user_attribute();
+ mock_user_dynamics();
+}
diff --git a/User/hart/slave/src/hart_slave_req.c b/User/hart/slave/src/hart_slave_req.c
new file mode 100644
index 0000000..bc6fc1e
--- /dev/null
+++ b/User/hart/slave/src/hart_slave_req.c
@@ -0,0 +1,4269 @@
+#include "../inc/hart_slave_req.h"
+#include "../inc/hart_slave_frame.h"
+
+/**
+ * @brief 未定义命令
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_undef_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ resp->code = RESPONSE_COMMUNICATION_CODE_6;
+ return TRUE;
+}
+
+/**
+ * @brief 读取唯一标识命令V5
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static void command_0_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ *resp->data_p++ = 254; // 默认254
+ *resp->data_p++ = HI_UINT16(hart_device_attribute.flash_variable.extended_device_type); // 扩展设备类型
+ *resp->data_p++ = LO_UINT16(hart_device_attribute.flash_variable.extended_device_type);
+ *resp->data_p++ = HART_PREAMBLE_DEFAULT_LEN; // 主设备到从设备的最少同步前导码数量
+ *resp->data_p++ = hart_get_current_protocol_version(); // 本设备实施的HART协议主要版本号。对于HART版本7。该值必须是数字7
+ *resp->data_p++ = hart_device_attribute.flash_variable.device_revision; // 设备版本
+ *resp->data_p++ = hart_device_attribute.flash_variable.device_software_revision; // 设备软件版本,254,255保留
+ *resp->data_p++ = hart_device_attribute.flash_variable.device_hardware_revision.version; // (高5bits)硬件版本号,31保留;(低3bits)5.10 物理信号
+ resp->data_p++; // 保留
+ osel_memcpy(resp->data_p, hart_device_attribute.flash_variable.long_address + 2, 3); // 设备ID,长ID的后3个字节
+ resp->data_p += 3;
+ uint16_t cfg_cnt = req->master == HART_MASTER ? hart_device_attribute.flash_variable.master_cfg_update_count : hart_device_attribute.flash_variable.slave_cfg_update_count; // 配置更新计数
+ if (hart_get_current_protocol_version() == HART_PROTOCOL_VERSION_7)
+ {
+ *resp->data_p++ = hart_device_attribute.flash_variable.s2m_preambles; // 从设备到主设备的响应前导码个数
+ *resp->data_p++ = 10; //*hart_device_attribute.last_device_variable; //ZKBW // 上一个设备变量,这表示应用程序应在现场设备中找到的最后一个设备变量代码(在执行Command 54时读取设备的变量)
+ *resp->data_p++ = HI_UINT16(cfg_cnt); // 配置被更新的次数
+ *resp->data_p++ = LO_UINT16(cfg_cnt);
+ *resp->data_p++ = hart_device_attribute.device_status.additional_device_status.extended_device_status; // 扩展现场设备状态未指定的任何位都是未定义的,必须设置为零。
+ *resp->data_p++ = HI_UINT16(hart_device_attribute.flash_variable.manufacturer_identification_code); // 制造商标识码
+ *resp->data_p++ = LO_UINT16(hart_device_attribute.flash_variable.manufacturer_identification_code);
+ *resp->data_p++ = HI_UINT16(hart_device_attribute.flash_variable.private_label_distributor_code); // 私有标签分销商代码
+ *resp->data_p++ = LO_UINT16(hart_device_attribute.flash_variable.private_label_distributor_code);
+ *resp->data_p++ = hart_device_attribute.flash_variable.device_profile; // 设备配置文件
+ }
+}
+
+/**
+ * @brief 读取唯一标识命令V5 2023-05-06
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_0_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ command_0_req(req, resp);
+ return TRUE;
+}
+
+/**
+ * @brief 读取主变量
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_1_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ float32_u tmp;
+ hart_device_variable_t *variable = NULL;
+ variable = get_device_variable_by_standard_code(DIN_246);
+ if (variable->code == DIN_250)
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_6;
+ return TRUE;
+ }
+ osel_memcpy((uint8_t *)&tmp.f, (uint8_t *)variable->value, sizeof(float32));
+ tmp.f -= variable->trim_point.value;
+ tmp.c = S2B_UINT32(tmp.c);
+ *resp->data_p++ = variable->units_code; // 主变量单位代码
+ osel_memcpy(resp->data_p, (uint8_t *)&tmp, sizeof(float32_u)); // 主要变量
+ resp->data_p += sizeof(float32_u);
+ return TRUE;
+}
+
+/**
+ * @brief 读取主变量的回路电流和量程百分比
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_2_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ float32_u tmp;
+ hart_device_variable_t *variable = NULL;
+ variable = get_device_variable_by_standard_code(DIN_245); // 回路电流
+ if (variable->code == DIN_250)
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_6;
+ return TRUE;
+ }
+ osel_memcpy((uint8_t *)&tmp.f, (uint8_t *)variable->value, sizeof(float32));
+ tmp.f -= variable->trim_point.value;
+ tmp.c = S2B_UINT32(tmp.c);
+ osel_memcpy(resp->data_p, (uint8_t *)&tmp, sizeof(float32_u));
+ resp->data_p += sizeof(float32_u);
+
+ variable = get_device_variable_by_standard_code(DIN_244); // 百分百
+ if (variable->code == DIN_250)
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_6;
+ return TRUE;
+ }
+ osel_memcpy((uint8_t *)&tmp.f, (uint8_t *)variable->value, sizeof(float32));
+ tmp.f -= variable->trim_point.value;
+ tmp.c = S2B_UINT32(tmp.c);
+ osel_memcpy(resp->data_p, (uint8_t *)&tmp, sizeof(float32_u));
+ resp->data_p += sizeof(float32_u);
+
+ return TRUE;
+}
+
+/**
+ * @brief 读取动态变量和回路电流
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_3_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ float32_u tmp;
+ hart_device_variable_t *variable = NULL;
+ variable = get_device_variable_by_standard_code(DIN_245); // 回路电流
+ if (variable->code == DIN_250)
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_12;
+ return TRUE;
+ }
+ osel_memcpy((uint8_t *)&tmp.f, (uint8_t *)variable->value, sizeof(float32));
+ tmp.f -= variable->trim_point.value;
+ tmp.c = S2B_UINT32(tmp.c);
+ osel_memcpy(resp->data_p, (uint8_t *)&tmp, sizeof(float32_u));
+ resp->data_p += sizeof(float32_u);
+
+ /**
+ * 响应数据在每个设备类型支持的最后一个动态变量之后被截断(请参见表1)对于给定的设备类型和设备版本,响应数据字节数必须是固定的。换句话说,一个设备类型可能在一种操作模式下不返回PV、SV和TV,后来(在不同的操作中)只返回PV和SV。返回的动态变量数可能随着设备版本的增加而增加。返回的动态变量的数量永远不会减少
+ */
+ variable = get_device_variable_by_standard_code(DIN_246); // 主变量
+ if (variable->code == DIN_250)
+ {
+ return TRUE;
+ }
+ osel_memcpy((uint8_t *)&tmp.f, (uint8_t *)variable->value, sizeof(float32));
+ tmp.f -= variable->trim_point.value;
+ tmp.c = S2B_UINT32(tmp.c);
+ *resp->data_p++ = variable->units_code;
+ osel_memcpy(resp->data_p, (uint8_t *)&tmp, sizeof(float32_u));
+ resp->data_p += sizeof(float32_u);
+
+ variable = get_device_variable_by_standard_code(DIN_247); // 次要变量
+ if (variable->code == DIN_250)
+ {
+ return TRUE;
+ }
+ osel_memcpy((uint8_t *)&tmp.f, (uint8_t *)variable->value, sizeof(float32));
+ tmp.f -= variable->trim_point.value;
+ tmp.c = S2B_UINT32(tmp.c);
+ *resp->data_p++ = variable->units_code;
+ osel_memcpy(resp->data_p, (uint8_t *)&tmp, sizeof(float32_u));
+ resp->data_p += sizeof(float32_u);
+
+ variable = get_device_variable_by_standard_code(DIN_248); // 三级变量
+ if (variable->code == DIN_250)
+ {
+ return TRUE;
+ }
+ osel_memcpy((uint8_t *)&tmp.f, (uint8_t *)variable->value, sizeof(float32));
+ tmp.f -= variable->trim_point.value;
+ tmp.c = S2B_UINT32(tmp.c);
+ *resp->data_p++ = variable->units_code;
+ osel_memcpy(resp->data_p, (uint8_t *)&tmp, sizeof(float32_u));
+ resp->data_p += sizeof(float32_u);
+
+ variable = get_device_variable_by_standard_code(DIN_249); // 四级变量
+ if (variable->code == DIN_250)
+ {
+ return TRUE;
+ }
+ osel_memcpy((uint8_t *)&tmp.f, (uint8_t *)variable->value, sizeof(float32));
+ tmp.f -= variable->trim_point.value;
+ tmp.c = S2B_UINT32(tmp.c);
+ *resp->data_p++ = variable->units_code;
+ osel_memcpy(resp->data_p, (uint8_t *)&tmp, sizeof(float32_u));
+ resp->data_p += sizeof(float32_u);
+ return TRUE;
+}
+
+/**
+ * @brief 写入轮训地址V5 2023-05-08
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_6_req(const hart_command_req_t *const req, hart_response_t *resp) // ZKBW
+{
+ BOOL change = FALSE;
+ if (req->data_length < 1)
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_5;
+ return TRUE;
+ }
+ if (req->data.command_6.poll_address > 63)
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_2;
+ return TRUE;
+ }
+ if (req->data_length == 2 && req->data.command_6.loop_current_mode > 1)
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_2;
+ return TRUE;
+ }
+ else
+ {
+ if (req->data_length == 1)
+ {
+ if (req->data.command_6.poll_address != hart_device_attribute.flash_variable.poll_address)
+ {
+ hart_device_attribute.flash_variable.poll_address = req->data.command_6.poll_address;
+ hart_storage_write_item(HART_STORAGE_PARAMS, HPB_POLL_ADDRESS,
+ &hart_device_attribute.flash_variable.poll_address);
+ change = TRUE;
+ }
+ if (hart_device_attribute.flash_variable.poll_address == 0)
+ {
+ hart_device_attribute.flash_variable.loop_current_mode = 0x01;
+ }
+ else
+ {
+ hart_device_attribute.flash_variable.loop_current_mode = 0x00;
+ }
+ }
+ else
+ {
+ if (req->data.command_6.loop_current_mode != hart_device_attribute.flash_variable.loop_current_mode)
+ {
+ hart_device_attribute.flash_variable.loop_current_mode = req->data.command_6.loop_current_mode;
+
+ hart_storage_write_item(HART_STORAGE_PARAMS, HPB_LOOP_CURRENT_MODE,
+ &hart_device_attribute.flash_variable.loop_current_mode);
+ change = TRUE;
+ }
+ }
+
+ if (change)
+ {
+ hart_device_status_set_operational_state(DEVICE_OPERATIONAL_STATE_7);
+ }
+
+ // 回复数据
+ {
+ *resp->data_p++ = hart_device_attribute.flash_variable.poll_address;
+ *resp->data_p++ = hart_device_attribute.flash_variable.loop_current_mode;
+
+ if (hart_device_attribute.flash_variable.loop_current_mode == 0)
+ {
+ hart_device_status_set_operational_state(DEVICE_OPERATIONAL_STATE_4);
+ }
+ else
+ {
+ hart_device_status_clr_operational_state(DEVICE_OPERATIONAL_STATE_4);
+ }
+ }
+ }
+ return TRUE;
+}
+
+/**
+ * @brief 读取循环配置 2023-05-08
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_7_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ *resp->data_p++ = hart_device_attribute.flash_variable.poll_address; // 轮询地址
+ *resp->data_p++ = hart_device_attribute.flash_variable.loop_current_mode; // 回路电流模式
+ return TRUE;
+}
+
+/**
+ * @brief 读取动态变量分类 2023-05-08
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_8_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ hart_device_variable_t *variable = NULL;
+ variable = get_device_variable_by_standard_code(DIN_246); // 主变量
+ *resp->data_p++ = variable->classification;
+ variable = get_device_variable_by_standard_code(DIN_247); // 主变量
+ *resp->data_p++ = variable->classification;
+ variable = get_device_variable_by_standard_code(DIN_248); // 主变量
+ *resp->data_p++ = variable->classification;
+ variable = get_device_variable_by_standard_code(DIN_249); // 主变量
+ *resp->data_p++ = variable->classification;
+ return TRUE;
+}
+
+/**
+ * @brief 读取具有状态的设备变量 2023-05-08
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_9_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ hart_device_variable_t *variable = NULL;
+ slot_device_variable_rsp_t slot;
+ hart_command_9_rsp_t rsp;
+ float32_u tmp;
+ uint8_t *code = NULL;
+ uint8_t uclength_temp = 0;
+ variable_e type = VARIABLE;
+ uclength_temp = req->data_length;
+ if (uclength_temp == 0)
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_5;
+ return TRUE;
+ }
+
+ if (uclength_temp > 8)
+ {
+ uclength_temp = 8;
+ }
+ if (uclength_temp == 4 && (req->data.command_9.hart_command_9_req.slot0 == 0xff) &&
+ (req->data.command_9.hart_command_9_req.slot1 == 0xff) && (req->data.command_9.hart_command_9_req.slot2 == 0xff) && (req->data.command_9.hart_command_9_req.slot3 == 0xff))
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_2;
+ return TRUE;
+ }
+
+ osel_memset((uint8_t *)&rsp, 0, sizeof(hart_command_9_rsp_t));
+ rsp.extended_field_device_status = hart_device_attribute.device_status.additional_device_status.extended_device_status; // 扩展现场设备状态
+ for (uint8_t i = 0; i < uclength_temp; i++)
+ {
+ code = (uint8_t *)(&req->data.command_9.hart_command_9_req.slot0) + i;
+ type = get_variable_type(*code);
+ osel_memset((uint8_t *)&slot, 0, sizeof(slot_device_variable_rsp_t));
+ if (type == VARIABLE)
+ {
+ variable = get_device_variable(*code);
+ }
+ else if (type == CONSTANT)
+ {
+ variable = &hart_device_variable_invalid;
+ }
+ else
+ {
+ variable = get_device_variable_by_standard_code(*code);
+ }
+ variable->code = *code; // ZKBW
+ slot.code = variable->code;
+ slot.classification = variable->classification;
+ slot.units_code = variable->units_code;
+ tmp.f = covert_float(variable->user_param.type, (void *)variable->value);
+ tmp.f -= variable->trim_point.value;
+ tmp.c = S2B_UINT32(tmp.c);
+ slot.value.f = tmp.f;
+ slot.status = variable->status.data;
+ osel_memcpy((uint8_t *)&rsp.slot[i], (uint8_t *)&slot, sizeof(slot_device_variable_rsp_t));
+ }
+ rsp.slot_data_timestamp = hart_get_timestamp();
+ rsp.slot_data_timestamp = S2B_UINT32(rsp.slot_data_timestamp);
+
+ *resp->data_p++ = rsp.extended_field_device_status;
+ osel_memcpy(resp->data_p, (uint8_t *)&rsp.slot, sizeof(slot_device_variable_rsp_t) * uclength_temp);
+ resp->data_p += sizeof(slot_device_variable_rsp_t) * uclength_temp;
+ osel_memcpy(resp->data_p, (uint8_t *)&rsp.slot_data_timestamp, sizeof(uint32_t));
+ resp->data_p += sizeof(uint32_t);
+ return TRUE;
+}
+
+/**
+ * @brief 读取与标签关联的唯一标识符 2023-05-08
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_11_req(const hart_command_req_t *const req, hart_response_t *resp) // ZKBW
+{
+ BOOL same = TRUE;
+ uint8_t buf[HART_PACKED8_LEN];
+ if (req->data_length == 0)
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_5;
+ return TRUE;
+ }
+
+ encode_ascii_6(hart_device_attribute.flash_variable.tag, HART_PACKED8_LEN, buf);
+ for (uint8_t i = 0; i < HART_PACKED6_LEN; i++)
+ {
+ if (req->data.command_11.tag[i] != buf[i])
+ {
+ same = FALSE;
+ break;
+ }
+ }
+
+ if (same)
+ {
+ command_0_req(req, resp); ///< 与命令0相同
+ return TRUE;
+ }
+ else
+ {
+ // resp->code = RESPONSE_COMMUNICATION_CODE_38;
+ return FALSE;
+ }
+}
+
+/**
+ * @brief 读取消息 2023-05-08
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_12_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ uint8_t buf[HART_PACKED32_LEN];
+ osel_memset(buf, 0x00, HART_PACKED32_LEN);
+ encode_ascii_6(hart_device_attribute.flash_variable.message, HART_PACKED32_LEN, buf);
+ for (uint8_t i = 0; i < HART_PACKED24_LEN; i++)
+ {
+ *resp->data_p++ = buf[i];
+ }
+ return TRUE;
+}
+
+/**
+ * @brief 读取标签、描述符、日期 2023-05-08
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_13_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ uint8_t buf[HART_PACKED24_LEN];
+ osel_memset(buf, 0x00, HART_PACKED24_LEN);
+ encode_ascii_6(hart_device_attribute.flash_variable.tag, HART_PACKED8_LEN, buf);
+ // LOG_HEX(hart_device_attribute.flash_variable.tag, HART_PACKED8_LEN);
+ // LOG_HEX(buf, HART_PACKED8_LEN);
+ for (uint8_t i = 0; i < HART_PACKED6_LEN; i++)
+ {
+ *resp->data_p++ = buf[i]; // 标签
+ }
+
+ osel_memset(buf, 0x00, HART_PACKED24_LEN);
+ encode_ascii_6(hart_device_attribute.flash_variable.descriptor, HART_PACKED16_LEN, buf);
+ // LOG_HEX(hart_device_attribute.flash_variable.descriptor, HART_PACKED16_LEN);
+ // LOG_HEX(buf, HART_PACKED16_LEN);
+ for (uint8_t i = 0; i < HART_PACKED12_LEN; i++)
+ {
+ *resp->data_p++ = buf[i]; // 描述符
+ }
+
+ for (uint8_t i = 0; i < HART_DATE_LEN; i++)
+ {
+ *resp->data_p++ = hart_device_attribute.flash_variable.date[i];
+ }
+ return TRUE;
+}
+
+/**
+ * @brief 读取主变量传感器信息 2023-05-08
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_14_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ hart_command_14_t data;
+ hart_device_variable_t *variable = NULL;
+ variable = get_device_variable_by_standard_code(DIN_246); // 主变量
+ if (variable->code == DIN_250)
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_16;
+ return TRUE;
+ }
+ osel_memcpy(data.pv_transducer_serial_number.bs, variable->transducer.serial_number.bs, sizeof(uint24_t));
+ data.pv_transducer_limits_and_minimum_span_units_code = variable->transducer.limits_and_minimum_span_units_code;
+ data.pv_upper_transducer_limit = variable->transducer.upper_limit;
+ data.pv_lower_transducer_limit = variable->transducer.lower_limit;
+ data.pv_minimum_span = variable->transducer.minimum_span;
+
+ data.pv_upper_transducer_limit.c = S2B_UINT32(data.pv_upper_transducer_limit.c); // 主变量上限
+ data.pv_lower_transducer_limit.c = S2B_UINT32(data.pv_lower_transducer_limit.c); // 主变量下限
+ data.pv_minimum_span.c = S2B_UINT32(data.pv_minimum_span.c); // 主变量最小跨度
+
+ osel_memcpy(resp->data_p, (uint8_t *)&data, sizeof(hart_command_14_t)); // 主变量传感器信息
+ resp->data_p += sizeof(hart_command_14_t);
+ return TRUE;
+}
+
+/**
+ * @brief 读取设备信息 2023-05-09
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_15_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ hart_device_variable_t *variable = NULL;
+ hart_command_15_t data;
+ variable = get_device_variable_by_standard_code(DIN_246); // 主变量
+ if (variable->code == DIN_250)
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_6;
+ return TRUE;
+ }
+
+ data.pv_alarm_selection_code = variable->attribute.alarm_selection_code;
+ data.pv_transfer_function_code = variable->attribute.transfer_function_code;
+ data.pv_upper_and_lower_range_values_units_code = variable->transducer.upper_and_lower_range_values_units_code;
+ data.pv_damping_value.f = variable->attribute.damping_value;
+ osel_memcpy((uint8_t *)&data.pv_upper_range_value.f, (uint8_t *)&variable->transducer.upper_limit.f, sizeof(float32));
+ osel_memcpy((uint8_t *)&data.pv_lower_range_value.f, (uint8_t *)&variable->transducer.lower_limit.f, sizeof(float32));
+ data.pv_upper_range_value.c = S2B_UINT32(data.pv_upper_range_value.c); // 主变量上限
+ data.pv_lower_range_value.c = S2B_UINT32(data.pv_lower_range_value.c); // 主变量下限
+ data.pv_damping_value.c = S2B_UINT32(data.pv_damping_value.c); // 主变量阻尼
+
+ data.write_protect_code = hart_device_attribute.flash_variable.write_protect_code;
+ data.reserved = 250;
+ data.pv_analog_channel_flags = variable->attribute.analog_channel_flags;
+ osel_memcpy(resp->data_p, (uint8_t *)&data, sizeof(hart_command_15_t)); // 设备信息
+ resp->data_p += sizeof(hart_command_15_t);
+ return TRUE;
+}
+
+/**
+ * @brief 读取最终总装编号 2023-05-09
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_16_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ osel_memcpy(resp->data_p, hart_device_attribute.flash_variable.final_assembly_number, HART_PACKED3_LEN); // 最终总装编号
+ resp->data_p += sizeof(uint24_t);
+ return TRUE;
+}
+
+/**
+ * @brief 写入消息V5
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_17_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ uint8_t buf[HART_PACKED32_LEN];
+ if (req->data_length < HART_PACKED24_LEN)
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_5;
+ return TRUE;
+ }
+ osel_memset(buf, 0x00, HART_PACKED32_LEN);
+ decode_ascii_6(req->data.command_17.message, HART_PACKED24_LEN, buf);
+
+ if (osel_memcmp(hart_device_attribute.flash_variable.message, buf, HART_PACKED32_LEN) != 0)
+ {
+ osel_memset(hart_device_attribute.flash_variable.message, 0x00, HART_PACKED32_LEN);
+ osel_memcpy(hart_device_attribute.flash_variable.message, buf, HART_PACKED32_LEN);
+ hart_storage_write_item(HART_STORAGE_PARAMS, HPB_MESSAGE,
+ hart_device_attribute.flash_variable.message);
+ hart_device_status_set_operational_state(DEVICE_OPERATIONAL_STATE_7);
+ }
+
+ // 回复数据
+ osel_memset(buf, 0x20, HART_PACKED32_LEN);
+ encode_ascii_6(hart_device_attribute.flash_variable.message, HART_PACKED32_LEN, buf);
+ osel_memcpy(resp->data_p, buf, HART_PACKED24_LEN);
+ resp->data_p += HART_PACKED24_LEN;
+
+ return TRUE;
+}
+
+/**
+ * @brief 写标签、描述符、日期V5
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_18_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ BOOL change = FALSE;
+ uint8_t buf[HART_PACKED24_LEN];
+ if (req->data_length < (HART_PACKED6_LEN + HART_PACKED12_LEN + HART_DATE_LEN))
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_5;
+ return TRUE;
+ }
+
+ osel_memset(buf, 0x00, HART_PACKED24_LEN);
+ decode_ascii_6(req->data.command_18.tag, HART_PACKED6_LEN, buf);
+ if (osel_memcmp(hart_device_attribute.flash_variable.tag, buf, HART_PACKED8_LEN) != 0)
+ {
+ osel_memset(hart_device_attribute.flash_variable.tag, 0x00, HART_PACKED8_LEN);
+ osel_memcpy(hart_device_attribute.flash_variable.tag, buf, HART_PACKED8_LEN); // 更新标签
+ hart_storage_write_item(HART_STORAGE_PARAMS, HPB_TAG,
+ hart_device_attribute.flash_variable.tag);
+ change = TRUE;
+ }
+
+ osel_memset(buf, 0x00, HART_PACKED24_LEN);
+ decode_ascii_6(req->data.command_18.descriptor, HART_PACKED12_LEN, buf);
+ if (osel_memcmp(hart_device_attribute.flash_variable.descriptor, buf, HART_PACKED8_LEN) != 0)
+ {
+ osel_memset(hart_device_attribute.flash_variable.descriptor, 0x00, HART_PACKED16_LEN);
+ osel_memcpy(hart_device_attribute.flash_variable.descriptor, buf, HART_PACKED16_LEN); // 更新描述符
+ hart_storage_write_item(HART_STORAGE_PARAMS, HPB_DESCRIPTOR,
+ hart_device_attribute.flash_variable.descriptor);
+ change = TRUE;
+ }
+
+ osel_memset(buf, 0x00, HART_PACKED24_LEN);
+ osel_memcpy(buf, req->data.command_18.date, HART_DATE_LEN);
+ if (osel_memcmp(hart_device_attribute.flash_variable.date, buf, HART_DATE_LEN) != 0)
+ {
+ osel_memset(hart_device_attribute.flash_variable.date, 0x00, HART_DATE_LEN);
+ osel_memcpy(hart_device_attribute.flash_variable.date, req->data.command_18.date, HART_DATE_LEN); // 更新日期
+ hart_storage_write_item(HART_STORAGE_PARAMS, HPB_DATE,
+ hart_device_attribute.flash_variable.date);
+ change = TRUE;
+ }
+
+ if (change)
+ {
+ hart_device_status_set_operational_state(DEVICE_OPERATIONAL_STATE_7);
+ }
+
+ // 回复数据
+ osel_memset(buf, 0x20, HART_PACKED24_LEN);
+ encode_ascii_6(hart_device_attribute.flash_variable.tag, HART_PACKED8_LEN, buf);
+ osel_memcpy(resp->data_p, buf, HART_PACKED6_LEN); // 标签
+ resp->data_p += HART_PACKED6_LEN;
+
+ osel_memset(buf, 0x20, HART_PACKED24_LEN);
+ encode_ascii_6(hart_device_attribute.flash_variable.descriptor, HART_PACKED16_LEN, buf);
+ osel_memcpy(resp->data_p, buf, HART_PACKED12_LEN); // 描述符
+ resp->data_p += HART_PACKED12_LEN;
+
+ osel_memcpy(resp->data_p, hart_device_attribute.flash_variable.date, HART_DATE_LEN); // 日期
+ resp->data_p += HART_DATE_LEN;
+
+ return TRUE;
+}
+
+/**
+ * @brief 编写总装编号V5
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_19_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ if (req->data_length < HART_PACKED3_LEN)
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_5;
+ return TRUE;
+ }
+
+ if (osel_memcmp(hart_device_attribute.flash_variable.final_assembly_number, req->data.command_19.final_assembly_number, HART_PACKED3_LEN) != 0)
+ {
+ osel_memset(hart_device_attribute.flash_variable.final_assembly_number, 0x00, HART_PACKED3_LEN);
+ osel_memcpy(hart_device_attribute.flash_variable.final_assembly_number, req->data.command_19.final_assembly_number, HART_PACKED3_LEN); // 更新总装编号
+
+ hart_storage_write_item(HART_STORAGE_PARAMS, HPB_FINAL_ASSEMBLY_NUMBER,
+ hart_device_attribute.flash_variable.final_assembly_number);
+
+ hart_device_status_set_operational_state(DEVICE_OPERATIONAL_STATE_7);
+ }
+
+ // 回复数据
+ osel_memcpy(resp->data_p, hart_device_attribute.flash_variable.final_assembly_number, HART_PACKED3_LEN);
+ resp->data_p += HART_PACKED3_LEN;
+ return TRUE;
+}
+
+/**
+ * @brief 读取长标签
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_20_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ osel_memcpy(resp->data_p, hart_device_attribute.flash_variable.long_tag, HART_PACKED32_LEN); // 长标签
+ resp->data_p += HART_PACKED32_LEN;
+ return TRUE;
+}
+
+/**
+ * @brief 读取与长标签关联的唯一标识符
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_21_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ BOOL same = TRUE;
+ if (req->data_length == 0)
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_5;
+ return TRUE;
+ }
+
+ for (uint8_t i = 0; i < HART_PACKED32_LEN; i++)
+ {
+ if (req->data.command_21.long_tag[i] != hart_device_attribute.flash_variable.long_tag[i])
+ {
+ same = FALSE;
+ break;
+ }
+ }
+
+ if (same)
+ {
+ command_0_req(req, resp);
+ }
+ else
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_38;
+ }
+ return TRUE;
+}
+
+/**
+ * @brief 写长标签
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_22_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ if (req->data_length < HART_PACKED32_LEN)
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_5;
+ return TRUE;
+ }
+
+ if (osel_memcmp(hart_device_attribute.flash_variable.long_tag, req->data.command_22.long_tag, HART_PACKED32_LEN) != 0)
+ {
+ osel_memset(hart_device_attribute.flash_variable.long_tag, 0x00, HART_PACKED32_LEN);
+ osel_memcpy(hart_device_attribute.flash_variable.long_tag, req->data.command_22.long_tag, HART_PACKED32_LEN); // 更新长标签
+
+ hart_storage_write_item(HART_STORAGE_PARAMS, HPB_LONG_TAG,
+ hart_device_attribute.flash_variable.long_tag);
+ hart_device_status_set_operational_state(DEVICE_OPERATIONAL_STATE_7);
+ }
+
+ // 回复数据
+ osel_memcpy(resp->data_p, hart_device_attribute.flash_variable.long_tag, HART_PACKED32_LEN);
+ resp->data_p += HART_PACKED32_LEN;
+ return TRUE;
+}
+
+/**
+ * @brief 重置配置更改标志
+ * 配置恢复,配置更改在未写入到EEPROM中是先存在RAM中。command6等写入指令会更新计数器,通过计数器的数值不同来判断配置是否更新
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_38_req(const hart_command_req_t *const req, hart_response_t *resp) // ZKBW
+{
+ uint16_t cfg_cnt = req->master == HART_MASTER ? hart_device_attribute.flash_variable.master_cfg_update_count : hart_device_attribute.flash_variable.slave_cfg_update_count; // 配置更新计数
+
+ if (req->data_length == 1) // ZKBW
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_5;
+ return TRUE;
+ }
+ else if (req->data_length == 2)
+ {
+ uint16_t configuration_change_counter = B2S_UINT16(req->data.command_38.configuration_change_counter);
+ if (configuration_change_counter != cfg_cnt)
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_9;
+ return TRUE;
+ }
+ }
+
+ // 将配置从falsh中重新读取到缓存
+ if (FALSE == hart_storage_read(HART_STORAGE_PARAMS, (uint8_t *)&hart_device_attribute.flash_variable))
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_16;
+ }
+ else
+ {
+ *resp->data_p++ = HI_UINT16(cfg_cnt);
+ *resp->data_p++ = LO_UINT16(cfg_cnt);
+ hart_device_status_clr_operational_state(DEVICE_OPERATIONAL_STATE_7);
+ }
+ return TRUE;
+}
+
+/**
+ * @brief 读取其他设备状态
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_48_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ additional_device_status_t command_48;
+ uint8_t *ptr = NULL;
+ osel_memset((uint8_t *)&command_48, 0x00, sizeof(additional_device_status_t));
+ ptr = command_48.device_specific_status;
+ for (uint8_t i = 0; i < ARRAY_LEN(hart_device_attribute.device_status.additional_device_status.device_specific_status); i++)
+ {
+ *ptr = hart_device_attribute.device_status.additional_device_status.device_specific_status[i];
+ ptr++;
+ }
+
+ ptr = &command_48.extended_device_status;
+ *ptr = hart_device_attribute.device_status.additional_device_status.extended_device_status;
+ ptr++;
+ *ptr = hart_device_attribute.device_status.additional_device_status.device_operating_mode;
+ ptr++;
+ *ptr = hart_device_attribute.device_status.additional_device_status.standardized_status0;
+ ptr++;
+ *ptr = hart_device_attribute.device_status.additional_device_status.standardized_status1;
+ ptr++;
+ // *ptr = hart_device_attribute.device_status.additional_device_status.analog_channel_saturated;
+ // ptr++;
+ // *ptr = hart_device_attribute.device_status.additional_device_status.standardized_status2;
+ // ptr++;
+ // *ptr = hart_device_attribute.device_status.additional_device_status.standardized_status3;
+ // ptr++;
+ // *ptr = hart_device_attribute.device_status.additional_device_status.analog_channel_fixed;
+ // ptr++;
+
+ // ptr = command_48.extended_device_specific_status;
+ // for (uint8_t i = 0; i < 11; i++)
+ // {
+ // *ptr = hart_device_attribute.device_status.additional_device_status.extended_device_specific_status[i];
+ // }
+
+ // 回复数据
+ osel_memcpy(resp->data_p, (uint8_t *)&command_48, sizeof(additional_device_status_t));
+ resp->data_p += sizeof(additional_device_status_t);
+ return TRUE;
+}
+// 扩展命令
+static BOOL hart_slave_command_31_req(const hart_command_req_t *const req, hart_response_t *resp) // ZKBW
+{
+ // uint8_t *code = NULL;
+ // hart_device_variable_t *variable = NULL;
+ // float32_u tmp;
+ if (req->data_length < 2)
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_5;
+ return TRUE;
+ }
+ else
+ {
+ // 处理大号命令
+ }
+ return TRUE;
+}
+// 通用命令
+
+/**
+ * @brief 读取设备变量V5
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_33_req(const hart_command_req_t *const req, hart_response_t *resp) // ZKBW
+{
+ uint8_t *code = NULL;
+ hart_device_variable_t *variable = NULL;
+ float32_u tmp;
+ uint8_t uctemp_length = 0;
+ uctemp_length = req->data_length;
+ variable_e type = VARIABLE;
+ if (uctemp_length == 0)
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_5;
+ return TRUE;
+ }
+ if(uctemp_length > 4)
+ {
+ uctemp_length = 4;
+ }
+ if(uctemp_length == 4 && req->data.command_33.slot_0 == 0xff && req->data.command_33.slot_1 == 0xff
+ && req->data.command_33.slot_2 == 0xff && req->data.command_33.slot_3)
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_2;
+ return TRUE;
+ }
+
+ code = (uint8_t *)&req->data.command_33;
+ for (uint8_t i = 0; i < uctemp_length; i++)
+ {
+
+ type = get_variable_type(*code);
+ if (type == VARIABLE)
+ {
+ variable = get_device_variable(*code);
+ }
+ else if (type == CONSTANT)
+ {
+ variable = &hart_device_variable_invalid;
+ }
+ else
+ {
+ variable = get_device_variable_by_standard_code(*code);
+ }
+
+ osel_memcpy((uint8_t *)&tmp.f, (uint8_t *)variable->value, sizeof(float32));
+ tmp.f -= variable->trim_point.value;
+ tmp.c = S2B_UINT32(tmp.c);
+ *resp->data_p++ = variable->code;
+ *resp->data_p++ = variable->units_code;
+ osel_memcpy(resp->data_p, (uint8_t *)&tmp, sizeof(float32_u));
+ resp->data_p += sizeof(float32_u);
+ code++;
+ }
+ return TRUE;
+}
+
+/**
+ * @brief 写入主变量范围值V5
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_35_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ BOOL change = FALSE;
+ hart_device_variable_t *variable = NULL;
+ float32_u tmpupper, tmplower;
+ hart_command_req_t user_req;
+ uint8_t i = 0;
+ if (req->data_length < sizeof(hart_command_35_t))
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_5;
+ return TRUE;
+ }
+ osel_memcpy((uint8_t *)&user_req.data.command_35, (uint8_t *)&req->data.command_35, sizeof(hart_command_35_t));
+ variable = get_device_variable_by_standard_code(DIN_246); // 主变量
+ if (variable->code == DIN_250)
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_11;
+ return TRUE;
+ }
+
+ for (i = 0; i < sizeof(variable->units_code_allow); i++)
+ {
+ if (variable->units_code_allow[i] == req->data.command_35.pv_upper_and_lower_range_values_units_code)
+ {
+ if (variable->transducer.upper_and_lower_range_values_units_code != req->data.command_35.pv_upper_and_lower_range_values_units_code)
+ {
+ variable->transducer.upper_and_lower_range_values_units_code = req->data.command_35.pv_upper_and_lower_range_values_units_code;
+ change = TRUE;
+ }
+ break;
+ }
+ }
+ if (i >= sizeof(variable->units_code_allow))
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_2;
+ return TRUE;
+ }
+ tmpupper.f = req->data.command_35.pv_upper_range_value;
+ tmpupper.c = B2S_UINT32(tmpupper.c);
+ tmplower.f = req->data.command_35.pv_lower_range_value;
+ tmplower.c = B2S_UINT32(tmplower.c);
+ if ((tmpupper.f > variable->transducer.upper_limit.f && tmplower.f < variable->transducer.lower_limit.f) || (tmpupper.f < variable->transducer.lower_limit.f && tmplower.f > variable->transducer.upper_limit.f))
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_13;
+
+ return TRUE;
+ }
+ if (tmplower.f > variable->transducer.upper_limit.f)
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_9;
+
+ return TRUE;
+ }
+ if (tmpupper.f > variable->transducer.upper_limit.f)
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_11;
+
+ return TRUE;
+ }
+ if (tmpupper.f < variable->transducer.lower_limit.f)
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_12;
+
+ return TRUE;
+ }
+
+ if (tmplower.f < variable->transducer.lower_limit.f)
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_10;
+
+ return TRUE;
+ }
+
+ if (tmpupper.f == tmplower.f)
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_29;
+
+ return TRUE;
+ }
+
+ if (((tmpupper.f - tmplower.f) <= 0) && ((tmplower.f - tmpupper.f) < variable->transducer.minimum_span.f))
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_14;
+ }
+ if (((tmpupper.f - tmplower.f) > 0) && ((tmpupper.f - tmplower.f) < variable->transducer.minimum_span.f))
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_14;
+ }
+
+ if (variable->transducer.upper_limit.f != tmpupper.f)
+ {
+ osel_memcpy((uint8_t *)&variable->transducer.upper_limit.f, (uint8_t *)&tmpupper.f, sizeof(float32));
+ change = TRUE;
+ }
+
+ if (variable->transducer.lower_limit.f != tmplower.f)
+ {
+ osel_memcpy((uint8_t *)&variable->transducer.lower_limit.f, (uint8_t *)&tmplower.f, sizeof(float32));
+ change = TRUE;
+ }
+
+ if (change)
+ {
+ hart_device_status_set_operational_state(DEVICE_OPERATIONAL_STATE_7);
+ }
+ // 回复数据
+ *resp->data_p++ = variable->transducer.upper_and_lower_range_values_units_code;
+ osel_memcpy((uint8_t *)&tmpupper.f, (uint8_t *)&variable->transducer.upper_limit.f, sizeof(float32));
+ tmpupper.c = S2B_UINT32(tmpupper.c);
+ osel_memcpy(resp->data_p, (uint8_t *)&tmpupper, sizeof(float32_u));
+ resp->data_p += sizeof(float32_u);
+
+ osel_memcpy((uint8_t *)&tmplower.f, (uint8_t *)&variable->transducer.lower_limit.f, sizeof(float32));
+ tmplower.c = S2B_UINT32(tmplower.c);
+ osel_memcpy(resp->data_p, (uint8_t *)&tmplower, sizeof(float32_u));
+ resp->data_p += sizeof(float32_u);
+ hart_user_common_event(HART_COMMAND_35_EVENT, (void *)&user_req); // 同步单位到udevice
+ return TRUE;
+}
+
+/**
+ * @brief 执行设备重置V5
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_42_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ // hart_device_reset();
+ // 7.9之后不再支持复位命令
+ return FALSE;
+}
+
+/**
+ * @brief 编写主变量单元V5
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_44_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ BOOL change = FALSE;
+ hart_device_variable_t *variable = NULL;
+ hart_command_req_t user_req;
+ uint8_t i = 0;
+ if (req->data_length < sizeof(hart_command_44_t))
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_5;
+ return TRUE;
+ }
+ osel_memcpy((uint8_t *)&user_req.data.command_44, (uint8_t *)&req->data.command_44, sizeof(hart_command_44_t));
+ variable = get_device_variable_by_standard_code(DIN_246); // 主变量
+ if (variable->code == DIN_250)
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_11;
+ return TRUE;
+ }
+ if (req->data.command_44.pv_units_code == 0xFA)
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_2;
+ return TRUE;
+ }
+
+ for (i = 0; i < sizeof(variable->units_code_allow); i++)
+ {
+ if (variable->units_code_allow[i] == req->data.command_44.pv_units_code)
+ {
+ if (variable->units_code != req->data.command_44.pv_units_code)
+ {
+ variable->units_code = req->data.command_44.pv_units_code;
+ change = TRUE;
+ }
+ if (variable->transducer.upper_and_lower_range_values_units_code != req->data.command_44.pv_units_code)
+ {
+ variable->transducer.upper_and_lower_range_values_units_code = req->data.command_44.pv_units_code;
+ change = TRUE;
+ }
+ break;
+ }
+ }
+ if (i >= sizeof(variable->units_code_allow))
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_2;
+ return TRUE;
+ }
+
+ if (change)
+ {
+ hart_device_status_set_operational_state(DEVICE_OPERATIONAL_STATE_7);
+ }
+
+ // 回复数据
+ *resp->data_p++ = variable->units_code;
+ hart_user_common_event(HART_COMMAND_44_EVENT, (void *)&user_req); // 同步单位到udevice
+ return TRUE;
+}
+
+/**
+ * @brief 读取动态变量赋值V5
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_50_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ hart_device_standard_variable_t *variable = NULL;
+ variable = get_device_standard_variable(DIN_246); // 主变量
+ *resp->data_p++ = variable->dynamic_variable_code;
+ variable = get_device_standard_variable(DIN_247); // 次要变量
+ *resp->data_p++ = variable->dynamic_variable_code;
+ variable = get_device_standard_variable(DIN_248); // 第三变量
+ *resp->data_p++ = variable->dynamic_variable_code;
+ variable = get_device_standard_variable(DIN_249); // 第四变量
+ *resp->data_p++ = variable->dynamic_variable_code;
+ return TRUE;
+}
+
+/**
+ * @brief 编写动态变量赋值V5
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_51_req(const hart_command_req_t *const req, hart_response_t *resp) // zkbw
+{
+ if (req->data_length == 0)
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_5;
+ return TRUE;
+ }
+ BOOL ret = FALSE;
+ BOOL change = FALSE;
+ uint8_t *ptr = NULL;
+ uint8_t code = 0;
+// uint16_t invalid_selection[] = {DIN_244, DIN_245, DIN_246, DIN_247,
+// DIN_248, DIN_249};
+ uint8_t device_variables[4];
+ osel_memset(device_variables, DIN_250, ARRAY_LEN(device_variables));
+ for (uint8_t i = 0; i < req->data_length; i++)
+ {
+ ptr = (uint8_t *)&req->data.command_51.device_ariables[i];
+ // 设备变量代码244-249是无效的选择
+ if (req->data.command_51.device_ariables[i] > 0x0A)
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_2;
+ return TRUE;
+ }
+ else
+ {
+ device_variables[i] = *ptr;
+ }
+ }
+
+ // 更新动态变量赋值
+ /* The above code is iterating through an array of device variables and setting their dynamic variable
+ codes based on their position in the array. It uses a switch statement to determine which device
+ variable to set and then adds the dynamic variable code to a response data buffer. */
+ for (uint8_t i = 0; i < ARRAY_LEN(device_variables); i++)
+ {
+ code = DIN_246 + i;
+ if (code != device_variables[i])
+ {
+ change = TRUE;
+ }
+
+ ret = copy_device_dynamic_variable(code, device_variables[i]);
+ if (ret == FALSE)
+ {
+ *resp->data_p++ = DIN_250;
+ }
+ else
+ {
+ *resp->data_p++ = device_variables[i];
+ }
+ }
+
+ if (change)
+ {
+ hart_device_status_set_operational_state(DEVICE_OPERATIONAL_STATE_7);
+ }
+
+ return TRUE;
+}
+
+/**
+ * @brief 设置设备变量零V5
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_52_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ hart_device_variable_t *variable = NULL;
+ BOOL find = FALSE;
+ if (req->data_length < sizeof(hart_command_52_t))
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_5; // 无效的数据长度
+ return TRUE;
+ }
+
+ /* The above code is iterating through an array of HART device variables and checking if the code of
+ each variable matches a specific device variable code provided in the request data. If a match is
+ found, the value of that device variable is set to 0 and the loop is exited. */
+
+ variable = get_device_variable(req->data.command_52.device_ariable);
+ if (variable->code == DIN_250)
+ {
+ find = FALSE;
+ }
+ else
+ {
+ if (variable->trim_point.trim_points != TRIM_POINTS_0)
+ {
+ find = TRUE;
+ // 数据处理
+ if (set_trim_point(variable, &resp->code) == TRUE)
+ {
+ hart_storage_write_item(HART_STORAGE_VARIABLE, variable->code,
+ (uint8_t *)variable);
+ hart_device_status_set_operational_state(DEVICE_OPERATIONAL_STATE_7);
+ }
+ }
+ }
+
+ // 回复数据
+ if (FALSE == find)
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_2; // 无效的设备变量代码
+ return TRUE;
+ }
+ else
+ {
+ *resp->data_p++ = variable->code; // 设备变量代码
+ }
+
+ return TRUE;
+}
+
+/**
+ * @brief 写入设备变量单位V5
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_53_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ hart_device_variable_t *hart_device_variable_p = NULL;
+ hart_command_req_t user_req;
+ variable_e type;
+ if (req->data_length < sizeof(hart_command_53_t))
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_5;
+ return TRUE;
+ }
+ osel_memcpy((uint8_t *)&user_req.data.command_53, (uint8_t *)&req->data.command_53, sizeof(hart_command_53_t));
+ hart_device_variable_p = get_device_variable(req->data.command_53.device_ariable);
+
+
+ type = get_variable_type(req->data.command_53.device_ariable);
+ if (type == VARIABLE)
+ {
+ hart_device_variable_p = get_device_variable(req->data.command_53.device_ariable);
+ }
+ else if (type == CONSTANT)
+ {
+ hart_device_variable_p = &hart_device_variable_invalid;
+ }
+ else
+ {
+ hart_device_variable_p = get_device_variable_by_standard_code(req->data.command_53.device_ariable);
+ }
+ if(req->data.command_53.device_ariable_unit_code == 0xFA)
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_12;
+ return TRUE;
+ }
+ // 回复数据
+ if (hart_device_variable_p->code == DIN_250)
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_11; // 无效的设备变量代码
+ }
+ else
+ {
+ BOOL allow = FALSE;
+ // 判断传过来的单位是否在允许的范围内
+ for (uint8_t i = 0; i < HART_VARIABLE_UNITS_ALLOWED_CNT; i++)
+ {
+ if (req->data.command_53.device_ariable_unit_code == hart_device_variable_p->units_code_allow[i])
+ {
+ allow = TRUE;
+ break;
+ }
+ }
+
+ if (allow == FALSE)
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_12;
+ }
+ else
+ {
+
+ if (hart_device_variable_p->units_code != req->data.command_53.device_ariable_unit_code)
+ {
+ hart_device_variable_p->units_code = req->data.command_53.device_ariable_unit_code;
+
+ hart_storage_write_item(HART_STORAGE_VARIABLE, hart_device_variable_p->code,
+ (uint8_t *)hart_device_variable_p);
+ hart_device_status_set_operational_state(DEVICE_OPERATIONAL_STATE_7);
+ }
+
+ // hart_user_common_event(HART_COMMAND_53_EVENT, (void *)&user_req); // 如果写入设备变量单位为压力或者电流,同步到命令129的变量单位中
+
+ *resp->data_p++ = hart_device_variable_p->code; // 设备变量代码
+ *resp->data_p++ = hart_device_variable_p->units_code; // 设备变量单位代码
+ }
+ }
+ return TRUE;
+}
+
+/**
+ * @brief 读取设备变量信息V5
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_54_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ hart_device_variable_t *hart_device_variable_p = NULL;
+ float32_u tmp;
+ uint32_t acquisition_period = 0;
+ if (req->data_length < sizeof(hart_command_54_t))
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_5;
+ return TRUE;
+ }
+ hart_device_variable_p = get_device_variable(req->data.command_54.device_ariable);
+ if (hart_device_variable_p->code == DIN_250)
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_11; // 无效的设备变量代码
+ return TRUE;
+ }
+ *hart_device_attribute.last_device_variable = hart_device_variable_p->code;
+
+ // 回复数据
+ *resp->data_p++ = hart_device_variable_p->code; // 设备变量代码
+ osel_memcpy(resp->data_p, hart_device_variable_p->transducer.serial_number.bs, sizeof(uint24_t)); // 设备可变传感器序列号
+ resp->data_p += sizeof(uint24_t);
+ *resp->data_p++ = hart_device_variable_p->transducer.limits_and_minimum_span_units_code; // 设备变量限制/最小量程单位代码
+
+ // 设备变量传感器上限
+ tmp.f = hart_device_variable_p->transducer.upper_limit.f;
+ tmp.c = S2B_UINT32(tmp.c);
+ osel_memcpy(resp->data_p, (uint8_t *)&tmp, sizeof(float32_u));
+ resp->data_p += sizeof(float32_u);
+ // 装置可变传感器下限
+ tmp.f = hart_device_variable_p->transducer.lower_limit.f;
+ tmp.c = S2B_UINT32(tmp.c);
+ osel_memcpy(resp->data_p, (uint8_t *)&tmp, sizeof(float32_u));
+ resp->data_p += sizeof(float32_u);
+ // 设备可变阻尼值
+ tmp.f = hart_device_variable_p->attribute.damping_value;
+ tmp.c = S2B_UINT32(tmp.c);
+ osel_memcpy(resp->data_p, (uint8_t *)&tmp, sizeof(float32_u));
+ resp->data_p += sizeof(float32_u);
+
+ // 设备变量最小量程
+ tmp.f = hart_device_variable_p->transducer.minimum_span.f;
+ tmp.c = S2B_UINT32(tmp.c);
+ osel_memcpy(resp->data_p, (uint8_t *)&tmp, sizeof(float32_u));
+ resp->data_p += sizeof(float32_u);
+
+ if (hart_get_current_protocol_version() == HART_PROTOCOL_VERSION_7)
+ {
+ *resp->data_p++ = hart_device_variable_p->classification; // 设备变量分类
+ *resp->data_p++ = hart_device_variable_p->family; // 设备变量系列
+
+ acquisition_period = hart_device_variable_p->acquisition_period;
+ acquisition_period = S2B_UINT32(acquisition_period);
+ osel_memcpy(resp->data_p, (uint8_t *)&acquisition_period, sizeof(uint32_t)); // 采集周期,表示设备变量更新之间的最长周期
+ resp->data_p += sizeof(uint32_t);
+
+ *resp->data_p++ = hart_device_variable_p->properties; // 设备变量属性
+ }
+ return TRUE;
+}
+
+/**
+ * @brief 写入响应序码数V5
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_59_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ if (req->data_length < sizeof(hart_command_59_t))
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_5;
+ return TRUE;
+ }
+ if (req->data.command_59.s2m_preambles < 5)
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_4;
+ return TRUE;
+ }
+ else if (req->data.command_59.s2m_preambles > 20)
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_3;
+ return TRUE;
+ }
+ else
+ {
+ if (hart_device_attribute.flash_variable.s2m_preambles != req->data.command_59.s2m_preambles)
+ {
+ hart_device_attribute.flash_variable.s2m_preambles = req->data.command_59.s2m_preambles;
+
+ hart_storage_write_item(HART_STORAGE_PARAMS, HPB_S2M_PREAMBLES,
+ &hart_device_attribute.flash_variable.s2m_preambles);
+ hart_device_status_set_operational_state(DEVICE_OPERATIONAL_STATE_7);
+ }
+
+ *resp->data_p++ = hart_device_attribute.flash_variable.s2m_preambles;
+ }
+
+ return TRUE;
+}
+
+/**
+ * @brief 读取精简状态映射数组
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_523_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ hart_user_req_t user_req;
+ if (hart_frame_data_length_check(req->data_length, sizeof(hart_command_523_t), (uint8_t *)&resp->code) == FALSE)
+ {
+ return TRUE;
+ }
+ osel_memcpy((uint8_t *)&user_req.data.command_523, (uint8_t *)&req->data.command_523, sizeof(hart_command_523_t));
+ if (FALSE == hart_user_common_event(HART_COMMAND_523_EVENT, (void *)&user_req))
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_64;
+ return TRUE;
+ }
+ if (user_req.rsp.len != 0)
+ {
+ osel_memcpy(resp->data_p, user_req.rsp.pbuf, user_req.rsp.len);
+ resp->data_p += user_req.rsp.len;
+ }
+ return TRUE;
+}
+/**
+ * @brief 写入精简状态映射
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_524_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+
+ return TRUE;
+}
+
+#if 0
+/**
+ * @brief 写入主变量阻尼值V5
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_34_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ float32_u tmp;
+ hart_device_variable_t *variable = NULL;
+ if (req->data_length < sizeof(hart_command_34_t))
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_5;
+ return TRUE;
+ }
+ variable = get_device_variable_by_standard_code(DIN_246); // 主变量
+ if (variable->code == DIN_250)
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_6;
+ return TRUE;
+ }
+
+ tmp.f = req->data.command_34.pv_damping_value;
+ tmp.c = B2S_UINT32(tmp.c);
+ variable->attribute.damping_value = tmp.f;
+ hart_device_status_set_operational_state(DEVICE_OPERATIONAL_STATE_7);
+ tmp.f = variable->attribute.damping_value;
+ tmp.c = S2B_UINT32(tmp.c);
+ osel_memcpy(resp->data_p, (uint8_t *)&tmp, sizeof(float32_u));
+ resp->data_p += sizeof(float32_u);
+ return TRUE;
+}
+
+
+/**
+ * @brief 设置主变量上限值V5
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_36_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ hart_device_variable_t *variable = NULL;
+ variable = get_device_variable_by_standard_code(DIN_246); // 主变量
+ if (variable->code == DIN_250)
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_6;
+ return TRUE;
+ }
+ osel_memcpy((uint8_t *)variable->value, (uint8_t *)&variable->transducer.upper_limit.f, sizeof(float32)); // 将主要变量上限值复制到主变量
+ hart_device_status_set_operational_state(DEVICE_OPERATIONAL_STATE_7);
+ return TRUE;
+}
+
+/**
+ * @brief 设置主变量下限值V5
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_37_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ hart_device_variable_t *variable = NULL;
+ variable = get_device_variable_by_standard_code(DIN_246); // 主变量
+ if (variable->code == DIN_250)
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_6;
+ return TRUE;
+ }
+ osel_memcpy((uint8_t *)variable->value, (uint8_t *)&variable->transducer.lower_limit.f, sizeof(float32)); // 将主要变量下限值复制到主变量
+ hart_device_status_set_operational_state(DEVICE_OPERATIONAL_STATE_7);
+ return TRUE;
+}
+
+
+/**
+ * @brief EEPROM控制V5 0 刻录EEPROM 1 恢复影子内存
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_39_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ BOOL ret = FALSE;
+ if (req->data_length < sizeof(hart_command_39_t))
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_5;
+ return TRUE;
+ }
+
+ if (0 == req->data.command_39.control_code)
+ {
+ hart_storage_write_sem_update();
+ }
+ else
+ {
+ ret = hart_storage_read(HART_STORAGE_PARAMS, (uint8_t *)&hart_device_attribute.flash_variable, sizeof(hart_storage_variable_t));
+ }
+ if (TRUE == ret)
+ {
+ // BIT_CLR(hart_device_attribute.device_status.operational_state, DEVICE_OPERATIONAL_STATE_7 | DEVICE_OPERATIONAL_STATE_8);
+ }
+ else
+ {
+ // BIT_SET(hart_device_attribute.device_status.operational_state, DEVICE_OPERATIONAL_STATE_8);
+ }
+
+ // 回复数据
+ *resp->data_p++ = req->data.command_39.control_code;
+ return TRUE;
+}
+
+/**
+ * @brief 执行自检V5
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_41_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ hart_perform_self_test(); // TODO 跳转到自检画面
+ return TRUE;
+}
+
+/**
+ * @brief 进入/退出固定电流模式V5
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_40_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ float32_u tmp;
+ if (req->data_length < sizeof(hart_command_40_t))
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_5;
+ return TRUE;
+ }
+ tmp.f = req->data.command_40.pv_fixed_current_level;
+ tmp.c = B2S_UINT32(tmp.c);
+ hart_device_attribute.pv_fixed_current_level = tmp.f;
+
+ // 回复数据
+ tmp.f = *hart_device_attribute.actual_pv_current_level;
+ tmp.c = S2B_UINT32(tmp.c);
+ osel_memcpy(resp->data_p, (uint8_t *)&tmp, sizeof(float32_u));
+ resp->data_p += sizeof(float32_u);
+ return TRUE;
+}
+
+/**
+ * @brief 设置主变量零V5
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_43_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ hart_device_variable_t *variable = NULL;
+ variable = get_device_variable_by_standard_code(DIN_246); // 主变量
+ if (variable->code == DIN_250)
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_6;
+ return TRUE;
+ }
+ *variable->value = 0;
+ return TRUE;
+}
+
+
+
+/**
+ * @brief 微调回路电流归零V5
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_45_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ float32_u tmp;
+ if (req->data_length < sizeof(hart_command_45_t))
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_5;
+ return TRUE;
+ }
+ hart_device_variable_t *variable = NULL;
+ variable = get_device_variable_by_standard_code(DIN_245); // 回路电流
+ if (variable->code == DIN_250)
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_6;
+ return TRUE;
+ }
+ tmp.f = req->data.command_45.pv_loop_current_level;
+ tmp.c = B2S_UINT32(tmp.c);
+ hart_device_attribute.pv_loop_current_level = tmp.f;
+
+ // 回复数据
+ tmp.f = *variable->value;
+ tmp.c = S2B_UINT32(tmp.c);
+ osel_memcpy(resp->data_p, (uint8_t *)&tmp, sizeof(float32_u));
+ resp->data_p += sizeof(float32_u);
+ return TRUE;
+}
+
+/**
+ * @brief 微调回路电流增益V5
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_46_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ float32_u tmp;
+ if (req->data_length < sizeof(hart_command_46_t))
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_5;
+ return TRUE;
+ }
+ hart_device_variable_t *variable = NULL;
+ variable = get_device_variable_by_standard_code(DIN_245); // 回路电流
+ if (variable->code == DIN_250)
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_6;
+ return TRUE;
+ }
+ tmp.f = req->data.command_46.pv_loop_current_level;
+ tmp.c = B2S_UINT32(tmp.c);
+ hart_device_attribute.pv_loop_current_level = tmp.f;
+
+ // 回复数据
+ tmp.f = *variable->value;
+ tmp.c = S2B_UINT32(tmp.c);
+ osel_memcpy(resp->data_p, (uint8_t *)&tmp, sizeof(float32_u));
+ resp->data_p += sizeof(float32_u);
+ return TRUE;
+}
+
+/**
+ * @brief 编写主变量传递函数V5
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_47_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ hart_device_variable_t *variable = NULL;
+ if (req->data_length < sizeof(hart_command_47_t))
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_5;
+ return TRUE;
+ }
+
+ variable = get_device_variable_by_standard_code(DIN_246); // 主变量
+ if (variable->code == DIN_250)
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_6;
+ return TRUE;
+ }
+ variable->attribute.transfer_function_code = req->data.command_47.pv_transfer_function_code;
+ hart_device_status_set_operational_state(DEVICE_OPERATIONAL_STATE_7);
+ // 回复数据
+ *resp->data_p++ = variable->attribute.transfer_function_code;
+ return TRUE;
+}
+
+/**
+ * @brief 写入主变量传感器序列号V5
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_49_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ hart_device_variable_t *variable = NULL;
+ if (req->data_length < sizeof(hart_command_49_t))
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_5;
+ return TRUE;
+ }
+ variable = get_device_variable_by_standard_code(DIN_246); // 主变量
+ if (variable->code == DIN_250)
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_6;
+ return TRUE;
+ }
+ osel_memcpy(variable->transducer.serial_number.bs, req->data.command_49.pv_transducer_serial_number.bs, sizeof(uint24_t));
+ hart_device_status_set_operational_state(DEVICE_OPERATIONAL_STATE_7);
+ osel_memcpy(resp->data_p, variable->transducer.serial_number.bs, sizeof(uint24_t));
+ resp->data_p += sizeof(uint24_t);
+ return TRUE;
+}
+
+/**
+ * @brief 写入设备可变阻尼值V5
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_55_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ float32_u tmp;
+ if (req->data_length < sizeof(hart_command_55_t))
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_5;
+ return TRUE;
+ }
+ hart_device_variable_t *variable = NULL;
+ variable = get_device_variable(req->data.command_55.device_ariable);
+ if (variable->code == DIN_250)
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_2;
+ return TRUE;
+ }
+ tmp.f = req->data.command_55.damping_value;
+ tmp.c = B2S_UINT32(tmp.c);
+ variable->attribute.damping_value = tmp.f;
+ hart_device_status_set_operational_state(DEVICE_OPERATIONAL_STATE_7);
+ // 回复数据
+ *resp->data_p++ = variable->code; // 设备变量代码
+ tmp.f = variable->attribute.damping_value;
+ tmp.c = S2B_UINT32(tmp.c);
+ osel_memcpy(resp->data_p, (uint8_t *)&tmp, sizeof(float32_u)); // 设备可变阻尼值
+ resp->data_p += sizeof(float32_u);
+ return TRUE;
+}
+
+/**
+ * @brief 写入设备可变传感器序列号V5
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_56_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ if (req->data_length < sizeof(hart_command_56_t))
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_5;
+ return TRUE;
+ }
+ hart_device_variable_t *variable = NULL;
+ variable = get_device_variable(req->data.command_56.device_ariable);
+ if (variable->code == DIN_250)
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_2;
+ return TRUE;
+ }
+ osel_memcpy(variable->transducer.serial_number.bs, req->data.command_56.serial_number.bs, sizeof(uint24_t));
+ hart_device_status_set_operational_state(DEVICE_OPERATIONAL_STATE_7);
+ // 回复数据
+ *resp->data_p++ = variable->code; // 设备变量代码
+ osel_memcpy(resp->data_p, variable->transducer.serial_number.bs, sizeof(uint24_t)); // 设备可变传感器序列号
+ resp->data_p += sizeof(uint24_t);
+ return TRUE;
+}
+
+/**
+ * @brief 读取单位标签、描述符、日期V5
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_57_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ osel_memcpy(resp->data_p, (uint8_t *)&hart_device_attribute.flash_variable.unit_device, sizeof(unit_device_t));
+ resp->data_p += sizeof(unit_device_t);
+ return TRUE;
+}
+
+/**
+ * @brief 编写单位标签、描述符、日期V5
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_58_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ if (req->data_length < sizeof(hart_command_58_t))
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_5;
+ return TRUE;
+ }
+ osel_memcpy((uint8_t *)&hart_device_attribute.flash_variable.unit_device, (uint8_t *)&req->data.command_58, sizeof(hart_command_58_t));
+ hart_device_status_set_operational_state(DEVICE_OPERATIONAL_STATE_7);
+ osel_memcpy(resp->data_p, (uint8_t *)&hart_device_attribute.flash_variable.unit_device, sizeof(unit_device_t));
+ resp->data_p += sizeof(unit_device_t);
+ return TRUE;
+}
+
+
+/**
+ * @brief 读取模拟通道和范围百分比V5
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_60_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ float32_u tmp;
+ analog_channel_t *analog_channel = NULL;
+ if (req->data_length < sizeof(hart_command_60_t))
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_5;
+ return TRUE;
+ }
+ analog_channel = get_analog_channel((analog_channel_number_codes_e)req->data.command_60.analog_channel_number_code);
+ if (analog_channel == NULL)
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_2;
+ return TRUE;
+ }
+
+ /* The above code is writing data to a response buffer. It is taking values from an analog channel
+ structure (code, units_code, level, percent_range) and converting them to a byte representation
+ using a union (tmp). The byte representation is then copied to the response buffer using memcpy. The
+ response buffer pointer is incremented after each write to ensure that the next write goes to the
+ correct location in the buffer. */
+ *resp->data_p++ = analog_channel->code;
+ *resp->data_p++ = analog_channel->units_code;
+
+ tmp.f = analog_channel->level.f;
+ tmp.c = B2S_UINT32(tmp.c);
+ osel_memcpy(resp->data_p, (uint8_t *)&tmp, sizeof(float32_u));
+ resp->data_p += sizeof(float32_u);
+
+ tmp.f = analog_channel->percent_range.f;
+ tmp.c = B2S_UINT32(tmp.c);
+ osel_memcpy(resp->data_p, (uint8_t *)&tmp, sizeof(float32_u));
+ resp->data_p += sizeof(float32_u);
+
+ return TRUE;
+}
+
+/**
+ * @brief读取动态变量和主变量模拟通道V5
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_61_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ float32_u tmp;
+ hart_device_variable_t *variable = NULL;
+ analog_channel_t *analog_channel = get_analog_channel(ANALOG_CHANNEL_NUMBER_CODES_0);
+ if (analog_channel == NULL)
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_6;
+ return TRUE;
+ }
+ *resp->data_p++ = analog_channel->units_code; // 主要模拟通道单元代码
+
+ tmp.f = analog_channel->level.f;
+ tmp.c = B2S_UINT32(tmp.c);
+ osel_memcpy(resp->data_p, (uint8_t *)&tmp, sizeof(float32_u)); // 主要可变模拟电平
+ resp->data_p += sizeof(float32_u);
+
+ variable = get_device_variable_by_standard_code(DIN_246);
+ if (variable->code == DIN_250)
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_6;
+ return TRUE;
+ }
+ *resp->data_p++ = variable->units_code; // 主要变量单元代码
+ tmp.f = *variable->value;
+ tmp.c = B2S_UINT32(tmp.c);
+ osel_memcpy(resp->data_p, (uint8_t *)&tmp, sizeof(float32_u)); // 主要变量值
+ resp->data_p += sizeof(float32_u);
+
+ variable = get_device_variable_by_standard_code(DIN_247);
+ if (variable->code == DIN_250)
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_6;
+ return TRUE;
+ }
+ *resp->data_p++ = variable->units_code; // 次要变量单元代码
+ tmp.f = *variable->value;
+ tmp.c = B2S_UINT32(tmp.c);
+ osel_memcpy(resp->data_p, (uint8_t *)&tmp, sizeof(float32_u)); // 次要变量值
+ resp->data_p += sizeof(float32_u);
+
+ variable = get_device_variable_by_standard_code(DIN_248);
+ if (variable->code == DIN_250)
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_6;
+ return TRUE;
+ }
+ *resp->data_p++ = variable->units_code; // 第三变量单元代码
+ tmp.f = *variable->value;
+ tmp.c = B2S_UINT32(tmp.c);
+ osel_memcpy(resp->data_p, (uint8_t *)&tmp, sizeof(float32_u)); // 第三变量值
+ resp->data_p += sizeof(float32_u);
+
+ variable = get_device_variable_by_standard_code(DIN_249);
+ if (variable->code == DIN_250)
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_6;
+ return TRUE;
+ }
+ *resp->data_p++ = variable->units_code; // 第四变量单元代码
+ tmp.f = *variable->value;
+ tmp.c = B2S_UINT32(tmp.c);
+ osel_memcpy(resp->data_p, (uint8_t *)&tmp, sizeof(float32_u)); // 第四变量值
+ resp->data_p += sizeof(float32_u);
+ return TRUE;
+}
+
+/**
+ * @brief读取模拟通道V5
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_62_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ float32_u tmp;
+ if (req->data_length == 0)
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_5;
+ return TRUE;
+ }
+ analog_channel_t *analog_channel = NULL;
+ uint8_t *code = (uint8_t *)&req->data.command_62;
+ for (uint8_t i = 0; i < req->data_length; i++)
+ {
+ analog_channel = get_analog_channel((analog_channel_number_codes_e)(*(code + i)));
+ if (analog_channel == NULL)
+ {
+ analog_channel = get_analog_channel(ANALOG_CHANNEL_NUMBER_CODES_0);
+ }
+ *resp->data_p++ = analog_channel->code; // 模拟通道代码
+ *resp->data_p++ = analog_channel->units_code; // 模拟通道单元代码
+
+ tmp.f = analog_channel->level.f;
+ tmp.c = B2S_UINT32(tmp.c);
+ osel_memcpy(resp->data_p, (uint8_t *)&tmp, sizeof(float32_u)); // 主要可变模拟电平
+ resp->data_p += sizeof(float32_u);
+ }
+
+ return TRUE;
+}
+/**
+ * @brief读取模拟通道信息V5
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_63_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ if (req->data_length == 0)
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_5;
+ return TRUE;
+ }
+ analog_channel_t *analog_channel = NULL;
+ float32_u tmp;
+ analog_channel = get_analog_channel((analog_channel_number_codes_e)req->data.command_63.analog_channel_number_code);
+ if (analog_channel == NULL)
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_2;
+ return TRUE;
+ }
+ *resp->data_p++ = analog_channel->code; // 模拟通道代码
+ *resp->data_p++ = analog_channel->attribute.alarm_selection_code; // 模拟通道报警选择代码
+ *resp->data_p++ = analog_channel->attribute.transfer_function_code; // 模拟通道单元代码
+ *resp->data_p++ = analog_channel->transducer.upper_and_lower_range_values_units_code; // 模拟通道上下限值单位代码
+
+ // 模拟通道上限值
+ osel_memcpy((uint8_t *)&tmp.f, (uint8_t *)&analog_channel->transducer.upper_limit.f, sizeof(float32));
+ tmp.c = B2S_UINT32(tmp.c);
+ osel_memcpy(resp->data_p, (uint8_t *)&tmp, sizeof(float32_u));
+ resp->data_p += sizeof(float32_u);
+
+ // 模拟通道下限值
+ osel_memcpy((uint8_t *)&tmp.f, (uint8_t *)&analog_channel->transducer.lower_limit.f, sizeof(float32));
+ tmp.c = B2S_UINT32(tmp.c);
+ osel_memcpy(resp->data_p, (uint8_t *)&tmp, sizeof(float32_u));
+ resp->data_p += sizeof(float32_u);
+
+ tmp.f = analog_channel->attribute.damping_value; // 模拟通道阻尼值
+ tmp.c = B2S_UINT32(tmp.c);
+ osel_memcpy(resp->data_p, (uint8_t *)&tmp, sizeof(float32_u));
+ resp->data_p += sizeof(float32_u);
+
+ if (hart_get_current_protocol_version() == HART_PROTOCOL_VERSION_7)
+ {
+ *resp->data_p++ = analog_channel->attribute.analog_channel_flags; // 模拟通道标志
+ }
+ return TRUE;
+}
+/**
+ * @brief写入模拟通道附加阻尼值V5
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_64_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ if (req->data_length < sizeof(hart_command_64_t))
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_5;
+ return TRUE;
+ }
+ analog_channel_t *analog_channel = NULL;
+ float32_u tmp;
+ analog_channel = get_analog_channel((analog_channel_number_codes_e)req->data.command_64.analog_channel_number_code);
+ if (analog_channel == NULL)
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_2;
+ return TRUE;
+ }
+ tmp.f = req->data.command_64.damping_value;
+ tmp.c = B2S_UINT32(tmp.c);
+ analog_channel->attribute.damping_value = tmp.f;
+ hart_device_status_set_operational_state(DEVICE_OPERATIONAL_STATE_7);
+ // 回复数据
+ *resp->data_p++ = analog_channel->code; // 模拟通道代码
+ tmp.f = analog_channel->attribute.damping_value;
+ tmp.c = B2S_UINT32(tmp.c);
+ osel_memcpy(resp->data_p, (uint8_t *)&tmp, sizeof(float32_u)); // 模拟通道阻尼值
+ resp->data_p += sizeof(float32_u);
+ return TRUE;
+}
+/**
+ * @brief写入模拟通道范围值V5
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_65_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ if (req->data_length < sizeof(hart_command_65_t))
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_5;
+ return TRUE;
+ }
+ analog_channel_t *analog_channel = NULL;
+ float32_u tmp;
+ analog_channel = get_analog_channel((analog_channel_number_codes_e)req->data.command_65.analog_channel_number_code);
+ if (analog_channel == NULL)
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_2;
+ return TRUE;
+ }
+ analog_channel->transducer.upper_and_lower_range_values_units_code = req->data.command_65.upper_and_lower_range_values_units_code; // 模拟通道上下限值单位代码
+
+ tmp.f = req->data.command_65.upper_range_value;
+ tmp.c = B2S_UINT32(tmp.c);
+ // 模拟通道上限值
+ osel_memcpy((uint8_t *)&analog_channel->transducer.upper_limit.f, (uint8_t *)&tmp.f, sizeof(float32));
+
+ tmp.f = req->data.command_65.lower_range_value;
+ tmp.c = B2S_UINT32(tmp.c);
+ // 模拟通道下限值
+ osel_memcpy((uint8_t *)&analog_channel->transducer.lower_limit.f, (uint8_t *)&tmp.f, sizeof(float32));
+ hart_device_status_set_operational_state(DEVICE_OPERATIONAL_STATE_7);
+ // 回复数据
+ *resp->data_p++ = analog_channel->code; // 模拟通道代码
+ *resp->data_p++ = analog_channel->transducer.upper_and_lower_range_values_units_code;
+
+ osel_memcpy((uint8_t *)&tmp.f, (uint8_t *)&analog_channel->transducer.upper_limit.f, sizeof(float32));
+ tmp.c = B2S_UINT32(tmp.c);
+ osel_memcpy(resp->data_p, (uint8_t *)&tmp, sizeof(float32_u)); // 模拟通道上限值
+ resp->data_p += sizeof(float32_u);
+
+ osel_memcpy((uint8_t *)&tmp.f, (uint8_t *)&analog_channel->transducer.lower_limit.f, sizeof(float32));
+ tmp.c = B2S_UINT32(tmp.c);
+ osel_memcpy(resp->data_p, (uint8_t *)&tmp, sizeof(float32_u)); // 模拟通道下限值
+ resp->data_p += sizeof(float32_u);
+ return TRUE;
+}
+/**
+ * @brief进入/退出固定模拟通道模式V5
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_66_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ if (req->data_length < sizeof(hart_command_66_t))
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_5;
+ return TRUE;
+ }
+ float32_u tmp;
+ analog_channel_t *analog_channel = NULL;
+ analog_channel = get_analog_channel((analog_channel_number_codes_e)req->data.command_66.analog_channel_number_code);
+ if (analog_channel == NULL)
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_2;
+ return TRUE;
+ }
+ analog_channel->units_code = req->data.command_66.units_code; // 模拟通道单元代码
+ /**
+ * A level containing "0x7F. 0xA0. 0x00. 0x00'with any Units Code exits the Fixed Analog Channel Mode
+ */
+
+ osel_memcpy((uint8_t *)&tmp.f, (uint8_t *)&req->data.command_66.fixed_analog_channel_level, sizeof(int32_t)); // 这里不能直接赋值,因为0x7F. 0xA0. 0x00. 0x00会丢字节
+ if (tmp.c == HART_INVALID_VALUE)
+ {
+ tmp.c = B2S_UINT32(tmp.c);
+ osel_memcpy((uint8_t *)&analog_channel->fixed_analog_channel_level.c, (uint8_t *)&tmp.c, sizeof(int32_t));
+ LOG_PRINT("%08x", analog_channel->fixed_analog_channel_level.c);
+ }
+ else
+ {
+ tmp.c = B2S_UINT32(tmp.c);
+ analog_channel->fixed_analog_channel_level.f = tmp.f; // 模拟通道电平
+ LOG_PRINT("%f", analog_channel->fixed_analog_channel_level.f);
+ }
+
+ hart_device_status_set_operational_state(DEVICE_OPERATIONAL_STATE_7);
+ // 回复数据
+ *resp->data_p++ = analog_channel->code; // 模拟通道代码
+ *resp->data_p++ = analog_channel->units_code;
+ tmp.c = B2S_UINT32(analog_channel->fixed_analog_channel_level.c);
+ if (tmp.c == HART_INVALID_VALUE)
+ {
+ osel_memcpy((uint8_t *)&tmp.c, (uint8_t *)&analog_channel->fixed_analog_channel_level.c, sizeof(int32_t));
+ }
+ else
+ {
+ tmp.c = B2S_UINT32(analog_channel->fixed_analog_channel_level.c);
+ }
+
+ osel_memcpy(resp->data_p, (uint8_t *)&tmp.c, sizeof(int32_t)); // 模拟通道电平
+ resp->data_p += sizeof(int32_t);
+
+ return TRUE;
+}
+/**
+ * @brief调整模拟通道零V5
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_67_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ if (req->data_length < sizeof(hart_command_67_t))
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_5;
+ return TRUE;
+ }
+ float32_u tmp;
+ analog_channel_t *analog_channel = NULL;
+ analog_channel = get_analog_channel((analog_channel_number_codes_e)req->data.command_67.analog_channel_number_code);
+ if (analog_channel == NULL)
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_2;
+ return TRUE;
+ }
+ tmp.c = B2S_UINT32(analog_channel->fixed_analog_channel_level.c);
+ if (tmp.c != HART_INVALID_VALUE)
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_9;
+ return TRUE;
+ }
+
+ analog_channel->units_code = req->data.command_67.units_code; // 模拟通道单元代码
+
+ tmp.f = req->data.command_67.actual_analog_channel_level;
+ tmp.c = B2S_UINT32(tmp.c);
+ analog_channel->actual_analog_channel_level.f = tmp.f; // 模拟通道电平
+
+ hart_device_status_set_operational_state(DEVICE_OPERATIONAL_STATE_7);
+
+ // 回复数据
+ *resp->data_p++ = analog_channel->code; // 模拟通道代码
+ *resp->data_p++ = analog_channel->units_code;
+ tmp.f = analog_channel->actual_analog_channel_level.f;
+ tmp.c = B2S_UINT32(tmp.c);
+ osel_memcpy(resp->data_p, (uint8_t *)&tmp.c, sizeof(int32_t)); // 模拟通道电平
+ resp->data_p += sizeof(int32_t);
+ return TRUE;
+}
+/**
+ * @brief微调模拟通道增益V5
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_68_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ if (req->data_length < sizeof(hart_command_68_t))
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_5;
+ return TRUE;
+ }
+ float32_u tmp;
+ analog_channel_t *analog_channel = NULL;
+ analog_channel = get_analog_channel((analog_channel_number_codes_e)req->data.command_68.analog_channel_number_code);
+ if (analog_channel == NULL)
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_2;
+ return TRUE;
+ }
+ tmp.c = B2S_UINT32(analog_channel->fixed_analog_channel_level.c);
+ if (tmp.c != HART_INVALID_VALUE)
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_9;
+ return TRUE;
+ }
+
+ analog_channel->units_code = req->data.command_68.units_code; // 模拟通道单元代码
+
+ tmp.f = req->data.command_68.externally_measured_analog_channel_level;
+ tmp.c = B2S_UINT32(tmp.c);
+ analog_channel->externally_measured_analog_channel_level.f = tmp.f; // 模拟通道电平
+
+ hart_device_status_set_operational_state(DEVICE_OPERATIONAL_STATE_7);
+
+ // 回复数据
+ *resp->data_p++ = analog_channel->code; // 模拟通道代码
+ *resp->data_p++ = analog_channel->units_code;
+ tmp.f = analog_channel->externally_measured_analog_channel_level.f;
+ tmp.c = B2S_UINT32(tmp.c);
+ osel_memcpy(resp->data_p, (uint8_t *)&tmp.c, sizeof(int32_t)); // 模拟通道电平
+ resp->data_p += sizeof(int32_t);
+ return TRUE;
+}
+/**
+ * @brief写入模拟通道传递函数V5
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_69_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ if (req->data_length < sizeof(hart_command_69_t))
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_5;
+ return TRUE;
+ }
+ analog_channel_t *analog_channel = NULL;
+ analog_channel = get_analog_channel((analog_channel_number_codes_e)req->data.command_69.analog_channel_number_code);
+ if (analog_channel == NULL)
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_2;
+ return TRUE;
+ }
+ analog_channel->attribute.transfer_function_code = req->data.command_69.transfer_function_code;
+ hart_device_status_set_operational_state(DEVICE_OPERATIONAL_STATE_7);
+ // 回复数据
+ *resp->data_p++ = analog_channel->code; // 模拟通道代码
+ *resp->data_p++ = analog_channel->attribute.transfer_function_code;
+ return TRUE;
+}
+/**
+ * @brief读取模拟通道端点值V5
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_70_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ if (req->data_length < sizeof(hart_command_70_t))
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_5;
+ return TRUE;
+ }
+ float32_u tmp;
+ analog_channel_t *analog_channel = NULL;
+ analog_channel = get_analog_channel((analog_channel_number_codes_e)req->data.command_70.analog_channel_number_code);
+ if (analog_channel == NULL)
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_2;
+ return TRUE;
+ }
+ // 回复数据
+ *resp->data_p++ = analog_channel->code; // 模拟通道代码
+ *resp->data_p++ = analog_channel->transducer.upper_and_lower_range_values_units_code; // 模拟通道上下限值单位代码
+
+ tmp.f = analog_channel->externally_measured_analog_channel_level.f;
+ tmp.c = B2S_UINT32(tmp.c);
+ osel_memcpy(resp->data_p, (uint8_t *)&tmp.c, sizeof(int32_t)); // 模拟通道上端点值
+ resp->data_p += sizeof(int32_t);
+
+ tmp.f = analog_channel->actual_analog_channel_level.f;
+ tmp.c = B2S_UINT32(tmp.c);
+ osel_memcpy(resp->data_p, (uint8_t *)&tmp.c, sizeof(int32_t)); // 模拟通道下端点值
+ resp->data_p += sizeof(int32_t);
+
+ if (hart_get_current_protocol_version() == HART_PROTOCOL_VERSION_7)
+ {
+ // 模拟通道上限值
+ osel_memcpy((uint8_t *)&tmp.f, (uint8_t *)&analog_channel->transducer.upper_limit.f, sizeof(float32));
+ tmp.c = B2S_UINT32(tmp.c);
+ osel_memcpy(resp->data_p, (uint8_t *)&tmp.c, sizeof(int32_t));
+ resp->data_p += sizeof(int32_t);
+
+ // 模拟通道下限值
+ osel_memcpy((uint8_t *)&tmp.f, (uint8_t *)&analog_channel->transducer.lower_limit.f, sizeof(float32));
+ tmp.c = B2S_UINT32(tmp.c);
+ osel_memcpy(resp->data_p, (uint8_t *)&tmp.c, sizeof(int32_t));
+ resp->data_p += sizeof(int32_t);
+ }
+ return TRUE;
+}
+
+
+/**
+ * @brief 锁定装置
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_71_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ if (req->data_length < sizeof(hart_command_71_t))
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_5;
+ return TRUE;
+ }
+ uint8_t lock_code = hart_device_attribute.flash_variable.lock_code;
+ if (req->data.command_71.lock_code == LOCK_DEVICE_CODE_0)
+ {
+ if (lock_code != LOCK_DEVICE_CODE_0) // 判断当前锁定状态
+ {
+ if (req->master == 0)
+ {
+ if (lock_code != LOCK_DEVICE_CODE_3)
+ {
+ // 第二主机 不能解锁
+ resp->code = RESPONSE_COMMUNICATION_CODE_10; // 不能解锁
+ return TRUE;
+ }
+ }
+ }
+ hart_device_attribute.flash_variable.lock_code = req->data.command_71.lock_code;
+ }
+ else
+ {
+ if (req->master == 0 && req->data.command_71.lock_code != LOCK_DEVICE_CODE_3)
+ {
+ // 第二主机 不能锁定
+ resp->code = RESPONSE_COMMUNICATION_CODE_11;
+ return TRUE;
+ }
+
+ hart_device_attribute.flash_variable.lock_code = req->data.command_71.lock_code;
+ }
+
+ // 更改锁定代码不会影响配置更改计数器或配置更改位
+ // 回复数据
+ *resp->data_p++ = hart_device_attribute.flash_variable.lock_code;
+
+ return TRUE;
+}
+
+/**
+ * @brief 呼叫
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_72_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ uint8_t squawk_control_code = 0;
+ if (req->data_length < sizeof(hart_command_72_t))
+ {
+ squawk_control_code = SQUAWK_CONTROL_CODE_2;
+ }
+ else
+ {
+ squawk_control_code = req->data.command_72.squawk_control_code;
+ }
+
+ if (squawk_control_code == SQUAWK_CONTROL_CODE_0)
+ {
+ squawk_control(FALSE, 0);
+ }
+ else
+ {
+ if (squawk_control_code == SQUAWK_CONTROL_CODE_2)
+ {
+ squawk_control(TRUE, HART_SQUAWK_CONTROL_ONCE_TIME);
+ }
+ else if (squawk_control_code == SQUAWK_CONTROL_CODE_1)
+ {
+ squawk_control(TRUE, 0);
+ }
+ else
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_9;
+ return TRUE;
+ }
+ }
+ // 回复数据
+ *resp->data_p++ = squawk_control_code;
+ return TRUE;
+}
+
+/**
+ * @brief 查找设备
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_73_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ if (TRUE == armed())
+ {
+ command_0_req(resp);
+ }
+ else
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_38;
+ return TRUE;
+ }
+
+ return TRUE;
+}
+
+/**
+ * @brief 读取I/O系统功能
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_74_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ resp->code = RESPONSE_COMMUNICATION_CODE_16;
+ return TRUE;
+}
+
+/**
+ * @brief 轮询子设备
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_75_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ resp->code = RESPONSE_COMMUNICATION_CODE_16;
+ return TRUE;
+}
+
+/**
+ * @brief 读锁定设备状态
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_76_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ *resp->data_p++ = hart_device_attribute.flash_variable.lock_code;
+ return TRUE;
+}
+
+
+/**
+ * @brief 写入设备变量
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_79_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ hart_device_variable_t *hart_device_variable_p = NULL;
+ float32_u tmp;
+ if (req->data_length < sizeof(hart_command_79_t))
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_5;
+ return TRUE;
+ }
+ hart_device_variable_p = get_device_variable(req->data.command_79.device_ariable);
+ if (hart_device_variable_p->code == DIN_250)
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_11; // 无效的设备变量代码
+ return TRUE;
+ }
+ hart_device_variable_p->write_device_variable_command_code = req->data.command_79.device_ariable_command_code;
+ hart_device_variable_p->units_code = req->data.command_79.device_ariable_unit_code;
+ tmp.f = req->data.command_79.device_ariable_value;
+ tmp.c = B2S_UINT32(tmp.c);
+ osel_memcpy((uint8_t *)hart_device_variable_p->value, (uint8_t *)&tmp.f, sizeof(float32));
+ hart_device_variable_p->status.data = req->data.command_79.status;
+ hart_device_status_set_operational_state(DEVICE_OPERATIONAL_STATE_7);
+
+ // 回复数据
+ *resp->data_p++ = hart_device_variable_p->code;
+ *resp->data_p++ = hart_device_variable_p->write_device_variable_command_code;
+ *resp->data_p++ = hart_device_variable_p->units_code;
+ osel_memcpy((uint8_t *)&tmp.f, (uint8_t *)hart_device_variable_p->value, sizeof(float32));
+ tmp.c = B2S_UINT32(tmp.c);
+ osel_memcpy(resp->data_p, (uint8_t *)&tmp.c, sizeof(int32_t));
+ resp->data_p += sizeof(int32_t);
+ *resp->data_p++ = hart_device_variable_p->status.data;
+ return TRUE;
+}
+
+/**
+ * @brief 读取设备可变微调点
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_80_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ hart_device_variable_t *hart_device_variable_p = NULL;
+ float32_u tmp;
+ if (req->data_length < sizeof(hart_command_80_t))
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_5;
+ return TRUE;
+ }
+ hart_device_variable_p = get_device_variable(req->data.command_80.device_ariable);
+ if (hart_device_variable_p->code == DIN_250)
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_11; // 无效的设备变量代码
+ return TRUE;
+ }
+ // 回复数据
+ *resp->data_p++ = hart_device_variable_p->code;
+ *resp->data_p++ = hart_device_variable_p->trim_point.units_code;
+
+ tmp.f = hart_device_variable_p->trim_point.lower;
+ tmp.c = B2S_UINT32(tmp.c);
+ osel_memcpy(resp->data_p, (uint8_t *)&tmp.c, sizeof(int32_t));
+ resp->data_p += sizeof(int32_t);
+
+ tmp.f = hart_device_variable_p->trim_point.upper;
+ tmp.c = B2S_UINT32(tmp.c);
+ osel_memcpy(resp->data_p, (uint8_t *)&tmp.c, sizeof(int32_t));
+ resp->data_p += sizeof(int32_t);
+ return TRUE;
+}
+
+/**
+ * @brief 读取设备变量调整指南
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_81_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ float32_u tmp;
+ hart_device_variable_t *variable = NULL;
+ variable = get_device_variable(req->data.command_81.device_ariable);
+ if (variable->code == DIN_250)
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_6;
+ return TRUE;
+ }
+
+ // 回复数据
+ *resp->data_p++ = variable->code;
+ *resp->data_p++ = variable->trim_point.trim_points;
+ *resp->data_p++ = variable->trim_point.units_code;
+
+ tmp.f = variable->trim_point.mini_lower;
+ tmp.c = B2S_UINT32(tmp.c);
+ osel_memcpy(resp->data_p, (uint8_t *)&tmp.c, sizeof(int32_t));
+ resp->data_p += sizeof(int32_t);
+
+ tmp.f = variable->trim_point.max_lower;
+ tmp.c = B2S_UINT32(tmp.c);
+ osel_memcpy(resp->data_p, (uint8_t *)&tmp.c, sizeof(int32_t));
+ resp->data_p += sizeof(int32_t);
+
+ tmp.f = variable->trim_point.mini_upper;
+ tmp.c = B2S_UINT32(tmp.c);
+ osel_memcpy(resp->data_p, (uint8_t *)&tmp.c, sizeof(int32_t));
+ resp->data_p += sizeof(int32_t);
+
+ tmp.f = variable->trim_point.max_upper;
+ tmp.c = B2S_UINT32(tmp.c);
+ osel_memcpy(resp->data_p, (uint8_t *)&tmp.c, sizeof(int32_t));
+ resp->data_p += sizeof(int32_t);
+
+ tmp.f = variable->trim_point.mini_differential;
+ tmp.c = B2S_UINT32(tmp.c);
+ osel_memcpy(resp->data_p, (uint8_t *)&tmp.c, sizeof(int32_t));
+ resp->data_p += sizeof(int32_t);
+ return TRUE;
+}
+
+/**
+ * @brief 写入设备可变微调点
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_82_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ float32_u tmp;
+ hart_device_variable_t *variable = NULL;
+ if (req->data_length < sizeof(hart_command_82_t))
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_5;
+ return TRUE;
+ }
+ variable = get_device_variable(req->data.command_82.device_ariable);
+ if (variable->code == DIN_250)
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_6;
+ return TRUE;
+ }
+ variable->trim_point.trim_points = req->data.command_82.trim_points;
+ variable->trim_point.units_code = req->data.command_82.units_code;
+ tmp.f = req->data.command_82.value;
+ tmp.c = B2S_UINT32(tmp.c);
+ variable->trim_point.value = tmp.f;
+
+ // 回复数据
+ *resp->data_p++ = variable->code;
+ *resp->data_p++ = variable->trim_point.trim_points;
+ *resp->data_p++ = variable->trim_point.units_code;
+ tmp.f = variable->trim_point.value;
+ tmp.c = B2S_UINT32(tmp.c);
+ osel_memcpy(resp->data_p, (uint8_t *)&tmp.c, sizeof(int32_t));
+ resp->data_p += sizeof(int32_t);
+ return TRUE;
+}
+
+/**
+ * @brief 重置设备变量调整
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_83_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ hart_device_variable_t *variable = NULL;
+ trim_point_t *ptr;
+ if (req->data_length < sizeof(hart_command_83_t))
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_5;
+ return TRUE;
+ }
+ variable = get_device_variable(req->data.command_83.device_ariable);
+ if (variable->code == DIN_250)
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_6;
+ return TRUE;
+ }
+ ptr = &variable->trim_point;
+ osel_memset((uint8_t *)ptr, 0, sizeof(trim_point_t));
+
+ // 回复数据
+ *resp->data_p++ = variable->code;
+ return TRUE;
+}
+
+/**
+ * @brief 读取子设备标识摘要
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_84_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ resp->code = RESPONSE_COMMUNICATION_CODE_16;
+ return TRUE;
+}
+
+/**
+ * @brief 读取I/O通道统计信息
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_85_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ resp->code = RESPONSE_COMMUNICATION_CODE_16;
+ return TRUE;
+}
+
+/**
+ * @brief 读取子设备统计信息
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_86_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ resp->code = RESPONSE_COMMUNICATION_CODE_16;
+ return TRUE;
+}
+
+/**
+ * @brief 写入I/O系统主模式
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_87_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ resp->code = RESPONSE_COMMUNICATION_CODE_16;
+ return TRUE;
+}
+
+/**
+ * @brief 写入I/O系统重试计数
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_88_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ resp->code = RESPONSE_COMMUNICATION_CODE_16;
+ return TRUE;
+}
+
+
+/**
+ * @brief 设置实时时钟
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_89_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ uint32_t time;
+ uint8_t year, month, day, hour, min, sec;
+ real_time_clock_t *pd = &hart_device_attribute.real_time_clock;
+ if (req->data_length < sizeof(hart_command_89_t))
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_5;
+ return TRUE;
+ }
+ if (req->data.command_89.time_set_code >= TIME_SETTING_CODE_MAX)
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_2;
+ return TRUE;
+ }
+
+ pd->time_set_code = req->data.command_89.time_set_code;
+ osel_memcpy(pd->date, req->data.command_89.date, HART_DATE_LEN);
+ time = B2S_UINT32(req->data.command_89.time);
+ pd->time = time;
+ pd->transmission_time = req->data.command_89.transmission_time;
+
+ hart_device_status_set_operational_state(DEVICE_OPERATIONAL_STATE_7);
+
+ year = pd->date[2];
+ covert_year_rtc(&year);
+ year = dec_format_hex(year);
+ month = dec_format_hex(pd->date[1]);
+ day = dec_format_hex(pd->date[0]);
+
+ convert_time(time, &hour, &min, &sec);
+ hart_set_real_time_clock(year, month, day, hour, min, sec);
+ pd->rtc_flags = REAL_TIME_CLOCK_FLAGS_1;
+
+ // LOG_PRINT("%d,%d,%d", hour, min, sec);
+ // 回复数据
+
+ *resp->data_p++ = pd->time_set_code;
+ osel_memcpy(resp->data_p, pd->date, HART_DATE_LEN);
+ resp->data_p += HART_DATE_LEN;
+ time = pd->time;
+ time = S2B_UINT32(time);
+ osel_memcpy(resp->data_p, (uint8_t *)&time, sizeof(uint32_t));
+ resp->data_p += sizeof(uint32_t);
+
+ return TRUE;
+}
+
+/**
+ * @brief 读取实时时钟
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_90_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ real_time_clock_t *pd = &hart_device_attribute.real_time_clock;
+ uint8_t year, month, day, hour, min, sec;
+ uint32_t time;
+ hart_get_real_time_clock(&year, &month, &day, &hour, &min, &sec);
+ convert_timestrap(&time, hour, min, sec, 0);
+ time = hart_get_timestamp();
+ // 当前日期
+ *resp->data_p++ = day;
+ *resp->data_p++ = month;
+ *resp->data_p++ = year > 0 ? (year + 100) : 0;
+ // 当前时间
+ time = S2B_UINT32(time);
+ osel_memcpy(resp->data_p, (uint8_t *)&time, sizeof(uint32_t));
+ resp->data_p += sizeof(uint32_t);
+
+ // 上一次设置的日期
+ osel_memcpy(resp->data_p, pd->date, HART_DATE_LEN);
+ resp->data_p += HART_DATE_LEN;
+ // 上一次设置的时间
+ time = pd->time;
+ time = S2B_UINT32(time);
+ osel_memcpy(resp->data_p, (uint8_t *)&time, sizeof(uint32_t));
+ resp->data_p += sizeof(uint32_t);
+ // RTC标志
+ *resp->data_p++ = pd->rtc_flags;
+
+ return TRUE;
+}
+
+/**
+ * @brief 读取趋势配置
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_91_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ uint32_t time = 0;
+ if (req->data_length < sizeof(hart_command_91_t))
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_5;
+ return TRUE;
+ }
+ if (req->data.command_91.trend_number > TREND_CONFIGURATIONS_LEN)
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_11;
+ return TRUE;
+ }
+
+ trend_configuration_t *cnf = &hart_device_attribute.flash_variable.trend_configurations[req->data.command_91.trend_number];
+ // 回复数据
+ *resp->data_p++ = req->data.command_91.trend_number;
+ *resp->data_p++ = TREND_CONFIGURATIONS_LEN;
+ *resp->data_p++ = cnf->trend_code;
+ *resp->data_p++ = cnf->device_variable_code;
+ time = cnf->trend_sample_interval;
+ time = B2S_UINT32(time);
+ osel_memcpy(resp->data_p, (uint8_t *)&time, sizeof(uint32_t));
+ resp->data_p += sizeof(uint32_t);
+ return TRUE;
+}
+
+/**
+ * @brief 写入趋势配置
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_92_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ uint32_t time = 0;
+ if (req->data_length < sizeof(hart_command_92_t))
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_5;
+ return TRUE;
+ }
+ if (req->data.command_92.trend_code >= TREND_CONTROL_CODE_MAX)
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_2;
+ return TRUE;
+ }
+ if (req->data.command_92.trend_number > TREND_CONFIGURATIONS_LEN)
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_11;
+ return TRUE;
+ }
+ time = S2B_UINT32(req->data.command_92.trend_sample_interval);
+ if (time > 2 * 3600 * 1000)
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_3;
+ return TRUE;
+ }
+
+ trend_configuration_t *cnf = &hart_device_attribute.flash_variable.trend_configurations[req->data.command_92.trend_number];
+ cnf->trend_code = req->data.command_92.trend_code;
+ cnf->device_variable_code = req->data.command_92.device_variable_code;
+ cnf->trend_sample_interval = time;
+
+ hart_device_status_set_operational_state(DEVICE_OPERATIONAL_STATE_7);
+
+ // 回复数据
+ *resp->data_p++ = req->data.command_92.trend_number;
+ *resp->data_p++ = cnf->trend_code;
+ *resp->data_p++ = cnf->device_variable_code;
+ time = cnf->trend_sample_interval;
+ time = B2S_UINT32(time);
+ osel_memcpy(resp->data_p, (uint8_t *)&time, sizeof(uint32_t));
+ resp->data_p += sizeof(uint32_t);
+ return TRUE;
+}
+
+/**
+ * @brief 读取趋势
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_93_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ uint32_t time = 0;
+ trend_value_t *value = NULL;
+ float32_u tmp;
+ if (req->data_length < sizeof(hart_command_93_t))
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_5;
+ return TRUE;
+ }
+ if (req->data.command_93.trend_number > TREND_CONFIGURATIONS_LEN)
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_11;
+ return TRUE;
+ }
+ trend_configuration_t *cnf = &hart_device_attribute.flash_variable.trend_configurations[req->data.command_93.trend_number];
+ // 回复数据
+ // 趋势编号
+ *resp->data_p++ = req->data.command_93.trend_number;
+ // 设备变量代码
+ *resp->data_p++ = cnf->device_variable_code;
+ // 设备变量分类
+ *resp->data_p++ = cnf->device_variable_classification;
+ // 设备变量单位代码
+ *resp->data_p++ = cnf->device_variable_unit_code;
+ // 趋势值的日期戳
+ osel_memcpy(resp->data_p, cnf->trend_value_date, HART_DATE_LEN);
+ resp->data_p += HART_DATE_LEN;
+ // 趋势值的时间戳
+ time = cnf->trend_value_time;
+ time = S2B_UINT32(time);
+ osel_memcpy(resp->data_p, (uint8_t *)&time, sizeof(uint32_t));
+ resp->data_p += sizeof(uint32_t);
+ // 采样间隔
+ time = cnf->trend_sample_interval;
+ time = S2B_UINT32(time);
+ osel_memcpy(resp->data_p, (uint8_t *)&time, sizeof(uint32_t));
+ resp->data_p += sizeof(uint32_t);
+
+ // 趋势值
+ if (cnf->trend_code == TREND_CONTROL_CODE_0)
+ {
+ // 当趋势未启用时,设备应返回最后收集的数据与相应的日期和时间,响应代码应设置为趋势不活跃
+ resp->code = RESPONSE_COMMUNICATION_CODE_8;
+ }
+ else
+ {
+ for (uint8_t i = 0; i < TREND_VALUES_LEN; i++)
+ {
+ value = &cnf->trend_values[i];
+ tmp.f = value->value;
+ tmp.c = S2B_UINT32(tmp.c);
+ osel_memcpy(resp->data_p, (uint8_t *)&tmp.c, sizeof(int32_t));
+ resp->data_p += sizeof(int32_t);
+ *resp->data_p++ = value->status.data;
+ }
+ }
+
+ return TRUE;
+}
+
+/**
+ * @brief 读取I/O系统客户端通信统计信息
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_94_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ resp->code = RESPONSE_COMMUNICATION_CODE_16;
+ return TRUE;
+}
+
+/**
+ * @brief 读取设备通信统计信息
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_95_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ *resp->data_p++ = HI_UINT16(hart_device_attribute.message_count.stx);
+ *resp->data_p++ = LO_UINT16(hart_device_attribute.message_count.stx);
+ *resp->data_p++ = HI_UINT16(hart_device_attribute.message_count.ack);
+ *resp->data_p++ = LO_UINT16(hart_device_attribute.message_count.ack);
+ *resp->data_p++ = HI_UINT16(hart_device_attribute.message_count.back);
+ *resp->data_p++ = LO_UINT16(hart_device_attribute.message_count.back);
+ return TRUE;
+}
+
+/**
+ * @brief 读取同步操作
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_96_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ uint32_t time = 0;
+ if (req->data_length < sizeof(hart_command_96_t))
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_5;
+ return TRUE;
+ }
+ if (req->data.command_96.action_number > SYNCHRONIZATION_OPERATION_LEN)
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_11;
+ return TRUE;
+ }
+ synchronization_operation_t *tmp = &hart_device_attribute.flash_variable.synchronization_operations[req->data.command_96.action_number];
+ // 回复数据
+ *resp->data_p++ = req->data.command_96.action_number; // 同步操作编号
+ *resp->data_p++ = SYNCHRONIZATION_OPERATION_LEN; // 同步操作总数
+
+ *resp->data_p++ = tmp->action_control_code; // 同步操作控制代码
+ if (tmp->action_control_code == 0)
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_2;
+ // 未使用的
+ *resp->data_p++ = DIN_251; // 同步操作设备变量代码
+ *resp->data_p++ = 0xff; // 同步操作命令编号
+ *resp->data_p++ = 0xff;
+ }
+ else
+ {
+ *resp->data_p++ = tmp->device_variable_code; // 同步操作设备变量代码
+ *resp->data_p++ = HI_UINT16(tmp->command_number); // 同步操作命令编号
+ *resp->data_p++ = LO_UINT16(tmp->command_number);
+ }
+
+ osel_memcpy(resp->data_p, tmp->trigger_date, HART_DATE_LEN); // 同步操作日期
+ resp->data_p += HART_DATE_LEN;
+ time = tmp->trigger_time; // 同步操作时间
+ time = S2B_UINT32(time);
+ osel_memcpy(resp->data_p, (uint8_t *)&time, sizeof(uint32_t));
+ resp->data_p += sizeof(uint32_t);
+ return TRUE;
+}
+
+/**
+ * @brief 配置同步操作
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_97_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ uint32_t time = 0;
+ /**
+ * 0 Success No Command-Specific Errors
+ 1 Undefined
+ 2 Error Invalid Selection
+ 3-4 Undefined
+ 5 Error Too Few Data Bytes Received
+ 6 Error Device-Specific Command Error
+ 7 Error In Write Protect Mode
+ 8 Warning Sampling Time Adjusted
+ 9 Error Bad Trigger Action
+ 10 Error Invalid Date
+ 11 Error Invalid Time
+ 12 Error Invalid Device Variable
+ 13 Error Command Number Not Supported
+ 14-15 Undefined
+ */
+ if (req->data_length < sizeof(hart_command_97_t))
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_5;
+ return TRUE;
+ }
+ if (req->data.command_97.action_number > SYNCHRONIZATION_OPERATION_LEN)
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_9;
+ return TRUE;
+ }
+ synchronization_operation_t *tmp = &hart_device_attribute.flash_variable.synchronization_operations[req->data.command_97.action_number];
+ tmp->action_control_code = req->data.command_97.action_control_code; // 同步操作控制代码
+
+ // 设备变量代码。如果动作执行命令,设备变量代码必须设置为251。“NONE”。
+ if (tmp->action_control_code == SYNCHRONIZATION_OPERATION_CONTROL_CODE_1)
+ {
+ tmp->device_variable_code = req->data.command_97.device_variable_code; // 同步操作设备变量代码
+ }
+ else
+ {
+ tmp->device_variable_code = DIN_251;
+ }
+
+ // 命令编号。如果操作是对设备变量进行采样,则命令编号必须设置为0xFFFF。
+ if (tmp->action_control_code == SYNCHRONIZATION_OPERATION_CONTROL_CODE_1)
+ {
+ tmp->command_number = 0xffff;
+ }
+ else
+ {
+
+ tmp->command_number = S2B_UINT16(req->data.command_97.command_number); // 同步操作命令编号
+ }
+
+ osel_memcpy(tmp->trigger_date, req->data.command_97.trigger_date, HART_DATE_LEN);
+ time = S2B_UINT32(req->data.command_97.trigger_time); // 同步操作时间
+ tmp->trigger_time = time;
+
+ hart_device_status_set_operational_state(DEVICE_OPERATIONAL_STATE_7);
+
+ // 回复数据
+ *resp->data_p++ = req->data.command_97.action_number; // 同步操作编号
+ *resp->data_p++ = tmp->action_control_code; // 同步操作控制代码
+ *resp->data_p++ = tmp->device_variable_code; // 同步操作设备变量代码
+ *resp->data_p++ = HI_UINT16(tmp->command_number); // 同步操作命令编号
+ *resp->data_p++ = LO_UINT16(tmp->command_number);
+ osel_memcpy(resp->data_p, tmp->trigger_date, HART_DATE_LEN); // 同步操作日期
+ resp->data_p += HART_DATE_LEN;
+ time = tmp->trigger_time; // 同步操作时间
+ time = S2B_UINT32(time);
+ osel_memcpy(resp->data_p, (uint8_t *)&time, sizeof(uint32_t));
+ resp->data_p += sizeof(uint32_t);
+ return TRUE;
+}
+
+/**
+ * @brief 读取命令操作
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_98_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ if (req->data_length < sizeof(hart_command_98_t))
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_5;
+ return TRUE;
+ }
+ if (req->data.command_98.action_number > SYNCHRONIZATION_OPERATION_LEN)
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_11;
+ return TRUE;
+ }
+ synchronization_operation_t *tmp = &hart_device_attribute.flash_variable.synchronization_operations[req->data.command_98.action_number];
+ // 回复数据
+ *resp->data_p++ = req->data.command_98.action_number; // 同步操作编号
+ *resp->data_p++ = HI_UINT16(tmp->command_number); // 同步操作命令编号
+ *resp->data_p++ = LO_UINT16(tmp->command_number);
+ *resp->data_p++ = tmp->command_data_length; // 字节计数
+ osel_memcpy(resp->data_p, tmp->command_data, tmp->command_data_length); // 命令数据
+ resp->data_p += tmp->command_data_length;
+ return TRUE;
+}
+
+/**
+ * @brief 配置命令操作
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_99_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ if (req->data_length < (4 + req->data.command_99.command_data_length))
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_5;
+ return TRUE;
+ }
+ if (req->data.command_99.action_number > SYNCHRONIZATION_OPERATION_LEN)
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_11;
+ return TRUE;
+ }
+ if (req->data.command_99.command_data_length > SYNCHRONIZATION_OPERATION_COMMAND_DATA_LEN)
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_10;
+ return TRUE;
+ }
+
+ synchronization_operation_t *tmp = &hart_device_attribute.flash_variable.synchronization_operations[req->data.command_99.action_number];
+ tmp->command_number = req->data.command_99.command_number;
+ tmp->command_data_length = req->data.command_99.command_data_length;
+ osel_memcpy(tmp->command_data, req->data.command_99.command_data, tmp->command_data_length);
+ hart_device_status_set_operational_state(DEVICE_OPERATIONAL_STATE_7);
+
+ // 回复数据
+ *resp->data_p++ = req->data.command_99.action_number; // 同步操作编号
+ *resp->data_p++ = HI_UINT16(tmp->command_number); // 同步操作命令编号
+ *resp->data_p++ = LO_UINT16(tmp->command_number);
+ *resp->data_p++ = tmp->command_data_length; // 字节计数
+ osel_memcpy(resp->data_p, tmp->command_data, tmp->command_data_length); // 命令数据
+ resp->data_p += tmp->command_data_length;
+ return TRUE;
+}
+
+
+/**
+ * @brief 写入主变量报警码
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_100_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ if (req->data_length < sizeof(hart_command_100_t))
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_5;
+ return TRUE;
+ }
+ hart_device_variable_t *variable = NULL;
+ variable = get_device_variable_by_standard_code(DIN_246);
+ if (variable->code == DIN_250)
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_6;
+ return TRUE;
+ }
+ variable->alarm_code = req->data.command_100.pv_alarm_selection_code;
+ hart_device_status_set_operational_state(DEVICE_OPERATIONAL_STATE_7);
+ // 回复数据
+ *resp->data_p++ = variable->alarm_code;
+ return TRUE;
+}
+
+
+/**
+ * @brief 读取子设备到突发消息映射
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_101_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ resp->code = RESPONSE_COMMUNICATION_CODE_16;
+ return TRUE;
+}
+/**
+ * @brief 将子设备映射到突发信息
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_102_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ resp->code = RESPONSE_COMMUNICATION_CODE_16;
+ return TRUE;
+}
+
+/**
+ * @brief 读取突发模式配置
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_105_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ uint32_t time;
+ float32_u f;
+ hart_device_variable_t *solt;
+ if (req->data.command_105.burst_message > BURST_MESSAGE_LEN)
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_9;
+ return TRUE;
+ }
+ burst_message_t *tmp = &hart_device_attribute.flash_variable.burst_messages[req->data.command_105.burst_message];
+
+ *resp->data_p++ = tmp->burst_mode_control_code; // 突发模式控制代码
+ *resp->data_p++ = tmp->command_number_expansion_flag; // 命令编号扩展标志
+ for (uint8_t i = 0; i < HART_DEVICE_VARIABLE_LEN; i++)
+ {
+ solt = &hart_device_attribute.device_variable[i];
+ *resp->data_p++ = solt->code; // 设备变量代码
+ }
+ *resp->data_p++ = req->data.command_105.burst_message; // 突发消息编号
+ *resp->data_p++ = BURST_MESSAGE_LEN; // 设备支持的最大突发消息数
+ *resp->data_p++ = HI_UINT16(tmp->extended_command_number); // 扩展命令编号
+ *resp->data_p++ = LO_UINT16(tmp->extended_command_number); // 扩展命令编号
+ time = S2B_UINT32(tmp->update_period_time); // 更新周期时间
+ osel_memcpy(resp->data_p, (uint8_t *)&time, sizeof(uint32_t));
+ resp->data_p += sizeof(uint32_t);
+ time = S2B_UINT32(tmp->max_update_period_time); // 最大更新周期时间
+ osel_memcpy(resp->data_p, (uint8_t *)&time, sizeof(uint32_t));
+ resp->data_p += sizeof(uint32_t);
+ *resp->data_p++ = tmp->burst_message_trigger_code; // 突发触发器代码
+ *resp->data_p++ = tmp->device_variable_vlassification_for_trigger_level; // 触发器级别的设备变量分类
+ *resp->data_p++ = tmp->units_code; // 突发触发器单位代码
+ f.f = tmp->trigger_level; // 触发电平
+ f.c = S2B_UINT32(f.c);
+ osel_memcpy(resp->data_p, (uint8_t *)&f, sizeof(float32_u));
+ resp->data_p += sizeof(float32_u);
+ return TRUE;
+}
+
+
+
+/**
+ * @brief注册事件管理器
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_514_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ if (req->data_length < sizeof(hart_command_514_t))
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_5;
+ return TRUE;
+ }
+ if (req->data.command_514.event_manager_registration_control_code == EVENT_MANAGER_REGISTRATION_CONTROL_CODE_0 &&
+ hart_device_attribute.flash_variable.event_manager_registration_control_code == EVENT_MANAGER_REGISTRATION_CONTROL_CODE_0)
+ {
+ // Access Restricted (e.g., an Event Manager is already registered)
+ resp->code = RESPONSE_COMMUNICATION_CODE_16;
+ return TRUE;
+ }
+ hart_device_attribute.flash_variable.event_manager_registration_control_code = req->data.command_514.event_manager_registration_control_code;
+ hart_device_status_set_operational_state(DEVICE_OPERATIONAL_STATE_7);
+ // 回复数据
+ *resp->data_p++ = hart_device_attribute.flash_variable.event_manager_registration_control_code;
+
+ return TRUE;
+}
+/**
+ * @brief读取事件管理器注册状态
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_515_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ // 回复数据
+ *resp->data_p++ = hart_device_attribute.flash_variable.event_manager_registration_control_code;
+ return TRUE;
+}
+
+
+/**
+ * @brief读取进程单元标签
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_520_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ return TRUE;
+}
+/**
+ * @brief写入进程单元标记
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_521_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ return TRUE;
+}
+/**
+ * @brief写入进程单元标记
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_522_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ return TRUE;
+}
+
+/**
+ * @brief重置精简状态图
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_525_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ return TRUE;
+}
+/**
+ * @brief写入状态模拟模式
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_526_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ return TRUE;
+}
+/**
+ * @brief模拟状态位
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_527_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ return TRUE;
+}
+/**
+ * @brief读取子设备分配列表信息
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_528_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ return TRUE;
+}
+/**
+ * @brief读取子设备分配
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_529_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ return TRUE;
+}
+/**
+ * @brief写入子设备分配
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_530_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ return TRUE;
+}
+/**
+ * @brief将实时列表传输到分配列表
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_531_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ return TRUE;
+}
+/**
+ * @brief读取客户端订阅摘要
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_532_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ return TRUE;
+}
+/**
+ * @brief写入客户端订阅标志
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_533_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ return TRUE;
+}
+
+
+/**
+ * @brief 读取设备变量命令代码
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_534_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ return TRUE;
+}
+
+/**
+ * @brief写入模拟通道端点值
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_535_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ return TRUE;
+}
+/**
+ * @brief写入应用时间操作
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_536_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ return TRUE;
+}
+/**
+ * @brief读取应用时间操作
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_537_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ return TRUE;
+}
+/**
+ * @brief读取HART-IP服务器端口
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_538_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ return TRUE;
+}
+/**
+ * @brief写入HART-IP UDP端口
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_539_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ return TRUE;
+}
+/**
+ * @brief写入HART-IP TCP端口
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_540_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ return TRUE;
+}
+/**
+ * @brief写入客户端PAKE密码
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_541_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ return TRUE;
+}
+/**
+ * @brief写入客户端预共享密钥
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_542_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ return TRUE;
+}
+/**
+ * @brief读取系统日志服务器主机名和端口
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_543_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ return TRUE;
+}
+/**
+ * @brief写入系统日志端口
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_544_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ return TRUE;
+}
+/**
+ * @brief写入系统日志服务器主机名
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_545_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ return TRUE;
+}
+/**
+ * @brief写入系统日志服务器预共享密钥
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_546_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ return TRUE;
+}
+/**
+ * @brief写入系统日志服务器PAKE密码
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_547_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ return TRUE;
+}
+#endif
+
+// /**
+// * @brief 向子设备发送命令
+// * @param {hart_command_req_t} *req
+// * @param {hart_response_t} *resp
+// * @return {*}
+// */
+// static BOOL hart_slave_command_77_req(const hart_command_req_t *const req, hart_response_t *resp)
+// {
+// resp->code = RESPONSE_COMMUNICATION_CODE_16;
+// return TRUE;
+// }
+
+// /**
+// * @brief 读取聚合命令
+// * @param {hart_command_req_t} *req
+// * @param {hart_response_t} *resp
+// * @return {*}
+// */
+// static BOOL hart_slave_command_78_req(const hart_command_req_t *const req, hart_response_t *resp)
+// {
+// resp->code = RESPONSE_COMMUNICATION_CODE_16;
+// return TRUE;
+// }
+
+/**
+ * @brief 写入突发周期
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_103_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ uint32_t time1, time2;
+ if (req->data_length < sizeof(hart_command_103_t))
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_5;
+ return TRUE;
+ }
+ if (req->data.command_103.burst_message > BURST_MESSAGE_LEN)
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_9;
+ return TRUE;
+ }
+ burst_message_t *tmp = &hart_device_attribute.flash_variable.burst_messages[req->data.command_103.burst_message];
+
+ // 校验更新时间
+ time1 = B2S_UINT32(req->data.command_103.update_period_time);
+ time1 = time1 / 32;
+ if (time1 > BURST_MESSAGE_UPDATE_TIME_MAX * 1000)
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_9;
+ return TRUE;
+ }
+ time2 = B2S_UINT32(req->data.command_103.max_update_period_time);
+ time2 = time2 / 32;
+ if (time2 > BURST_MESSAGE_UPDATE_TIME_MAX * 1000)
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_9;
+ return TRUE;
+ }
+
+ tmp->update_period_time = time1;
+ tmp->max_update_period_time = time2;
+
+ hart_device_status_set_operational_state(DEVICE_OPERATIONAL_STATE_7);
+
+ // 回复数据
+ *resp->data_p++ = req->data.command_103.burst_message; // 突发消息编号
+ time1 = S2B_UINT32(tmp->update_period_time * 32);
+ osel_memcpy(resp->data_p, (uint8_t *)&time1, sizeof(uint32_t)); // 更新周期时间
+ resp->data_p += sizeof(uint32_t);
+ time2 = S2B_UINT32(tmp->max_update_period_time * 32);
+ osel_memcpy(resp->data_p, (uint8_t *)&time2, sizeof(uint32_t)); // 最大更新周期时间
+ resp->data_p += sizeof(uint32_t);
+
+ return TRUE;
+}
+
+/**
+ * @brief 写入突发触发器
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_104_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ float32_u f;
+ if (req->data_length < sizeof(hart_command_104_t))
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_5;
+ return TRUE;
+ }
+ if (req->data.command_104.burst_message > BURST_MESSAGE_LEN)
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_9;
+ return TRUE;
+ }
+ f.f = req->data.command_104.trigger_level;
+ f.c = B2S_UINT32(f.c);
+ burst_message_t *tmp = &hart_device_attribute.flash_variable.burst_messages[req->data.command_104.burst_message];
+ tmp->burst_message_trigger_code = req->data.command_104.burst_message_trigger_code; // 突发触发器代码
+ tmp->device_variable_vlassification_for_trigger_level = req->data.command_104.device_variable_vlassification_for_trigger_level; // 触发器级别的设备变量分类
+ tmp->units_code = req->data.command_104.units_code; // 突发触发器单位代码
+ tmp->trigger_level = f.f; // 触发电平
+
+ hart_device_status_set_operational_state(DEVICE_OPERATIONAL_STATE_7);
+
+ // 回复数据
+ f.f = tmp->trigger_level;
+ f.c = S2B_UINT32(f.c);
+ *resp->data_p++ = req->data.command_104.burst_message; // 突发消息编号
+ *resp->data_p++ = tmp->burst_message_trigger_code; // 突发触发器代码
+ *resp->data_p++ = tmp->device_variable_vlassification_for_trigger_level; // 触发器级别的设备变量分类
+ *resp->data_p++ = tmp->units_code; // 突发触发器单位代码
+ osel_memcpy(resp->data_p, (uint8_t *)&f, sizeof(float32_u)); // 触发电平
+ resp->data_p += sizeof(float32_u);
+ return TRUE;
+}
+
+/**
+ * @brief 写入突发设备变量
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_107_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ burst_message_t *solt;
+ uint8_t count = HART_PACKED8_LEN;
+ if (req->data_length < sizeof(hart_command_107_t))
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_5;
+ return TRUE;
+ }
+
+ if (*hart_device_attribute.hart_protocol_version == HART_PROTOCOL_VERSION_7)
+ {
+ if (req->data_length != 9)
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_16;
+ return TRUE;
+ }
+ }
+ else if (*hart_device_attribute.hart_protocol_version == HART_PROTOCOL_VERSION_5)
+ {
+ if (req->data_length != 5)
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_16;
+ return TRUE;
+ }
+ count = HART_PACKED8_LEN >> 1; // 5版本只有4个设备变量
+ }
+
+ // 分配给插槽设备变量代码
+ for (uint8_t i = 0; i < count; i++)
+ {
+ solt = &hart_device_attribute.flash_variable.burst_messages[i];
+ solt->code = req->data.command_107.solt_device_variable_codes[i];
+ }
+
+ // 回复数据
+ for (uint8_t i = 0; i < count; i++)
+ {
+ solt = &hart_device_attribute.flash_variable.burst_messages[i];
+ *resp->data_p++ = solt->code;
+ }
+ *resp->data_p++ = req->data.command_107.burst_message; // 突发消息编号
+
+ hart_device_status_set_operational_state(DEVICE_OPERATIONAL_STATE_7);
+ return TRUE;
+}
+
+/**
+ * @brief 写入突发模式命令编号
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_108_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ resp->code = RESPONSE_COMMUNICATION_CODE_16;
+ return TRUE;
+}
+
+// /**
+// * @brief 刷新延迟响应
+// * @param {hart_command_req_t} *req
+// * @param {hart_response_t} *resp
+// * @return {*}
+// */
+// static BOOL hart_slave_command_106_req(const hart_command_req_t *const req, hart_response_t *resp)
+// {
+// resp->code = RESPONSE_COMMUNICATION_CODE_16;
+// return TRUE;
+// }
+
+// /**
+// * @brief 读取所有动态变量V5 (新设计不建议使用此命令)
+// * @param {hart_command_req_t} *req
+// * @param {hart_response_t} *resp
+// * @return {*}
+// */
+// static BOOL hart_slave_command_110_req(const hart_command_req_t *const req, hart_response_t *resp)
+// {
+// hart_device_variable_t *dv;
+// float32_u f;
+
+// dv = get_device_variable_by_standard_code(DIN_246); // 主变量
+// *resp->data_p++ = dv->code;
+// f.f = *dv->value;
+// f.c = S2B_UINT32(f.c);
+// osel_memcpy(resp->data_p, (uint8_t *)&f, sizeof(float32_u));
+// resp->data_p += sizeof(float32_u);
+
+// dv = get_device_variable_by_standard_code(DIN_247); // 第二变量
+// *resp->data_p++ = dv->code;
+// f.f = *dv->value;
+// f.c = S2B_UINT32(f.c);
+// osel_memcpy(resp->data_p, (uint8_t *)&f, sizeof(float32_u));
+// resp->data_p += sizeof(float32_u);
+
+// dv = get_device_variable_by_standard_code(DIN_248); // 第三变量
+// *resp->data_p++ = dv->code;
+// f.f = *dv->value;
+// f.c = S2B_UINT32(f.c);
+// osel_memcpy(resp->data_p, (uint8_t *)&f, sizeof(float32_u));
+// resp->data_p += sizeof(float32_u);
+
+// dv = get_device_variable_by_standard_code(DIN_249); // 第四变量
+// *resp->data_p++ = dv->code;
+// f.f = *dv->value;
+// f.c = S2B_UINT32(f.c);
+// osel_memcpy(resp->data_p, (uint8_t *)&f, sizeof(float32_u));
+// resp->data_p += sizeof(float32_u);
+// return TRUE;
+// }
+
+// /**
+// * @brief转移服务控制
+// * @param {hart_command_req_t} *req
+// * @param {hart_response_t} *resp
+// * @return {*}
+// */
+// static BOOL hart_slave_command_111_req(const hart_command_req_t *const req, hart_response_t *resp)
+// {
+// resp->code = RESPONSE_COMMUNICATION_CODE_16;
+// return TRUE;
+// }
+// /**
+// * @brief传输服务
+// * @param {hart_command_req_t} *req
+// * @param {hart_response_t} *resp
+// * @return {*}
+// */
+// static BOOL hart_slave_command_112_req(const hart_command_req_t *const req, hart_response_t *resp)
+// {
+// resp->code = RESPONSE_COMMUNICATION_CODE_16;
+// return TRUE;
+// }
+// /**
+// * @brief捕获设备变量
+// * @param {hart_command_req_t} *req
+// * @param {hart_response_t} *resp
+// * @return {*}
+// */
+// static BOOL hart_slave_command_113_req(const hart_command_req_t *const req, hart_response_t *resp)
+// {
+// resp->code = RESPONSE_COMMUNICATION_CODE_16;
+// return TRUE;
+// }
+// /**
+// * @brief读取捕获的设备变量
+// * @param {hart_command_req_t} *req
+// * @param {hart_response_t} *resp
+// * @return {*}
+// */
+// static BOOL hart_slave_command_114_req(const hart_command_req_t *const req, hart_response_t *resp)
+// {
+// resp->code = RESPONSE_COMMUNICATION_CODE_16;
+// return TRUE;
+// }
+// /**
+// * @brief读取事件通知摘要
+// * @param {hart_command_req_t} *req
+// * @param {hart_response_t} *resp
+// * @return {*}
+// */
+// static BOOL hart_slave_command_115_req(const hart_command_req_t *const req, hart_response_t *resp)
+// {
+// resp->code = RESPONSE_COMMUNICATION_CODE_16;
+// return TRUE;
+// }
+// /**
+// * @brief写入事件通知位掩码
+// * @param {hart_command_req_t} *req
+// * @param {hart_response_t} *resp
+// * @return {*}
+// */
+// static BOOL hart_slave_command_116_req(const hart_command_req_t *const req, hart_response_t *resp)
+// {
+// resp->code = RESPONSE_COMMUNICATION_CODE_16;
+// return TRUE;
+// }
+// /**
+// * @brief写入事件通知时序
+// * @param {hart_command_req_t} *req
+// * @param {hart_response_t} *resp
+// * @return {*}
+// */
+// static BOOL hart_slave_command_117_req(const hart_command_req_t *const req, hart_response_t *resp)
+// {
+// resp->code = RESPONSE_COMMUNICATION_CODE_16;
+// return TRUE;
+// }
+// /**
+// * @brief事件通知控制
+// * @param {hart_command_req_t} *req
+// * @param {hart_response_t} *resp
+// * @return {*}
+// */
+// static BOOL hart_slave_command_118_req(const hart_command_req_t *const req, hart_response_t *resp)
+// {
+// resp->code = RESPONSE_COMMUNICATION_CODE_16;
+// return TRUE;
+// }
+// /**
+// * @brief确认事件通知
+// * @param {hart_command_req_t} *req
+// * @param {hart_response_t} *resp
+// * @return {*}
+// */
+// static BOOL hart_slave_command_119_req(const hart_command_req_t *const req, hart_response_t *resp)
+// {
+// resp->code = RESPONSE_COMMUNICATION_CODE_16;
+// return TRUE;
+// }
+
+// /**
+// * @brief 读取国家代码
+// * @param {hart_command_req_t} *req
+// * @param {hart_response_t} *resp
+// * @return {*}
+// */
+// static BOOL hart_slave_command_512_req(const hart_command_req_t *const req, hart_response_t *resp)
+// {
+// *resp->data_p++ = HI_UINT16(hart_device_attribute.flash_variable.country_code);
+// *resp->data_p++ = LO_UINT16(hart_device_attribute.flash_variable.country_code);
+// *resp->data_p++ = hart_device_attribute.flash_variable.si_units_control_code;
+// return TRUE;
+// }
+
+// /**
+// * @brief 编写国家代码
+// * @param {hart_command_req_t} *req
+// * @param {hart_response_t} *resp
+// * @return {*}
+// */
+// static BOOL hart_slave_command_513_req(const hart_command_req_t *const req, hart_response_t *resp)
+// {
+// if (req->data_length < sizeof(hart_command_513_t))
+// {
+// resp->code = RESPONSE_COMMUNICATION_CODE_5;
+// return TRUE;
+// }
+// if (req->data.command_513.si_units_control_code >= SI_UNITS_CONTROL_CODE_MAX)
+// {
+// resp->code = RESPONSE_COMMUNICATION_CODE_8;
+// return TRUE;
+// }
+// hart_device_attribute.flash_variable.country_code = B2S_UINT16(req->data.command_513.country_code);
+// hart_device_attribute.flash_variable.si_units_control_code = req->data.command_513.si_units_control_code;
+// hart_device_status_set_operational_state(DEVICE_OPERATIONAL_STATE_7);
+// // 回复数据
+// *resp->data_p++ = HI_UINT16(hart_device_attribute.flash_variable.country_code);
+// *resp->data_p++ = LO_UINT16(hart_device_attribute.flash_variable.country_code);
+// *resp->data_p++ = hart_device_attribute.flash_variable.si_units_control_code;
+// return TRUE;
+// }
+
+// /**
+// * @brief读取设备位置
+// * @param {hart_command_req_t} *req
+// * @param {hart_response_t} *resp
+// * @return {*}
+// */
+// static BOOL hart_slave_command_516_req(const hart_command_req_t *const req, hart_response_t *resp)
+// {
+// return TRUE;
+// }
+// /**
+// * @brief写入设备位置
+// * @param {hart_command_req_t} *req
+// * @param {hart_response_t} *resp
+// * @return {*}
+// */
+// static BOOL hart_slave_command_517_req(const hart_command_req_t *const req, hart_response_t *resp)
+// {
+// return TRUE;
+// }
+// /**
+// * @brief读取位置说明
+// * @param {hart_command_req_t} *req
+// * @param {hart_response_t} *resp
+// * @return {*}
+// */
+// static BOOL hart_slave_command_518_req(const hart_command_req_t *const req, hart_response_t *resp)
+// {
+// return TRUE;
+// }
+// /**
+// * @brief写入位置说明
+// * @param {hart_command_req_t} *req
+// * @param {hart_response_t} *resp
+// * @return {*}
+// */
+// static BOOL hart_slave_command_519_req(const hart_command_req_t *const req, hart_response_t *resp)
+// {
+// return TRUE;
+// }
+
+/**
+ * @brief 初始化哈希表,用于注册从端发送给主端的命令的处理函数。
+ * @return 无
+ * @note 此函数通常在哈希表的初始化时调用,以设置默认的未定义命令。
+ */
+void hart_slave_req_init(void)
+{
+ for (uint16_t i = 0; i < HART_COMMAND_MAX; i++)
+ {
+ hart_command_ptr_arr[i] = hart_slave_command_undef_req; // 默认为未定义命令
+ }
+
+ // 通用命令 23条
+ hart_command_ptr_arr[HART_COMMAND_0] = hart_slave_command_0_req; // 读取唯一标识命令
+ hart_command_ptr_arr[HART_COMMAND_1] = hart_slave_command_1_req; // 读取主变量
+ hart_command_ptr_arr[HART_COMMAND_2] = hart_slave_command_2_req; // 读取主变量的回路电流和量程百分比
+ hart_command_ptr_arr[HART_COMMAND_3] = hart_slave_command_3_req; // 读取动态变量和回路电流
+ /*命令4和命令5设备不需要支持*/
+ hart_command_ptr_arr[HART_COMMAND_6] = hart_slave_command_6_req; // 写入轮训地址
+ hart_command_ptr_arr[HART_COMMAND_7] = hart_slave_command_7_req; // 读取循环配置
+ hart_command_ptr_arr[HART_COMMAND_8] = hart_slave_command_8_req; // 读取动态变量分类
+ hart_command_ptr_arr[HART_COMMAND_9] = hart_slave_command_9_req; // 读取具有状态的设备变量
+ hart_command_ptr_arr[HART_COMMAND_11] = hart_slave_command_11_req; // 读取与标签关联的唯一标识符
+ hart_command_ptr_arr[HART_COMMAND_12] = hart_slave_command_12_req; // 读取消息
+ hart_command_ptr_arr[HART_COMMAND_13] = hart_slave_command_13_req; // 读取标签、描述符、日期
+ hart_command_ptr_arr[HART_COMMAND_14] = hart_slave_command_14_req; // 读取主变量传感器信息
+ hart_command_ptr_arr[HART_COMMAND_15] = hart_slave_command_15_req; // 读取设备信息
+ hart_command_ptr_arr[HART_COMMAND_16] = hart_slave_command_16_req; // 读取最终总装编号
+ hart_command_ptr_arr[HART_COMMAND_17] = hart_slave_command_17_req; // 写入消息
+ hart_command_ptr_arr[HART_COMMAND_18] = hart_slave_command_18_req; // 写标签、描述符、日期
+ hart_command_ptr_arr[HART_COMMAND_19] = hart_slave_command_19_req; // 编写总装编号
+ hart_command_ptr_arr[HART_COMMAND_20] = hart_slave_command_20_req; // 读取长标签
+ hart_command_ptr_arr[HART_COMMAND_21] = hart_slave_command_21_req; // 读取与长标签关联的唯一标识符
+ hart_command_ptr_arr[HART_COMMAND_22] = hart_slave_command_22_req; // 写长标签
+ hart_command_ptr_arr[HART_COMMAND_31] = hart_slave_command_31_req; // 处理大号命令
+ hart_command_ptr_arr[HART_COMMAND_38] = hart_slave_command_38_req; // 重置配置更改标志
+ hart_command_ptr_arr[HART_COMMAND_48] = hart_slave_command_48_req; // 读取其他设备状态
+
+ // 常用命令
+ hart_command_ptr_arr[HART_COMMAND_33] = hart_slave_command_33_req; // 读取设备变量
+ hart_command_ptr_arr[HART_COMMAND_35] = hart_slave_command_35_req; // 写入主变量范围值
+ hart_command_ptr_arr[HART_COMMAND_42] = hart_slave_command_42_req; // 执行设备重置
+ hart_command_ptr_arr[HART_COMMAND_44] = hart_slave_command_44_req; // 编写主变量单元
+ hart_command_ptr_arr[HART_COMMAND_50] = hart_slave_command_50_req; // 读取动态变量赋值
+ hart_command_ptr_arr[HART_COMMAND_51] = hart_slave_command_51_req; // 编写动态变量赋值
+ hart_command_ptr_arr[HART_COMMAND_52] = hart_slave_command_52_req; // 设置设备变量零
+ hart_command_ptr_arr[HART_COMMAND_53] = hart_slave_command_53_req; // 写入设备变量单元
+ hart_command_ptr_arr[HART_COMMAND_54] = hart_slave_command_54_req; // 读取设备变量信息
+ hart_command_ptr_arr[HART_COMMAND_59] = hart_slave_command_59_req; // 写入设备变量单元
+
+ // hart_command_ptr_arr[HART_COMMAND_512] = hart_slave_command_512_req; // 读取国家代码
+ // hart_command_ptr_arr[HART_COMMAND_513] = hart_slave_command_513_req; // 编写国家代码
+ // hart_command_ptr_arr[HART_COMMAND_516] = hart_slave_command_516_req; // 读取设备位置
+ // hart_command_ptr_arr[HART_COMMAND_517] = hart_slave_command_517_req; // 写入设备位置
+ // hart_command_ptr_arr[HART_COMMAND_518] = hart_slave_command_518_req; // 读取位置说明
+ // hart_command_ptr_arr[HART_COMMAND_519] = hart_slave_command_519_req; // 写入位置说明
+
+ // hart_command_ptr_arr[HART_COMMAND_34] = hart_slave_command_34_req; // 写入主变量阻尼值
+ // hart_command_ptr_arr[HART_COMMAND_36] = hart_slave_command_36_req; // 设置主变量上限值
+ // hart_command_ptr_arr[HART_COMMAND_37] = hart_slave_command_37_req; // 设置主变量下限值
+ // hart_command_ptr_arr[HART_COMMAND_39] = hart_slave_command_39_req; // EEPROM控制
+ // hart_command_ptr_arr[HART_COMMAND_41] = hart_slave_command_41_req; // 执行自检
+ // hart_command_ptr_arr[HART_COMMAND_40] = hart_slave_command_40_req; // 进入/退出固定电流模式
+ // hart_command_ptr_arr[HART_COMMAND_43] = hart_slave_command_43_req; // 设置主变量零
+ // hart_command_ptr_arr[HART_COMMAND_45] = hart_slave_command_45_req; // 微调回路电流归零
+ // hart_command_ptr_arr[HART_COMMAND_46] = hart_slave_command_46_req; // 微调回路电流增益
+ // hart_command_ptr_arr[HART_COMMAND_47] = hart_slave_command_47_req; // 编写主变量传递函数
+ // hart_command_ptr_arr[HART_COMMAND_49] = hart_slave_command_49_req; // 写入主变量传感器序列号
+
+ // hart_command_ptr_arr[HART_COMMAND_55] = hart_slave_command_55_req; // 写入设备可变阻尼值
+ // hart_command_ptr_arr[HART_COMMAND_56] = hart_slave_command_56_req; // 写入设备可变传感器序列号
+ // hart_command_ptr_arr[HART_COMMAND_57] = hart_slave_command_57_req; // 读取单位标签、描述符、日期
+ // hart_command_ptr_arr[HART_COMMAND_58] = hart_slave_command_58_req; // 编写单位标签、描述符、日期
+ // hart_command_ptr_arr[HART_COMMAND_59] = hart_slave_command_59_req; // 写入响应序码数
+ // hart_command_ptr_arr[HART_COMMAND_60] = hart_slave_command_60_req; // 读取模拟通道和范围百分比
+ // hart_command_ptr_arr[HART_COMMAND_61] = hart_slave_command_61_req; // 读取动态变量和主变量模拟通道
+ // hart_command_ptr_arr[HART_COMMAND_62] = hart_slave_command_62_req; // 读取模拟通道
+ // hart_command_ptr_arr[HART_COMMAND_63] = hart_slave_command_63_req; // 读取模拟通道信息
+ // hart_command_ptr_arr[HART_COMMAND_64] = hart_slave_command_64_req; // 写入模拟通道附加阻尼值
+ // hart_command_ptr_arr[HART_COMMAND_65] = hart_slave_command_65_req; // 写入模拟通道范围值
+ // hart_command_ptr_arr[HART_COMMAND_66] = hart_slave_command_66_req; // 进入/退出固定模拟通道模式
+ // hart_command_ptr_arr[HART_COMMAND_67] = hart_slave_command_67_req; // 调整模拟通道零
+ // hart_command_ptr_arr[HART_COMMAND_68] = hart_slave_command_68_req; // 微调模拟通道增益
+ // hart_command_ptr_arr[HART_COMMAND_69] = hart_slave_command_69_req; // 写入模拟通道传递函数
+ // hart_command_ptr_arr[HART_COMMAND_70] = hart_slave_command_70_req; // 读取模拟通道端点值
+ // hart_command_ptr_arr[HART_COMMAND_71] = hart_slave_command_71_req; // 锁定装置
+ // hart_command_ptr_arr[HART_COMMAND_72] = hart_slave_command_72_req; // 呼叫
+ // hart_command_ptr_arr[HART_COMMAND_73] = hart_slave_command_73_req; // 查找设备
+ // hart_command_ptr_arr[HART_COMMAND_74] = hart_slave_command_74_req; // 读取I/O系统功能
+ // hart_command_ptr_arr[HART_COMMAND_75] = hart_slave_command_75_req; // 轮询子设备
+ // hart_command_ptr_arr[HART_COMMAND_76] = hart_slave_command_76_req; // 读锁定设备状态
+ // hart_command_ptr_arr[HART_COMMAND_79] = hart_slave_command_79_req; // 写入设备变量
+ // hart_command_ptr_arr[HART_COMMAND_80] = hart_slave_command_80_req; // 读取设备可变微调点
+ // hart_command_ptr_arr[HART_COMMAND_81] = hart_slave_command_81_req; // 读取设备变量调整指南
+ // hart_command_ptr_arr[HART_COMMAND_82] = hart_slave_command_82_req; // 写入设备可变微调点
+ // hart_command_ptr_arr[HART_COMMAND_83] = hart_slave_command_83_req; // 重置设备变量调整
+ // hart_command_ptr_arr[HART_COMMAND_84] = hart_slave_command_84_req; // 读取子设备标识摘要
+ // hart_command_ptr_arr[HART_COMMAND_85] = hart_slave_command_85_req; // 读取I/O通道统计信息
+ // hart_command_ptr_arr[HART_COMMAND_86] = hart_slave_command_86_req; // 读取子设备统计信息
+ // hart_command_ptr_arr[HART_COMMAND_87] = hart_slave_command_87_req; // 写入I/O系统主模式
+ // hart_command_ptr_arr[HART_COMMAND_88] = hart_slave_command_88_req; // 写入I/O系统重试计数
+ // hart_command_ptr_arr[HART_COMMAND_89] = hart_slave_command_89_req; // 设置实时时钟
+ // hart_command_ptr_arr[HART_COMMAND_90] = hart_slave_command_90_req; // 读取实时时钟
+ // hart_command_ptr_arr[HART_COMMAND_91] = hart_slave_command_91_req; // 读取趋势配置
+ // hart_command_ptr_arr[HART_COMMAND_92] = hart_slave_command_92_req; // 写入趋势配置
+ // hart_command_ptr_arr[HART_COMMAND_93] = hart_slave_command_93_req; // 读取趋势
+ // hart_command_ptr_arr[HART_COMMAND_94] = hart_slave_command_94_req; // 读取I/O系统客户端通信统计信息
+ // hart_command_ptr_arr[HART_COMMAND_95] = hart_slave_command_95_req; // 读取设备通信统计信息
+ // hart_command_ptr_arr[HART_COMMAND_96] = hart_slave_command_96_req; // 读取同步操作
+ // hart_command_ptr_arr[HART_COMMAND_97] = hart_slave_command_97_req; // 配置同步操作
+ // hart_command_ptr_arr[HART_COMMAND_98] = hart_slave_command_98_req; // 读取命令操作
+ // hart_command_ptr_arr[HART_COMMAND_99] = hart_slave_command_99_req; // 配置命令操作
+ // hart_command_ptr_arr[HART_COMMAND_100] = hart_slave_command_100_req; // 写入主变量报警码
+ hart_command_ptr_arr[HART_COMMAND_103] = hart_slave_command_103_req; // 写入突发周期
+ hart_command_ptr_arr[HART_COMMAND_104] = hart_slave_command_104_req; // 写入突发触发器
+ // hart_command_ptr_arr[HART_COMMAND_105] = hart_slave_command_105_req; // 读取突发模式配置
+ hart_command_ptr_arr[HART_COMMAND_107] = hart_slave_command_107_req; // 写入突发设备变量V5
+ // hart_command_ptr_arr[HART_COMMAND_514] = hart_slave_command_514_req; // 注册事件管理器
+ // hart_command_ptr_arr[HART_COMMAND_515] = hart_slave_command_515_req; // 读取事件管理器注册状态
+ // hart_command_ptr_arr[HART_COMMAND_520] = hart_slave_command_520_req; // 读取进程单元标签
+ // hart_command_ptr_arr[HART_COMMAND_521] = hart_slave_command_521_req; // 写入进程单元标记
+ // hart_command_ptr_arr[HART_COMMAND_522] = hart_slave_command_522_req; // 写入体积流分类
+ hart_command_ptr_arr[HART_COMMAND_523] = hart_slave_command_523_req; // 读取精简状态映射数组
+ hart_command_ptr_arr[HART_COMMAND_524] = hart_slave_command_524_req; // 写入精简状态映射
+ // hart_command_ptr_arr[HART_COMMAND_525] = hart_slave_command_525_req; // 重置精简状态图
+ // hart_command_ptr_arr[HART_COMMAND_526] = hart_slave_command_526_req; // 写入状态模拟模式
+ // hart_command_ptr_arr[HART_COMMAND_527] = hart_slave_command_527_req; // 模拟状态位
+ // hart_command_ptr_arr[HART_COMMAND_528] = hart_slave_command_528_req; // 读取子设备分配列表信息
+ // hart_command_ptr_arr[HART_COMMAND_529] = hart_slave_command_529_req; // 读取子设备分配
+ // hart_command_ptr_arr[HART_COMMAND_530] = hart_slave_command_530_req; // 写入子设备分配
+ // hart_command_ptr_arr[HART_COMMAND_531] = hart_slave_command_531_req; // 将实时列表传输到分配列表
+ // hart_command_ptr_arr[HART_COMMAND_532] = hart_slave_command_532_req; // 读取客户端订阅摘要
+ // hart_command_ptr_arr[HART_COMMAND_533] = hart_slave_command_533_req; // 写入客户端订阅标志
+ // hart_command_ptr_arr[HART_COMMAND_534] = hart_slave_command_534_req; // 读取设备变量命令代码
+ // hart_command_ptr_arr[HART_COMMAND_535] = hart_slave_command_535_req; // 写入模拟通道端点值
+ // hart_command_ptr_arr[HART_COMMAND_536] = hart_slave_command_536_req; // 写入应用时间操作
+ // hart_command_ptr_arr[HART_COMMAND_537] = hart_slave_command_537_req; // 读取应用时间操作
+ // hart_command_ptr_arr[HART_COMMAND_538] = hart_slave_command_538_req; // 读取HART-IP服务器端口
+ // hart_command_ptr_arr[HART_COMMAND_539] = hart_slave_command_539_req; // 写入HART-IP UDP端口
+ // hart_command_ptr_arr[HART_COMMAND_540] = hart_slave_command_540_req; // 写入HART-IP TCP端口
+ // hart_command_ptr_arr[HART_COMMAND_541] = hart_slave_command_541_req; // 写入客户端PAKE密码
+ // hart_command_ptr_arr[HART_COMMAND_542] = hart_slave_command_542_req; // 写入客户端预共享密钥
+ // hart_command_ptr_arr[HART_COMMAND_543] = hart_slave_command_543_req; // 读取系统日志服务器主机名和端口
+ // hart_command_ptr_arr[HART_COMMAND_544] = hart_slave_command_544_req; // 写入系统日志端口
+ // hart_command_ptr_arr[HART_COMMAND_545] = hart_slave_command_545_req; // 写入系统日志服务器主机名
+ // hart_command_ptr_arr[HART_COMMAND_546] = hart_slave_command_546_req; // 写入系统日志服务器预共享密钥
+ // hart_command_ptr_arr[HART_COMMAND_547] = hart_slave_command_547_req; // 写入系统日志服务器PAKE密码
+
+ // hart_command_ptr_arr[HART_COMMAND_77] = hart_slave_command_77_req; // 向子设备发送命令
+ // hart_command_ptr_arr[HART_COMMAND_78] = hart_slave_command_78_req; // 读取聚合命令
+ // hart_command_ptr_arr[HART_COMMAND_101] = hart_slave_command_101_req; // 读取子设备到突发消息映射
+ // hart_command_ptr_arr[HART_COMMAND_102] = hart_slave_command_102_req; // 将子设备映射到突发信息
+ // hart_command_ptr_arr[HART_COMMAND_106] = hart_slave_command_106_req; // 刷新延迟响应
+ hart_command_ptr_arr[HART_COMMAND_108] = hart_slave_command_108_req; // 写入突发模式命令编号V5
+ // hart_command_ptr_arr[HART_COMMAND_110] = hart_slave_command_110_req; // 读取所有动态变量V5
+ // hart_command_ptr_arr[HART_COMMAND_111] = hart_slave_command_111_req; // 转移服务控制
+ // hart_command_ptr_arr[HART_COMMAND_112] = hart_slave_command_112_req; // 传输服务
+ // hart_command_ptr_arr[HART_COMMAND_113] = hart_slave_command_113_req; // 捕获设备变量
+ // hart_command_ptr_arr[HART_COMMAND_114] = hart_slave_command_114_req; // 读取捕获的设备变量
+ // hart_command_ptr_arr[HART_COMMAND_115] = hart_slave_command_115_req; // 读取事件通知摘要
+ // hart_command_ptr_arr[HART_COMMAND_116] = hart_slave_command_116_req; // 写入事件通知位掩码
+ // hart_command_ptr_arr[HART_COMMAND_117] = hart_slave_command_117_req; // 写入事件通知时序
+ // hart_command_ptr_arr[HART_COMMAND_118] = hart_slave_command_118_req; // 事件通知控制
+ // hart_command_ptr_arr[HART_COMMAND_119] = hart_slave_command_119_req; // 确认事件通知
+
+ // 暂不支持指令 end
+ hart_slave_req_init_user(); // 用户自定义命令
+}
diff --git a/User/hart/slave/src/hart_slave_req_user.c b/User/hart/slave/src/hart_slave_req_user.c
new file mode 100644
index 0000000..b65c44d
--- /dev/null
+++ b/User/hart/slave/src/hart_slave_req_user.c
@@ -0,0 +1,1337 @@
+#include "../inc/hart_slave_req.h"
+#include "../inc/hart_slave_frame.h"
+
+#ifndef STM32
+static uint32_t sys_millis(void)
+{
+ return 0;
+}
+#else
+#include "delay.h"
+#endif
+
+static const uint32_t invalid_val = HART_INVALID_VALUE;
+
+/**
+ * @brief 用户自定义参数设置检查
+ * @param {hart_command_req_t} *req
+ * @param {uint8_t} *cnt
+ * @return {*}
+ * @note
+ */
+static response_communication_code_e user_setting_length_check(const hart_command_req_t *const req, uint8_t *cnt)
+{
+ uint8_t cmd = 0, len = 0, key_len = 1;
+ hart_device_variable_t *variable = NULL;
+ hart_device_constant_t *constant = NULL;
+
+ uint8_t *index = (uint8_t *)req->data.command_130.pbuf;
+ variable_e type = VARIABLE;
+ if (req->data_length > USER_RESPONSE_MAX_LEN)
+ {
+ return RESPONSE_COMMUNICATION_CODE_3;
+ }
+
+ while (len < req->data_length)
+ {
+ type = get_variable_type(*index);
+ if (type == VARIABLE)
+ {
+ variable = get_device_variable(*index);
+ if (variable->code == DIN_250)
+ {
+ return RESPONSE_COMMUNICATION_CODE_6;
+ }
+ len = variable->user_param.len + key_len + len;
+ index = variable->user_param.len + key_len + index;
+ }
+ else if (type == CONSTANT)
+ {
+ constant = get_device_constant(*index);
+ if (constant->code == DIN_250)
+ {
+ return RESPONSE_COMMUNICATION_CODE_6;
+ }
+ len = constant->user_param.len + key_len + len;
+ index = constant->user_param.len + key_len + index;
+ }
+ else
+ {
+ variable = get_device_variable_by_standard_code(*index);
+ if (variable->code == DIN_250)
+ {
+ return RESPONSE_COMMUNICATION_CODE_6;
+ }
+ len = variable->user_param.len + key_len + len;
+ index = variable->user_param.len + key_len + index;
+ }
+
+ cmd++;
+ }
+ if (len != req->data_length)
+ {
+ return RESPONSE_COMMUNICATION_CODE_5;
+ }
+ else
+ {
+ *cnt = cmd;
+ return RESPONSE_COMMUNICATION_CODE_0;
+ }
+}
+
+/**
+ * @brief 用户自定义参数变量设置
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ * @note
+ */
+static uint8_t user_loading_parse_variable(hart_device_variable_t *cmd, uint8_t *data)
+{
+ hart_device_variable_t *variable = cmd;
+ uint8_t *hart_device_variable_data = (uint8_t *)variable->value;
+ uint8_t *payload = data;
+ uint8_t len = 0, key_len = 1;
+ uint16_t tmp_word = 0;
+ uint32_t tmp_uint32 = 0;
+ float32 tmp_float = 0;
+
+ // 命令号
+ *payload++ = variable->code;
+ // 载荷
+ while (len < variable->user_param.len)
+ {
+ switch (variable->user_param.type)
+ {
+ case USER_BYTE:
+ osel_memcpy(payload, hart_device_variable_data, sizeof(uint8_t));
+ hart_device_variable_data += sizeof(uint8_t);
+ payload += sizeof(uint8_t);
+ len += sizeof(uint8_t);
+ break;
+ case USER_WORD:
+ osel_memcpy((uint8_t *)&tmp_word, hart_device_variable_data, sizeof(uint16_t));
+ tmp_word = S2B_UINT16(tmp_word);
+ osel_memcpy(payload, (uint8_t *)&tmp_word, sizeof(uint16_t));
+ hart_device_variable_data += sizeof(uint16_t);
+ payload += sizeof(uint16_t);
+ len += sizeof(uint16_t);
+ break;
+ case USER_UINT32:
+ osel_memcpy((uint8_t *)&tmp_uint32, hart_device_variable_data, sizeof(uint32_t));
+ tmp_uint32 = S2B_UINT32(tmp_uint32);
+ osel_memcpy(payload, (uint8_t *)&tmp_uint32, sizeof(uint32_t));
+ hart_device_variable_data += sizeof(uint32_t);
+ payload += sizeof(uint32_t);
+ len += sizeof(uint32_t);
+ break;
+ case USER_FLOAT:
+ osel_memcpy((uint8_t *)&tmp_float, hart_device_variable_data, sizeof(float32));
+ tmp_float = S2B_FLOAT32(tmp_float);
+ osel_memcpy(payload, (uint8_t *)&tmp_float, sizeof(float32));
+ hart_device_variable_data += sizeof(float32);
+ payload += sizeof(float32);
+ len += sizeof(float32);
+ break;
+ default:
+ return len;
+ }
+ }
+ len = len + key_len;
+ return len;
+}
+
+/**
+ * @brief 用户自定义参数常量设置
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ * @note
+ */
+static uint8_t user_loading_parse_constant(hart_device_constant_t *cmd, uint8_t *data)
+{
+ hart_device_constant_t *constant = cmd;
+ uint8_t *hart_device_constant_data = (uint8_t *)constant->value;
+ uint8_t *payload = data;
+ uint8_t len = 0, key_len = 1;
+ uint16_t tmp_word = 0;
+ uint32_t tmp_uint32 = 0;
+ float32 tmp_float = 0;
+
+ // 命令号
+ *payload++ = constant->code;
+ // 载荷
+ while (len < constant->user_param.len)
+ {
+ switch (constant->user_param.type)
+ {
+ case USER_BYTE:
+ osel_memcpy(payload, hart_device_constant_data, sizeof(uint8_t));
+ hart_device_constant_data += sizeof(uint8_t);
+ payload += sizeof(uint8_t);
+ len += sizeof(uint8_t);
+ break;
+ case USER_WORD:
+ osel_memcpy((uint8_t *)&tmp_word, hart_device_constant_data, sizeof(uint16_t));
+ tmp_word = S2B_UINT16(tmp_word);
+ osel_memcpy(payload, (uint8_t *)&tmp_word, sizeof(uint16_t));
+ hart_device_constant_data += sizeof(uint16_t);
+ payload += sizeof(uint16_t);
+ len += sizeof(uint16_t);
+ break;
+ case USER_UINT32:
+ osel_memcpy((uint8_t *)&tmp_uint32, hart_device_constant_data, sizeof(uint32_t));
+ tmp_uint32 = S2B_UINT32(tmp_uint32);
+ osel_memcpy(hart_device_constant_data, (uint8_t *)&tmp_uint32, sizeof(uint32_t));
+ hart_device_constant_data += sizeof(uint32_t);
+ payload += sizeof(uint32_t);
+ len += sizeof(uint32_t);
+ break;
+ case USER_FLOAT:
+ osel_memcpy((uint8_t *)&tmp_float, hart_device_constant_data, sizeof(float32));
+ tmp_float = S2B_FLOAT32(tmp_float);
+ osel_memcpy(payload, (uint8_t *)&tmp_float, sizeof(float32));
+ hart_device_constant_data += sizeof(float32);
+ payload += sizeof(float32);
+ len += sizeof(float32);
+ break;
+ default:
+ return len;
+ }
+ }
+ len = len + key_len;
+ return len;
+}
+
+/**
+ * @brief 突发模式控制V5
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ */
+static BOOL hart_slave_command_109_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ hart_user_req_t user_req;
+ if (hart_frame_data_length_check(req->data_length, sizeof(hart_command_109_t), (uint8_t *)&resp->code) == FALSE)
+ {
+ return TRUE;
+ }
+ osel_memcpy((uint8_t *)&user_req.data.command_109, (uint8_t *)&req->data.command_109, sizeof(hart_command_109_t));
+ if (FALSE == hart_user_common_event(HART_COMMAND_109_EVENT, (void *)&user_req))
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_64;
+ return TRUE;
+ }
+
+ if (user_req.rsp.len != 0)
+ {
+ osel_memcpy(resp->data_p, user_req.rsp.pbuf, user_req.rsp.len);
+ resp->data_p += user_req.rsp.len;
+ }
+
+ return TRUE;
+}
+
+/**
+ * @brief 用户自定义参数读取
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ * @note
+ */
+static BOOL hart_slave_command_129_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ hart_device_variable_t *variable = NULL;
+ hart_device_constant_t *constant = NULL;
+ uint8_t *index = (uint8_t *)req->data.command_129.pbuf;
+ uint8_t *payload = NULL;
+ uint8_t i = 0, len = 0, key_len = 1;
+ uint32_t val = 0;
+ variable_e tp = VARIABLE;
+ if (req->data_length > USER_PARAM_MAX_NUM)
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_3;
+ return TRUE;
+ }
+ else if (req->data_length == 0)
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_5;
+ return TRUE;
+ }
+
+ for (i = 0; i < req->data_length; i++)
+ {
+ tp = get_variable_type(*index);
+ if (tp == VARIABLE)
+ {
+ variable = get_device_variable(*index);
+ if (variable->code == DIN_250)
+ {
+ // 回复数据加入无效参数
+ resp->code = RESPONSE_COMMUNICATION_CODE_126;
+ *resp->data_p++ = DIN_250;
+ val = S2B_UINT32(invalid_val);
+ osel_memcpy(resp->data_p, (uint8_t *)&val, sizeof(uint32_t));
+ resp->data_p += sizeof(uint32_t);
+ }
+ else
+ {
+ // 数据处理
+ len = key_len + variable->user_param.len;
+ payload = (uint8_t *)osel_mem_alloc(len);
+ user_loading_parse_variable(variable, payload);
+ // 回复数据加入有效数据
+ osel_memcpy(resp->data_p, payload, len);
+ resp->data_p += len;
+ osel_mem_free(payload);
+ }
+ }
+ else if (tp == CONSTANT)
+ {
+ constant = get_device_constant(*index);
+ if (constant->code == DIN_250)
+ {
+ // 回复数据加入无效参数
+ resp->code = RESPONSE_COMMUNICATION_CODE_126;
+ *resp->data_p++ = DIN_250;
+ val = S2B_UINT32(invalid_val);
+ osel_memcpy(resp->data_p, (uint8_t *)&val, sizeof(uint32_t));
+ resp->data_p += sizeof(uint32_t);
+ }
+ else
+ {
+ // 数据处理
+ len = key_len + constant->user_param.len;
+ payload = (uint8_t *)osel_mem_alloc(len);
+ user_loading_parse_constant(constant, payload);
+ // 回复数据加入有效数据
+ osel_memcpy(resp->data_p, payload, len);
+ resp->data_p += len;
+ osel_mem_free(payload);
+ }
+ }
+ else
+ {
+ // 复制上面变量的处理逻辑
+ variable = get_device_variable_by_standard_code(*index);
+ if (variable->code == DIN_250)
+ {
+ // 回复数据加入无效参数
+ resp->code = RESPONSE_COMMUNICATION_CODE_126;
+ *resp->data_p++ = DIN_250;
+ val = S2B_UINT32(invalid_val);
+ osel_memcpy(resp->data_p, (uint8_t *)&val, sizeof(uint32_t));
+ resp->data_p += sizeof(uint32_t);
+ }
+ else
+ {
+ // 数据处理
+ len = key_len + variable->user_param.len;
+ payload = (uint8_t *)osel_mem_alloc(len);
+ user_loading_parse_variable(variable, payload);
+ // 回复数据加入有效数据
+ osel_memcpy(resp->data_p, payload, len);
+ resp->data_p += len;
+ osel_mem_free(payload);
+ }
+ }
+
+ // 数据偏移
+ index = index + key_len;
+ }
+ return TRUE;
+}
+
+/**
+ * @brief 用户自定义参数设置
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ * @note
+ */
+static BOOL hart_slave_command_130_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ response_communication_code_e res;
+ uint8_t cnt = 0, len = 0, i = 0, key_len = 1;
+ uint32_t val = 0;
+ variable_e tp = VARIABLE;
+
+ res = user_setting_length_check(req, &cnt);
+ if (res != RESPONSE_COMMUNICATION_CODE_0)
+ {
+ resp->code = res;
+ return TRUE;
+ }
+
+ // 用户自定义参数设置
+ hart_device_variable_t *variable = NULL;
+ hart_device_constant_t *constant = NULL;
+
+ uint8_t *index = (uint8_t *)req->data.command_130.pbuf;
+ uint8_t *payload = index + key_len;
+
+ for (i = 0; i < cnt; i++)
+ {
+ tp = get_variable_type(*index);
+ if (tp == VARIABLE)
+ {
+ variable = get_device_variable(*index);
+ if (variable->user_param.access != USER_READ_WRITE)
+ {
+ // 回复数据加入无效参数
+ resp->code = RESPONSE_COMMUNICATION_CODE_126;
+ *resp->data_p++ = DIN_250;
+ val = S2B_UINT32(invalid_val);
+ osel_memcpy(resp->data_p, (uint8_t *)&val, sizeof(uint32_t));
+ resp->data_p += sizeof(uint32_t);
+ }
+ else
+ {
+ // 数据处理
+ set_device_variable(variable, payload);
+ // 回复数据加入有效参数
+ len = variable->user_param.len + key_len;
+ osel_memcpy(resp->data_p, index, len);
+ resp->data_p += len;
+ }
+ }
+ else if (tp == CONSTANT)
+ {
+ constant = get_device_constant(*index);
+ if (constant->user_param.access != USER_READ_WRITE)
+ {
+ // 回复数据加入无效参数
+ resp->code = RESPONSE_COMMUNICATION_CODE_126;
+ *resp->data_p++ = DIN_250;
+ val = S2B_UINT32(invalid_val);
+ osel_memcpy(resp->data_p, (uint8_t *)&val, sizeof(uint32_t));
+ resp->data_p += sizeof(uint32_t);
+ }
+ else
+ {
+ // 数据处理
+ set_device_constant(constant, payload);
+ // 回复数据加入有效参数
+ len = constant->user_param.len + key_len;
+ osel_memcpy(resp->data_p, index, len);
+ resp->data_p += len;
+ }
+ }
+ else
+ {
+ variable = get_device_variable(*index);
+ if (variable->user_param.access != USER_READ_WRITE)
+ {
+ // 回复数据加入无效参数
+ resp->code = RESPONSE_COMMUNICATION_CODE_126;
+ *resp->data_p++ = DIN_250;
+ val = S2B_UINT32(invalid_val);
+ osel_memcpy(resp->data_p, (uint8_t *)&val, sizeof(uint32_t));
+ resp->data_p += sizeof(uint32_t);
+ }
+ else
+ {
+ // 数据处理
+ set_device_variable(variable, payload);
+ // 回复数据加入有效参数
+ len = variable->user_param.len + key_len;
+ osel_memcpy(resp->data_p, index, len);
+ resp->data_p += len;
+ }
+ }
+
+ // 数据偏移1
+ index = index + variable->user_param.len + key_len;
+ payload = index + key_len;
+ }
+
+ return TRUE;
+}
+
+/**
+ * @brief 写入整定参数
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ * @note
+ */
+static BOOL hart_slave_command_131_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ hart_user_req_t user_req;
+ if (hart_frame_data_length_check(req->data_length, sizeof(hart_command_131_t), (uint8_t *)&resp->code) == FALSE)
+ {
+ return TRUE;
+ }
+ osel_memcpy((uint8_t *)&user_req.data.command_131, (uint8_t *)&req->data.command_131, sizeof(hart_command_131_t));
+ if (FALSE == hart_user_common_event(HART_COMMAND_131_EVENT, (void *)&user_req))
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_64;
+ return TRUE;
+ }
+ if (user_req.rsp.len != 0)
+ {
+ osel_memcpy(resp->data_p, user_req.rsp.pbuf, user_req.rsp.len);
+ resp->data_p += user_req.rsp.len;
+ }
+
+ return TRUE;
+}
+
+/**
+ * @brief 读取整定参数类型
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ * @note
+ */
+static BOOL hart_slave_command_132_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ hart_user_req_t user_req;
+ if (FALSE == hart_user_common_event(HART_COMMAND_132_EVENT, (void *)&user_req))
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_64;
+ return TRUE;
+ }
+ if (user_req.rsp.len != 0)
+ {
+ osel_memcpy(resp->data_p, user_req.rsp.pbuf, user_req.rsp.len);
+ resp->data_p += user_req.rsp.len;
+ }
+ return TRUE;
+}
+
+/**
+ * @brief 获取打开的文件信息
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ * @note
+ */
+static BOOL hart_slave_command_133_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ if (hart_frame_data_length_check(req->data_length, sizeof(hart_command_133_t), (uint8_t *)&resp->code) == FALSE)
+ {
+ return TRUE;
+ }
+ hart_user_req_t user_req;
+ osel_memcpy((uint8_t *)&user_req.data.command_133, (uint8_t *)&req->data.command_133, sizeof(hart_command_133_t));
+ if (FALSE == hart_user_common_event(HART_COMMAND_133_EVENT, (void *)&user_req))
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_64;
+ return TRUE;
+ }
+ if (user_req.rsp.len != 0)
+ {
+ osel_memcpy(resp->data_p, user_req.rsp.pbuf, user_req.rsp.len);
+ resp->data_p += user_req.rsp.len;
+ }
+ return TRUE;
+}
+
+/**
+ * @brief 读取文件内容
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ * @note
+ */
+static BOOL hart_slave_command_134_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ if (hart_frame_data_length_check(req->data_length, sizeof(hart_command_134_t), (uint8_t *)&resp->code) == FALSE)
+ {
+ return TRUE;
+ }
+ hart_user_req_t user_req;
+ osel_memcpy((uint8_t *)&user_req.data.command_134, (uint8_t *)&req->data.command_134, sizeof(hart_command_134_t));
+ user_req.data_length = req->data_length;
+ user_req.data.command_134.file_offset = B2S_UINT16(user_req.data.command_134.file_offset);
+ if (FALSE == hart_user_common_event(HART_COMMAND_134_EVENT, (void *)&user_req))
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_64;
+ return TRUE;
+ }
+
+ if (user_req.rsp.len != 0)
+ {
+ osel_memcpy(resp->data_p, user_req.rsp.pbuf, user_req.rsp.len);
+ resp->data_p += user_req.rsp.len;
+ }
+ return TRUE;
+}
+
+/**
+ * @brief 写入文件
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ * @note
+ */
+static BOOL hart_slave_command_135_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ if (req->data_length > sizeof(hart_command_135_t))
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_3; // 这里不适用hart_frame_data_length_check
+ return TRUE;
+ }
+
+ hart_user_req_t user_req;
+ osel_memcpy((uint8_t *)&user_req.data.command_135, (uint8_t *)&req->data.command_135, req->data_length);
+ user_req.data_length = req->data_length;
+ user_req.data.command_135.address = B2S_UINT16(user_req.data.command_135.address);
+ if (FALSE == hart_user_common_event(HART_COMMAND_135_EVENT, (void *)&user_req))
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_64;
+ return TRUE;
+ }
+ if (user_req.rsp.len != 0)
+ {
+ osel_memcpy(resp->data_p, user_req.rsp.pbuf, user_req.rsp.len);
+ resp->data_p += user_req.rsp.len;
+ }
+
+ return TRUE;
+}
+
+/**
+ * @brief 读取/解除/写入EEPROM
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ * @note
+ */
+static BOOL hart_slave_command_136_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ // 锁类型可忽略,不做长度检查处理
+ hart_user_req_t user_req;
+ osel_memcpy((uint8_t *)&user_req.data.command_136, (uint8_t *)&req->data.command_136, req->data_length);
+ if (FALSE == hart_user_common_event(HART_COMMAND_136_EVENT, (void *)&user_req))
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_64;
+ return TRUE;
+ }
+ if (user_req.rsp.len != 0)
+ {
+ osel_memcpy(resp->data_p, user_req.rsp.pbuf, user_req.rsp.len);
+ resp->data_p += user_req.rsp.len;
+ }
+ return TRUE;
+}
+
+/**
+ * @brief 读取其他状态
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ * @note
+ */
+static BOOL hart_slave_command_138_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ hart_user_req_t user_req;
+ if (FALSE == hart_user_common_event(HART_COMMAND_138_EVENT, (void *)&user_req))
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_64;
+ return TRUE;
+ }
+ if (user_req.rsp.len != 0)
+ {
+ osel_memcpy(resp->data_p, user_req.rsp.pbuf, user_req.rsp.len);
+ resp->data_p += user_req.rsp.len;
+ }
+ return TRUE;
+}
+
+/**
+ * @brief 读取触发器定义的内容
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ * @note
+ */
+static BOOL hart_slave_command_140_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ // uint8_t resp_data_length = req->data.command_140.req.read_data_len; ///< 读取数据长度
+ if (hart_frame_data_length_check(req->data_length, sizeof(hart_command_140_t), (uint8_t *)&resp->code) == FALSE)
+ {
+ return TRUE;
+ }
+ hart_user_req_t user_req;
+ osel_memcpy((uint8_t *)&user_req.data.command_140, (uint8_t *)&req->data.command_140, sizeof(hart_command_140_t));
+ if (FALSE == hart_user_common_event(HART_COMMAND_140_EVENT, (void *)&user_req))
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_64;
+ return TRUE;
+ }
+ // if (user_req.rsp.len == resp_data_length) ///< 读取数据长度正确(暂未明确意思)
+ //{
+ osel_memcpy(resp->data_p, user_req.rsp.pbuf, user_req.rsp.len);
+ resp->data_p += user_req.rsp.len;
+ //}
+ // else ///< 读取数据长度错误
+ // {
+ // resp->code = RESPONSE_COMMUNICATION_CODE_6;
+ // }
+ return TRUE;
+}
+
+static BOOL hart_slave_command_141_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ if (hart_frame_data_length_check(req->data_length, sizeof(hart_command_141_t), (uint8_t *)&resp->code) == FALSE)
+ {
+ return TRUE;
+ }
+
+ // 计数器暂时用不到,这里直接改变读写状态
+ hart_command_141_t data;
+ osel_memcpy((uint8_t *)&data, (uint8_t *)&req->data.command_141, sizeof(hart_command_141_t));
+ if (data.protection_code != WRITE_PROTECT_CODE_NOT_WRITE_PROTECT &&
+ data.protection_code != WRITE_PROTECT_CODE_WRITE_PROTECT)
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_5;
+ }
+ else
+ {
+ if (hart_device_attribute.flash_variable.write_protect_code != data.protection_code)
+ {
+ hart_device_attribute.flash_variable.write_protect_code = data.protection_code;
+ hart_storage_write_item(HART_STORAGE_PARAMS, HPB_WRITE_PROTECT_CODE,
+ (uint8_t *)&hart_device_attribute.flash_variable.write_protect_code);
+ hart_device_status_set_operational_state(DEVICE_OPERATIONAL_STATE_7);
+ }
+ }
+
+ // 回复数据
+ osel_memcpy(resp->data_p, (uint8_t *)&data, sizeof(hart_command_141_t));
+ resp->data_p += sizeof(hart_command_141_t);
+
+ return TRUE;
+}
+/**
+ * @brief 校准
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ * @note
+ */
+static BOOL hart_slave_command_142_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ if (req->data_length != 1)
+ {
+ if (hart_frame_data_length_check(req->data_length, sizeof(hart_command_142_t), (uint8_t *)&resp->code) == FALSE)
+ {
+ return TRUE;
+ }
+ }
+
+ hart_user_req_t user_req;
+ osel_memcpy((uint8_t *)&user_req.data.command_142, (uint8_t *)&req->data.command_142, sizeof(hart_command_142_t));
+
+ if (FALSE == hart_user_common_event(HART_COMMAND_142_EVENT, (void *)&user_req))
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_64;
+ return TRUE;
+ }
+ osel_memcpy(resp->data_p, (uint8_t *)&user_req.data.command_142, req->data_length);
+ resp->data_p += req->data_length;
+ return TRUE;
+}
+
+/**
+ * @brief 设置阀门序列号
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ * @note
+ */
+static BOOL hart_slave_command_143_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ if (hart_frame_data_length_check(req->data_length, sizeof(hart_command_143_t), (uint8_t *)&resp->code) == FALSE)
+ {
+ return TRUE;
+ }
+ hart_user_req_t user_req;
+ osel_memcpy((uint8_t *)&user_req.data.command_143, (uint8_t *)&req->data.command_143, sizeof(hart_command_143_t));
+
+ if (FALSE == hart_user_common_event(HART_COMMAND_143_EVENT, (void *)&user_req))
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_64;
+ return TRUE;
+ }
+ if (user_req.rsp.len != 0)
+ {
+ osel_memcpy(resp->data_p, user_req.rsp.pbuf, user_req.rsp.len);
+ resp->data_p += user_req.rsp.len;
+ }
+
+ return TRUE;
+}
+
+/**
+ * @brief 读取阀门序列号
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ * @note
+ */
+static BOOL hart_slave_command_144_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ hart_user_req_t user_req;
+ if (FALSE == hart_user_common_event(HART_COMMAND_144_EVENT, (void *)&user_req))
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_64;
+ return TRUE;
+ }
+ if (user_req.rsp.len != 0)
+ {
+ osel_memcpy(resp->data_p, user_req.rsp.pbuf, user_req.rsp.len);
+ resp->data_p += user_req.rsp.len;
+ }
+ return TRUE;
+}
+
+/**
+ * @brief 读取仪器序列号
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ * @note
+ */
+static BOOL hart_slave_command_145_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ hart_user_req_t user_req;
+ if (FALSE == hart_user_common_event(HART_COMMAND_145_EVENT, (void *)&user_req))
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_64;
+ return TRUE;
+ }
+ if (user_req.rsp.len != 0)
+ {
+ osel_memcpy(resp->data_p, user_req.rsp.pbuf, user_req.rsp.len);
+ resp->data_p += user_req.rsp.len;
+ }
+ return TRUE;
+}
+
+/**
+ * @brief 读取标准跨度信息
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ * @note
+ */
+static BOOL hart_slave_command_146_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ hart_user_req_t user_req;
+ if (FALSE == hart_user_common_event(HART_COMMAND_146_EVENT, (void *)&user_req))
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_64;
+ return TRUE;
+ }
+ if (user_req.rsp.len != 0)
+ {
+ osel_memcpy(resp->data_p, user_req.rsp.pbuf, user_req.rsp.len);
+ resp->data_p += user_req.rsp.len;
+ }
+ return TRUE;
+}
+
+/**
+ * @brief 读取设备等级
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ * @note
+ */
+static BOOL hart_slave_command_147_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ hart_user_req_t user_req;
+ if (FALSE == hart_user_common_event(HART_COMMAND_147_EVENT, (void *)&user_req))
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_64;
+ return TRUE;
+ }
+ if (user_req.rsp.len != 0)
+ {
+ osel_memcpy(resp->data_p, user_req.rsp.pbuf, user_req.rsp.len);
+ resp->data_p += user_req.rsp.len;
+ }
+ return TRUE;
+}
+
+/**
+ * @brief 设置仪器时间
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ * @note
+ */
+static BOOL hart_slave_command_149_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ if (hart_frame_data_length_check(req->data_length, sizeof(hart_command_149_t), (uint8_t *)&resp->code) == FALSE)
+ {
+ return TRUE;
+ }
+ hart_user_req_t user_req;
+ osel_memcpy((uint8_t *)&user_req.data.command_149, (uint8_t *)&req->data.command_149, sizeof(hart_command_149_t));
+ user_req.data.command_149.secs = B2S_UINT32(user_req.data.command_149.secs);
+ if (FALSE == hart_user_common_event(HART_COMMAND_149_EVENT, (void *)&user_req))
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_64;
+ return TRUE;
+ }
+ if (user_req.rsp.len != 0)
+ {
+ osel_memcpy(resp->data_p, user_req.rsp.pbuf, user_req.rsp.len);
+ resp->data_p += user_req.rsp.len;
+ }
+
+ return TRUE;
+}
+
+/**
+ * @brief 读取仪器时间
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ * @note
+ */
+static BOOL hart_slave_command_150_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ hart_user_req_t user_req;
+ if (FALSE == hart_user_common_event(HART_COMMAND_150_EVENT, (void *)&user_req))
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_64;
+ return TRUE;
+ }
+ if (user_req.rsp.len != 0)
+ {
+ osel_memcpy(resp->data_p, user_req.rsp.pbuf, user_req.rsp.len);
+ resp->data_p += user_req.rsp.len;
+ }
+ return TRUE;
+}
+
+/**
+ * @brief 读取版本信息
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ * @note
+ */
+static BOOL hart_slave_command_151_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ hart_user_req_t user_req;
+ if (FALSE == hart_user_common_event(HART_COMMAND_151_EVENT, (void *)&user_req))
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_64;
+ return TRUE;
+ }
+ if (user_req.rsp.len != 0)
+ {
+ osel_memcpy(resp->data_p, user_req.rsp.pbuf, user_req.rsp.len);
+ resp->data_p += user_req.rsp.len;
+ }
+ return TRUE;
+}
+
+/**
+ * @brief 读取校准记录
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ * @note
+ */
+static BOOL hart_slave_command_153_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ hart_user_req_t user_req;
+ if (FALSE == hart_user_common_event(HART_COMMAND_153_EVENT, (void *)&user_req))
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_64;
+ return TRUE;
+ }
+ if (user_req.rsp.len != 0)
+ {
+ osel_memcpy(resp->data_p, user_req.rsp.pbuf, user_req.rsp.len);
+ resp->data_p += user_req.rsp.len;
+ }
+ return TRUE;
+}
+
+/**
+ * @brief 设置仪器序列号
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ * @note
+ */
+static BOOL hart_slave_command_154_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ if (hart_frame_data_length_check(req->data_length, sizeof(hart_command_154_t), (uint8_t *)&resp->code) == FALSE)
+ {
+ return TRUE;
+ }
+ hart_user_req_t user_req;
+ osel_memcpy((uint8_t *)&user_req.data.command_154, (uint8_t *)&req->data.command_154, sizeof(hart_command_154_t));
+
+ if (FALSE == hart_user_common_event(HART_COMMAND_154_EVENT, (void *)&user_req))
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_64;
+ return TRUE;
+ }
+ if (user_req.rsp.len != 0)
+ {
+ osel_memcpy(resp->data_p, user_req.rsp.pbuf, user_req.rsp.len);
+ resp->data_p += user_req.rsp.len;
+ }
+
+ return TRUE;
+}
+
+/**
+ * @brief 执行诊断
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ * @note
+ */
+static BOOL hart_slave_command_155_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ if (hart_frame_data_length_check(req->data_length, sizeof(hart_command_155_t), (uint8_t *)&resp->code) == FALSE)
+ {
+ return TRUE;
+ }
+ hart_user_req_t user_req;
+ osel_memcpy((uint8_t *)&user_req.data.command_155, (uint8_t *)&req->data.command_155, sizeof(hart_command_155_t));
+
+ if (FALSE == hart_user_common_event(HART_COMMAND_155_EVENT, (void *)&user_req))
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_64;
+ return TRUE;
+ }
+ return TRUE;
+}
+
+/**
+ * @brief 读取诊断状态
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ * @note
+ */
+static BOOL hart_slave_command_156_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ hart_user_req_t user_req;
+ // osel_memcpy((uint8_t *)&user_req.data.command_156, (uint8_t *)&req->data.command_156, sizeof(hart_command_156_t));
+
+ if (FALSE == hart_user_common_event(HART_COMMAND_156_EVENT, (void *)&user_req))
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_64;
+ return TRUE;
+ }
+ if (user_req.rsp.len != 0)
+ {
+ osel_memcpy(resp->data_p, user_req.rsp.pbuf, user_req.rsp.len);
+ resp->data_p += user_req.rsp.len;
+ }
+ return TRUE;
+}
+
+/**
+ * @brief 停止诊断
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ * @note
+ */
+static BOOL hart_slave_command_157_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ if (FALSE == hart_user_common_event(HART_COMMAND_157_EVENT, NULL))
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_64;
+ return TRUE;
+ }
+ return TRUE;
+}
+
+/**
+ * @brief 在线诊断测试
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ * @note
+ */
+static BOOL hart_slave_command_158_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ if (hart_frame_data_length_check(req->data_length, sizeof(hart_command_158_t), (uint8_t *)&resp->code) == FALSE) ///< 校验数据长度
+ {
+ return TRUE;
+ }
+ hart_user_req_t user_req;
+ osel_memcpy((uint8_t *)&user_req.data.command_158, (uint8_t *)&req->data.command_158, sizeof(hart_command_158_t));
+ user_req.data.command_158.points = B2S_UINT16(user_req.data.command_158.points);
+ if (FALSE == hart_user_common_event(HART_COMMAND_158_EVENT, (void *)&user_req))
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_64;
+ return TRUE;
+ }
+ return TRUE;
+}
+
+/**
+ * @brief 设置气源气压/A口/B口
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ * @note
+ */
+static BOOL hart_slave_command_162_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ if (hart_frame_data_length_check(req->data_length, sizeof(hart_command_162_t), (uint8_t *)&resp->code) == FALSE) ///< 校验数据长度
+ {
+ return TRUE;
+ }
+ hart_user_req_t user_req;
+ osel_memcpy((uint8_t *)&user_req.data.command_162, (uint8_t *)&req->data.command_162, sizeof(hart_command_162_t));
+ user_req.data.command_162.press_value = B2S_FLOAT32(user_req.data.command_162.press_value);
+ if (FALSE == hart_user_common_event(HART_COMMAND_162_EVENT, (void *)&user_req))
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_64;
+ return TRUE;
+ }
+ if (user_req.rsp.len != 0)
+ {
+ osel_memcpy(resp->data_p, user_req.rsp.pbuf, user_req.rsp.len);
+ resp->data_p += user_req.rsp.len;
+ }
+ return TRUE;
+}
+/**
+ * @brief 读取规格表数据
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ * @note
+ */
+static BOOL hart_slave_command_164_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ hart_user_req_t user_req;
+ if (hart_frame_data_length_check(req->data_length, sizeof(hart_command_164_t), (uint8_t *)&resp->code) == FALSE)
+ {
+ return TRUE;
+ }
+ osel_memcpy((uint8_t *)&user_req.data.command_164, (uint8_t *)&req->data.command_164, sizeof(hart_command_164_t));
+ user_req.data.command_164.address = B2S_UINT16(user_req.data.command_164.address);
+ if (FALSE == hart_user_common_event(HART_COMMAND_164_EVENT, (void *)&user_req))
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_64;
+ return TRUE;
+ }
+ if (user_req.rsp.len != 0)
+ {
+ osel_memcpy(resp->data_p, user_req.rsp.pbuf, user_req.rsp.len);
+ resp->data_p += user_req.rsp.len;
+ }
+ return TRUE;
+}
+
+/**
+ * @brief 写入规格表数据
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ * @note
+ */
+static BOOL hart_slave_command_165_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ hart_user_req_t user_req;
+ if (req->data_length > sizeof(hart_command_165_t))
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_3; // 这里不适用hart_frame_data_length_check
+ return TRUE;
+ }
+
+ user_req.data_length = req->data_length;
+ osel_memcpy((uint8_t *)&user_req.data.command_165, (uint8_t *)&req->data.command_165, sizeof(hart_command_165_t));
+ user_req.data.command_165.address = B2S_UINT16(user_req.data.command_165.address);
+ if (FALSE == hart_user_common_event(HART_COMMAND_165_EVENT, (void *)&user_req))
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_64;
+ return TRUE;
+ }
+ if (user_req.rsp.len != 0)
+ {
+ osel_memcpy(resp->data_p, user_req.rsp.pbuf, user_req.rsp.len);
+ resp->data_p += user_req.rsp.len;
+ }
+
+ return TRUE;
+}
+/**
+ * @brief 写入校准记录(操作日期和操作人员)
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ * @note
+ */
+static BOOL hart_slave_command_167_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ hart_user_req_t user_req;
+ if (hart_frame_data_length_check(req->data_length, sizeof(hart_command_167_t), (uint8_t *)&resp->code) == FALSE)
+ {
+ return TRUE;
+ }
+ osel_memcpy((uint8_t *)&user_req.data.command_167, (uint8_t *)&req->data.command_167, sizeof(hart_command_167_t));
+
+ if (FALSE == hart_user_common_event(HART_COMMAND_167_EVENT, (void *)&user_req))
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_64;
+ return TRUE;
+ }
+
+ return TRUE;
+}
+
+/**
+ * @brief 读取部分行程警报
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ * @note
+ */
+static BOOL hart_slave_command_168_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ hart_user_req_t user_req;
+ if (FALSE == hart_user_common_event(HART_COMMAND_168_EVENT, (void *)&user_req))
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_64;
+ return TRUE;
+ }
+ if (user_req.rsp.len != 0)
+ {
+ osel_memcpy(resp->data_p, user_req.rsp.pbuf, user_req.rsp.len);
+ resp->data_p += user_req.rsp.len;
+ }
+ return TRUE;
+}
+
+/**
+ * @brief 读取制造信息序列号
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ * @note
+ */
+static BOOL hart_slave_command_170_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ if (hart_frame_data_length_check(req->data_length, sizeof(hart_command_170_t), (uint8_t *)&resp->code) == FALSE)
+ {
+ return TRUE;
+ }
+ hart_user_req_t user_req;
+ osel_memcpy((uint8_t *)&user_req.data.command_170, (uint8_t *)&req->data.command_170, sizeof(hart_command_170_t));
+ if (FALSE == hart_user_common_event(HART_COMMAND_170_EVENT, (void *)&user_req))
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_64;
+ return TRUE;
+ }
+ if (user_req.rsp.len != 0)
+ {
+ osel_memcpy(resp->data_p, user_req.rsp.pbuf, user_req.rsp.len);
+ resp->data_p += user_req.rsp.len;
+ }
+ return TRUE;
+}
+
+static BOOL hart_slave_command_187_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ if (hart_frame_data_length_check(req->data_length, sizeof(hart_command_187_t), (uint8_t *)&resp->code) == FALSE)
+ {
+ return TRUE;
+ }
+ hart_user_req_t user_req;
+ osel_memcpy((uint8_t *)&user_req.data.command_187, (uint8_t *)&req->data.command_187, sizeof(hart_command_187_t));
+ if (FALSE == hart_user_common_event(HART_COMMAND_187_EVENT, (void *)&user_req))
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_64;
+ return TRUE;
+ }
+ if (user_req.rsp.len != 0)
+ {
+ osel_memcpy(resp->data_p, user_req.rsp.pbuf, user_req.rsp.len);
+ resp->data_p += user_req.rsp.len;
+ }
+ return TRUE;
+}
+
+/**
+ * @brief 读取NVM非易失性存储器数据
+ * @param {hart_command_req_t} *req
+ * @param {hart_response_t} *resp
+ * @return {*}
+ * @note
+ */
+static BOOL hart_slave_command_200_req(const hart_command_req_t *const req, hart_response_t *resp)
+{
+ if (hart_frame_data_length_check(req->data_length, sizeof(hart_command_200_t), (uint8_t *)&resp->code) == FALSE)
+ {
+ return TRUE;
+ }
+ hart_user_req_t user_req;
+ osel_memcpy((uint8_t *)&user_req.data.command_200, (uint8_t *)&req->data.command_200, sizeof(hart_command_200_t));
+ if (FALSE == hart_user_common_event(HART_COMMAND_200_EVENT, (void *)&user_req))
+ {
+ resp->code = RESPONSE_COMMUNICATION_CODE_64;
+ return TRUE;
+ }
+ if (user_req.rsp.len != 0)
+ {
+ osel_memcpy(resp->data_p, user_req.rsp.pbuf, user_req.rsp.len);
+ resp->data_p += user_req.rsp.len;
+ }
+ return TRUE;
+}
+
+/**
+ * @brief 用户自定义指令初始化
+ * @return {*}
+ */
+void hart_slave_req_init_user(void)
+{
+ hart_command_ptr_arr[HART_COMMAND_109] = hart_slave_command_109_req; // 突发模式控制V5
+ // 128-253 设备特定
+ hart_command_ptr_arr[HART_COMMAND_129] = hart_slave_command_129_req; // 用户自定义读取参数
+ hart_command_ptr_arr[HART_COMMAND_130] = hart_slave_command_130_req; // 用户自定义设置参数
+ hart_command_ptr_arr[HART_COMMAND_131] = hart_slave_command_131_req; // 写入整定参数
+ hart_command_ptr_arr[HART_COMMAND_132] = hart_slave_command_132_req; // 读取整定参数类型
+ hart_command_ptr_arr[HART_COMMAND_133] = hart_slave_command_133_req; // 读取整定参数
+ hart_command_ptr_arr[HART_COMMAND_134] = hart_slave_command_134_req; // 读取文件内容
+ hart_command_ptr_arr[HART_COMMAND_135] = hart_slave_command_135_req; // 写入文件
+ hart_command_ptr_arr[HART_COMMAND_136] = hart_slave_command_136_req; // 读取/解除/写入EEPROM
+ hart_command_ptr_arr[HART_COMMAND_138] = hart_slave_command_138_req; // 读取其他状态
+ hart_command_ptr_arr[HART_COMMAND_140] = hart_slave_command_140_req; // 读取触发器定义的内容
+ hart_command_ptr_arr[HART_COMMAND_141] = hart_slave_command_141_req; // 写保护
+ hart_command_ptr_arr[HART_COMMAND_142] = hart_slave_command_142_req; // 校准
+ hart_command_ptr_arr[HART_COMMAND_143] = hart_slave_command_143_req; // 设置阀门序列号
+ hart_command_ptr_arr[HART_COMMAND_144] = hart_slave_command_144_req; // 读取阀门序列号
+ hart_command_ptr_arr[HART_COMMAND_145] = hart_slave_command_145_req; // 读取仪器序列号
+ hart_command_ptr_arr[HART_COMMAND_146] = hart_slave_command_146_req; // 读取标准跨度信息
+ hart_command_ptr_arr[HART_COMMAND_147] = hart_slave_command_147_req; // 读取设备等级
+ hart_command_ptr_arr[HART_COMMAND_149] = hart_slave_command_149_req; // 设置仪器时间
+ hart_command_ptr_arr[HART_COMMAND_150] = hart_slave_command_150_req; // 读取仪器时间
+ hart_command_ptr_arr[HART_COMMAND_151] = hart_slave_command_151_req; // 读取版本信息
+ hart_command_ptr_arr[HART_COMMAND_153] = hart_slave_command_153_req; // 读取校准记录
+ hart_command_ptr_arr[HART_COMMAND_154] = hart_slave_command_154_req; // 设置仪器序列号
+ hart_command_ptr_arr[HART_COMMAND_155] = hart_slave_command_155_req; // 执行诊断
+ hart_command_ptr_arr[HART_COMMAND_156] = hart_slave_command_156_req; // 读取诊断状态
+ hart_command_ptr_arr[HART_COMMAND_157] = hart_slave_command_157_req; // 停止诊断
+ hart_command_ptr_arr[HART_COMMAND_158] = hart_slave_command_158_req; // 在线诊断测试
+ hart_command_ptr_arr[HART_COMMAND_162] = hart_slave_command_162_req; // 设置气源气压/A口/B口
+ hart_command_ptr_arr[HART_COMMAND_164] = hart_slave_command_164_req; // 读取规格表数据
+ hart_command_ptr_arr[HART_COMMAND_165] = hart_slave_command_165_req; // 写入规格表数据
+ hart_command_ptr_arr[HART_COMMAND_167] = hart_slave_command_167_req; // 写入操作日期和用户
+ hart_command_ptr_arr[HART_COMMAND_168] = hart_slave_command_168_req; // 读取部分行程警报
+ hart_command_ptr_arr[HART_COMMAND_170] = hart_slave_command_170_req; // 读取制造信息序列号
+ hart_command_ptr_arr[HART_COMMAND_187] = hart_slave_command_187_req; // 基金会测试指令
+ hart_command_ptr_arr[HART_COMMAND_200] = hart_slave_command_200_req; // 读取制造信息序列号
+
+ // 254-511 自定义指令
+}
diff --git a/User/hart/test/.gitignore b/User/hart/test/.gitignore
new file mode 100644
index 0000000..8ea7b5d
--- /dev/null
+++ b/User/hart/test/.gitignore
@@ -0,0 +1,60 @@
+# Prerequisites
+*.d
+
+# Object files
+*.o
+*.ko
+*.obj
+*.elf
+
+# Linker output
+*.ilk
+*.map
+*.exp
+
+# Precompiled Headers
+*.gch
+*.pch
+
+# Libraries
+*.lib
+*.a
+*.la
+*.lo
+
+# Shared objects (inc. Windows DLLs)
+*.dll
+*.so
+*.so.*
+*.dylib
+
+# Executables
+*.exe
+*.out
+*.app
+*.i*86
+*.x86_64
+*.hex
+
+# Debug files
+*.dSYM/
+*.su
+*.idb
+*.pdb
+
+# Kernel Module Compile Results
+*.mod*
+*.cmd
+*.xml
+*.iml
+*.pyc
+
+
+.tmp_versions/
+modules.order
+Module.symvers
+Mkfile.old
+dkms.conf
+venv/
+doc/
+report/
diff --git a/User/hart/test/LICENSE b/User/hart/test/LICENSE
new file mode 100644
index 0000000..9e32cde
--- /dev/null
+++ b/User/hart/test/LICENSE
@@ -0,0 +1,127 @@
+ 木兰宽松许可证, 第2版
+
+ 木兰宽松许可证, 第2版
+ 2020年1月 http://license.coscl.org.cn/MulanPSL2
+
+
+ 您对“软件”的复制、使用、修改及分发受木兰宽松许可证,第2版(“本许可证”)的如下条款的约束:
+
+ 0. 定义
+
+ “软件”是指由“贡献”构成的许可在“本许可证”下的程序和相关文档的集合。
+
+ “贡献”是指由任一“贡献者”许可在“本许可证”下的受版权法保护的作品。
+
+ “贡献者”是指将受版权法保护的作品许可在“本许可证”下的自然人或“法人实体”。
+
+ “法人实体”是指提交贡献的机构及其“关联实体”。
+
+ “关联实体”是指,对“本许可证”下的行为方而言,控制、受控制或与其共同受控制的机构,此处的控制是指有受控方或共同受控方至少50%直接或间接的投票权、资金或其他有价证券。
+
+ 1. 授予版权许可
+
+ 每个“贡献者”根据“本许可证”授予您永久性的、全球性的、免费的、非独占的、不可撤销的版权许可,您可以复制、使用、修改、分发其“贡献”,不论修改与否。
+
+ 2. 授予专利许可
+
+ 每个“贡献者”根据“本许可证”授予您永久性的、全球性的、免费的、非独占的、不可撤销的(根据本条规定撤销除外)专利许可,供您制造、委托制造、使用、许诺销售、销售、进口其“贡献”或以其他方式转移其“贡献”。前述专利许可仅限于“贡献者”现在或将来拥有或控制的其“贡献”本身或其“贡献”与许可“贡献”时的“软件”结合而将必然会侵犯的专利权利要求,不包括对“贡献”的修改或包含“贡献”的其他结合。如果您或您的“关联实体”直接或间接地,就“软件”或其中的“贡献”对任何人发起专利侵权诉讼(包括反诉或交叉诉讼)或其他专利维权行动,指控其侵犯专利权,则“本许可证”授予您对“软件”的专利许可自您提起诉讼或发起维权行动之日终止。
+
+ 3. 无商标许可
+
+ “本许可证”不提供对“贡献者”的商品名称、商标、服务标志或产品名称的商标许可,但您为满足第4条规定的声明义务而必须使用除外。
+
+ 4. 分发限制
+
+ 您可以在任何媒介中将“软件”以源程序形式或可执行形式重新分发,不论修改与否,但您必须向接收者提供“本许可证”的副本,并保留“软件”中的版权、商标、专利及免责声明。
+
+ 5. 免责声明与责任限制
+
+ “软件”及其中的“贡献”在提供时不带任何明示或默示的担保。在任何情况下,“贡献者”或版权所有者不对任何人因使用“软件”或其中的“贡献”而引发的任何直接或间接损失承担责任,不论因何种原因导致或者基于何种法律理论,即使其曾被建议有此种损失的可能性。
+
+ 6. 语言
+ “本许可证”以中英文双语表述,中英文版本具有同等法律效力。如果中英文版本存在任何冲突不一致,以中文版为准。
+
+ 条款结束
+
+ 如何将木兰宽松许可证,第2版,应用到您的软件
+
+ 如果您希望将木兰宽松许可证,第2版,应用到您的新软件,为了方便接收者查阅,建议您完成如下三步:
+
+ 1, 请您补充如下声明中的空白,包括软件名、软件的首次发表年份以及您作为版权人的名字;
+
+ 2, 请您在软件包的一级目录下创建以“LICENSE”为名的文件,将整个许可证文本放入该文件中;
+
+ 3, 请将如下声明文本放入每个源文件的头部注释中。
+
+ Copyright (c) [Year] [name of copyright holder]
+ [Software Name] is licensed under Mulan PSL v2.
+ You can use this software according to the terms and conditions of the Mulan PSL v2.
+ You may obtain a copy of Mulan PSL v2 at:
+ http://license.coscl.org.cn/MulanPSL2
+ THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
+ See the Mulan PSL v2 for more details.
+
+
+ Mulan Permissive Software License,Version 2
+
+ Mulan Permissive Software License,Version 2 (Mulan PSL v2)
+ January 2020 http://license.coscl.org.cn/MulanPSL2
+
+ Your reproduction, use, modification and distribution of the Software shall be subject to Mulan PSL v2 (this License) with the following terms and conditions:
+
+ 0. Definition
+
+ Software means the program and related documents which are licensed under this License and comprise all Contribution(s).
+
+ Contribution means the copyrightable work licensed by a particular Contributor under this License.
+
+ Contributor means the Individual or Legal Entity who licenses its copyrightable work under this License.
+
+ Legal Entity means the entity making a Contribution and all its Affiliates.
+
+ Affiliates means entities that control, are controlled by, or are under common control with the acting entity under this License, ‘control’ means direct or indirect ownership of at least fifty percent (50%) of the voting power, capital or other securities of controlled or commonly controlled entity.
+
+ 1. Grant of Copyright License
+
+ Subject to the terms and conditions of this License, each Contributor hereby grants to you a perpetual, worldwide, royalty-free, non-exclusive, irrevocable copyright license to reproduce, use, modify, or distribute its Contribution, with modification or not.
+
+ 2. Grant of Patent License
+
+ Subject to the terms and conditions of this License, each Contributor hereby grants to you a perpetual, worldwide, royalty-free, non-exclusive, irrevocable (except for revocation under this Section) patent license to make, have made, use, offer for sale, sell, import or otherwise transfer its Contribution, where such patent license is only limited to the patent claims owned or controlled by such Contributor now or in future which will be necessarily infringed by its Contribution alone, or by combination of the Contribution with the Software to which the Contribution was contributed. The patent license shall not apply to any modification of the Contribution, and any other combination which includes the Contribution. If you or your Affiliates directly or indirectly institute patent litigation (including a cross claim or counterclaim in a litigation) or other patent enforcement activities against any individual or entity by alleging that the Software or any Contribution in it infringes patents, then any patent license granted to you under this License for the Software shall terminate as of the date such litigation or activity is filed or taken.
+
+ 3. No Trademark License
+
+ No trademark license is granted to use the trade names, trademarks, service marks, or product names of Contributor, except as required to fulfill notice requirements in Section 4.
+
+ 4. Distribution Restriction
+
+ You may distribute the Software in any medium with or without modification, whether in source or executable forms, provided that you provide recipients with a copy of this License and retain copyright, patent, trademark and disclaimer statements in the Software.
+
+ 5. Disclaimer of Warranty and Limitation of Liability
+
+ THE SOFTWARE AND CONTRIBUTION IN IT ARE PROVIDED WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED. IN NO EVENT SHALL ANY CONTRIBUTOR OR COPYRIGHT HOLDER BE LIABLE TO YOU FOR ANY DAMAGES, INCLUDING, BUT NOT LIMITED TO ANY DIRECT, OR INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES ARISING FROM YOUR USE OR INABILITY TO USE THE SOFTWARE OR THE CONTRIBUTION IN IT, NO MATTER HOW IT’S CAUSED OR BASED ON WHICH LEGAL THEORY, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+ 6. Language
+
+ THIS LICENSE IS WRITTEN IN BOTH CHINESE AND ENGLISH, AND THE CHINESE VERSION AND ENGLISH VERSION SHALL HAVE THE SAME LEGAL EFFECT. IN THE CASE OF DIVERGENCE BETWEEN THE CHINESE AND ENGLISH VERSIONS, THE CHINESE VERSION SHALL PREVAIL.
+
+ END OF THE TERMS AND CONDITIONS
+
+ How to Apply the Mulan Permissive Software License,Version 2 (Mulan PSL v2) to Your Software
+
+ To apply the Mulan PSL v2 to your work, for easy identification by recipients, you are suggested to complete following three steps:
+
+ i Fill in the blanks in following statement, including insert your software name, the year of the first publication of your software, and your name identified as the copyright owner;
+
+ ii Create a file named “LICENSE” which contains the whole context of this License in the first directory of your software package;
+
+ iii Attach the statement to the appropriate annotated syntax at the beginning of each source file.
+
+
+ Copyright (c) [Year] [name of copyright holder]
+ [Software Name] is licensed under Mulan PSL v2.
+ You can use this software according to the terms and conditions of the Mulan PSL v2.
+ You may obtain a copy of Mulan PSL v2 at:
+ http://license.coscl.org.cn/MulanPSL2
+ THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
+ See the Mulan PSL v2 for more details.
diff --git a/User/hart/test/README.md b/User/hart/test/README.md
new file mode 100644
index 0000000..02d51ff
--- /dev/null
+++ b/User/hart/test/README.md
@@ -0,0 +1,12 @@
+# 简介
+
+本项目主要是 HART 协议,通过 python 调用动态库接口。
+
+# 环境安装
+
+mingw、python3.7-win32
+
+# HART 模块测试说明
+
+测试文件放在 test 目录中,通过执行 makefile 实现接口的全覆盖测试,
+测试结果放在 test/report 目录中
diff --git a/User/hart/test/main.py b/User/hart/test/main.py
new file mode 100644
index 0000000..4562948
--- /dev/null
+++ b/User/hart/test/main.py
@@ -0,0 +1,17 @@
+'''
+FilePath: \hart\main.py
+Author: shenghao.xu
+Date: 2023-03-14 08:51:18
+LastEditors: shenghao.xu
+LastEditTime: 2023-05-05 10:14:50
+Descripttion:
+'''
+import os
+
+
+def main():
+ print('hello world')
+
+
+if __name__ == '__main__':
+ main()
diff --git a/User/hart/test/src/pkg/__init__.py b/User/hart/test/src/pkg/__init__.py
new file mode 100644
index 0000000..cb788bd
--- /dev/null
+++ b/User/hart/test/src/pkg/__init__.py
@@ -0,0 +1,10 @@
+'''
+Author: shenghao.xu
+Date: 2023-03-30 13:14:52
+LastEditors: shenghao.xu
+LastEditTime: 2023-03-30 13:27:06
+FilePath: \hart\test\pkg\__init__.py
+Description:
+email:545403892@qq.com
+Copyright (c) 2023 by shenghao.xu, All Rights Reserved.
+'''
diff --git a/User/hart/test/src/pkg/common.py b/User/hart/test/src/pkg/common.py
new file mode 100644
index 0000000..d339d20
--- /dev/null
+++ b/User/hart/test/src/pkg/common.py
@@ -0,0 +1,130 @@
+'''
+FilePath: \hart\test\pkg\common.py
+Author: shenghao.xu
+Date: 2023-03-15 10:17:55
+LastModifiedBy: shenghao.xu
+LastEditTime: 2023-09-20 15:36:00
+Descripttion:
+'''
+from ctypes import *
+import os
+import struct
+import sys
+
+
+def print_hex_data_space(bytes, uppercase=False):
+ l = ['{:02x} '.format(int(i)) for i in bytes]
+ if uppercase:
+ l = [i.upper() for i in l]
+ print("".join(l))
+ pass
+
+
+def print_hex_space(bytes):
+ l = ['0x{:02x} '.format(int(i)) for i in bytes]
+ print("".join(l))
+ pass
+
+
+# 十六进制打印
+def print_hex(bytes):
+ l = [hex(int(i)) for i in bytes]
+ print("".join(l))
+ pass
+
+
+# 数组异或操作
+def xor(bytes):
+ result = 0
+ for i in bytes:
+ result ^= i
+ return result
+
+
+# bytearray 转 ctypes
+def bytes_to_ctypes(bytes):
+ return (c_ubyte * len(bytes))(*bytes)
+
+
+# 字符串转assic码数组
+def str_to_ascii(str):
+ return [ord(i) for i in str]
+
+# 字符串转assic-6码数组
+def encode_ascii_6(input, input_length, output):
+ adjusted_input = [0x20]*input_length
+ i = 0
+
+ for i in range(input_length):
+ if input[i] == 0x00:
+ adjusted_input[i] = 0x20
+ continue
+
+ adjusted_input[i] = input[i] - 0x40 if input[i] >= 0x40 else input[i]
+
+ acs8_len = i + 1
+ acs6_len = acs8_len * 6 // 8
+
+ for i in range(acs6_len):
+ pos = i * 8 // 6
+ val = adjusted_input[pos] & 0x3f
+ valNext = (adjusted_input[pos + 1] & 0x3f) if pos + 1 < acs8_len else 0x20
+ newVal = 0
+ if i % 3 == 0:
+ newVal = val << 2
+ newVal += valNext >> 4
+ elif i % 3 == 1:
+ newVal = val << 4
+ newVal += valNext >> 2
+ elif i % 3 == 2:
+ newVal = val << 6
+ newVal += valNext
+ output[i] = newVal
+
+
+# assic码数组转字符串
+def ascii_to_str(ascii):
+ # ascii 遇到00 截断
+ if 0 in ascii:
+ ascii = ascii[:ascii.index(0)]
+ return ''.join([chr(i) for i in ascii])
+
+
+# 数组B的值复制到数组A,从数组A的第offset个元素开始
+def copy_to_array(A, B, offset):
+ for i in range(len(B)):
+ A[offset + i] = B[i]
+ pass
+
+
+# 将bytes转换为float32
+def bytes2float32slice(bytes):
+ x = []
+ for i in range(int(len(bytes) / 4)):
+ data = bytes[i * 4: (i * 4) + 4]
+ a = struct.unpack('f', data)
+ x.append(float(a[0]))
+ return x
+
+def convert_time(t):
+ t = (t / 32)
+ ms = t % 1000
+ t = t / 1000
+ h = t / 3600
+ m = (t - (h) * 3600) / 60
+ s = t - (h) * 3600 - (m) * 60
+ return h,m,s
+
+def convert_timestrap(h,m,s,ms):
+ t = (h * 3600 + m * 60 + s) * 1000 + ms
+ t = (t) * 32
+ return t
+
+class HiddenPrints:
+ def __enter__(self):
+ self._original_stdout = sys.stdout
+ sys.stdout = open(os.devnull, 'w')
+
+ def __exit__(self, exc_type, exc_val, exc_tb):
+ sys.stdout.close()
+ sys.stdout = self._original_stdout
diff --git a/User/hart/test/src/pkg/entity.py b/User/hart/test/src/pkg/entity.py
new file mode 100644
index 0000000..bdb4f17
--- /dev/null
+++ b/User/hart/test/src/pkg/entity.py
@@ -0,0 +1,1545 @@
+'''
+FilePath: \hart\test\pkg\entity.py
+Author: shenghao.xu
+Date: 2023-03-29 22:18:08
+LastModifiedBy: shenghao.xu
+LastEditTime: 2024-08-13 14:36:03
+Descripttion:
+'''
+import binascii
+from ctypes import *
+import datetime
+import sys
+import os
+import numpy as np
+
+sys.path.append(os.path.dirname(os.path.abspath(__file__))) # 添加项目路径
+from common import print_hex_data_space, bytes_to_ctypes, str_to_ascii, copy_to_array, convert_timestrap, encode_ascii_6, bytes2float32slice # noqa
+
+response_func = CFUNCTYPE(c_void_p, c_ubyte, POINTER(c_ubyte), c_ushort)
+flash_read_func = CFUNCTYPE(c_char_p, c_uint32, POINTER(c_ubyte), c_ushort)
+flash_write_func = CFUNCTYPE(c_char_p, c_uint32, POINTER(c_ubyte), c_ushort)
+perform_self_test_func = CFUNCTYPE(c_void_p)
+device_reset_func = CFUNCTYPE(c_void_p)
+squawk_control_func = CFUNCTYPE(c_void_p, c_bool, c_uint8)
+armed_func = CFUNCTYPE(c_char_p)
+user_common_event_func = CFUNCTYPE(c_char_p,c_uint32,POINTER(c_ubyte))
+
+class hart_interface_t(Structure):
+ _fields_ = [
+ ("response", response_func),
+ ("flash_read", flash_read_func),
+ ("flash_write", flash_write_func),
+ ("perform_self_test", perform_self_test_func),
+ ("device_reset", device_reset_func),
+ ("squawk_control", squawk_control_func),
+ ("armed", armed_func),
+ # ("user_common_event", user_common_event_func),
+ ]
+ pass
+
+
+class hart_master_init_t(Structure): # 模块主机初始化接口参数
+ _pack_ = 1 # 1字节对齐
+ # address_bit 为1时表示基本主设备,为0时表示副主设备
+ _fields_ = [("address_bit", c_ubyte)]
+ pass
+
+
+class hart_slave_init_t(Structure): # 模块从机初始化接口参数
+ _pack_ = 1 # 1字节对齐
+ _fields_ = []
+ pass
+
+
+class hart_command_none_t(Structure):
+ _pack_ = 1 # 1字节对齐
+ _fields_ = []
+ pass
+
+
+class hart_command_6_t(Structure):
+ _pack_ = 1 # 1字节对齐
+ _fields_ = [("poll_address", c_ubyte), ("loop_current_mode", c_ubyte)]
+ pass
+
+
+class hart_command_11_t(Structure):
+ _pack_ = 1 # 1字节对齐
+ _fields_ = [("tag", c_ubyte * 6)]
+ pass
+
+
+class hart_command_17_t(Structure):
+ _pack_ = 1 # 1字节对齐
+ _fields_ = [("message", c_ubyte * 24)]
+ pass
+
+
+class hart_command_18_t(Structure):
+ _pack_ = 1 # 1字节对齐
+ _fields_ = [("tag", c_ubyte * 6), ("descriptor",
+ c_ubyte * 12), ("date", c_ubyte * 3)]
+ pass
+
+
+class hart_command_19_t(Structure):
+ _pack_ = 1 # 1字节对齐
+ _fields_ = [("final_assembly_number", c_ubyte * 3)]
+ pass
+
+
+class hart_command_21_t(Structure):
+ _pack_ = 1 # 1字节对齐
+ _fields_ = [("long_tag", c_ubyte * 32)]
+ pass
+
+
+class hart_command_22_t(Structure):
+ _pack_ = 1 # 1字节对齐
+ _fields_ = [("long_tag", c_ubyte * 32)]
+ pass
+
+
+class hart_command_38_t(Structure):
+ _pack_ = 1 # 1字节对齐
+ _fields_ = [("configuration_change_counter", c_uint16)]
+ pass
+
+
+class hart_command_33_t(Structure):
+ _pack_ = 1 # 1字节对齐
+ _fields_ = [("slot_0", c_uint8), ("slot_1", c_uint8),
+ ("slot_2", c_uint8), ("slot_3", c_uint8)]
+ pass
+
+
+class hart_command_34_t(Structure):
+ _pack_ = 1 # 1字节对齐
+ _fields_ = [("pv_damping_value", c_float)]
+ pass
+
+
+class hart_command_35_t(Structure):
+ _pack_ = 1 # 1字节对齐
+ _fields_ = [("pv_upper_and_lower_range_values_units_code", c_uint8), ("pv_upper_range_value", c_float),
+ ("pv_lower_range_value", c_float)]
+ pass
+
+
+class hart_command_39_t(Structure):
+ _pack_ = 1 # 1字节对齐
+ _fields_ = [("control_code", c_uint8)]
+ pass
+
+
+class hart_command_40_t(Structure):
+ _pack_ = 1 # 1字节对齐
+ _fields_ = [("pv_fixed_current_level", c_float)]
+ pass
+
+
+class hart_command_44_t(Structure):
+ _pack_ = 1 # 1字节对齐
+ _fields_ = [("pv_units_code", c_uint8)]
+ pass
+
+
+class hart_command_45_t(Structure):
+ _pack_ = 1 # 1字节对齐
+ _fields_ = [("pv_loop_current_level", c_float)]
+ pass
+
+
+class hart_command_46_t(Structure):
+ _pack_ = 1 # 1字节对齐
+ _fields_ = [("pv_loop_current_level", c_float)]
+ pass
+
+
+class hart_command_47_t(Structure):
+ _pack_ = 1 # 1字节对齐
+ _fields_ = [("pv_transfer_function_code", c_uint8)]
+ pass
+
+
+class hart_command_49_t(Structure):
+ _pack_ = 1 # 1字节对齐
+ _fields_ = [("pv_transducer_serial_number", c_uint8 * 3)]
+ pass
+
+
+class hart_command_51_t(Structure):
+ _pack_ = 1 # 1字节对齐
+ _fields_ = [("device_ariables", c_uint8 * 4)]
+ pass
+
+
+class hart_command_52_t(Structure):
+ _pack_ = 1 # 1字节对齐
+ _fields_ = [("device_ariable", c_uint8)]
+ pass
+
+
+class hart_command_53_t(Structure):
+ _pack_ = 1 # 1字节对齐
+ _fields_ = [("device_ariable", c_uint8),
+ ("device_ariable_unit_code", c_uint8)]
+ pass
+
+
+class hart_command_54_t(Structure):
+ _pack_ = 1 # 1字节对齐
+ _fields_ = [("device_ariable", c_uint8)]
+ pass
+
+
+class hart_command_55_t(Structure):
+ _pack_ = 1 # 1字节对齐
+ _fields_ = [("device_ariable", c_uint8), ("damping_value", c_float)]
+ pass
+
+
+class hart_command_56_t(Structure):
+ _pack_ = 1 # 1字节对齐
+ _fields_ = [("device_ariable", c_uint8), ("serial_number", c_uint8 * 3)]
+ pass
+
+
+class hart_command_58_t(Structure):
+ _pack_ = 1 # 1字节对齐
+ _fields_ = [("unit_tag", c_uint8 * 6), ("unit_descriptor",
+ c_uint8 * 12), ("unit_date", c_uint8 * 3)]
+ pass
+
+
+class hart_command_59_t(Structure):
+ _pack_ = 1 # 1字节对齐
+ _fields_ = [("s2m_preambles", c_uint8)]
+ pass
+
+
+class hart_command_60_t(Structure):
+ _pack_ = 1 # 1字节对齐
+ _fields_ = [("analog_channel_number_code", c_uint8)]
+ pass
+
+
+class hart_command_62_t(Structure):
+ _pack_ = 1 # 1字节对齐
+ _fields_ = [("slot0", c_uint8), ("slot1", c_uint8),
+ ("slot2", c_uint8), ("slot3", c_uint8)]
+ pass
+
+
+class hart_command_63_t(Structure):
+ _pack_ = 1 # 1字节对齐
+ _fields_ = [("analog_channel_number_code", c_uint8)]
+ pass
+
+
+class hart_command_64_t(Structure):
+ _pack_ = 1 # 1字节对齐
+ _fields_ = [("analog_channel_number_code", c_uint8),
+ ("damping_value", c_float)]
+ pass
+
+
+class hart_command_65_t(Structure):
+ _pack_ = 1 # 1字节对齐
+ _fields_ = [("analog_channel_number_code", c_uint8), ("upper_and_lower_range_values_units_code", c_uint8),
+ ("upper_range_value", c_float), ("lower_range_value", c_float)]
+ pass
+
+
+class hart_command_66_t(Structure):
+ _pack_ = 1 # 1字节对齐
+ _fields_ = [("analog_channel_number_code", c_uint8), ("units_code", c_uint8),
+ ("fixed_analog_channel_level", c_float)]
+ pass
+
+
+class hart_command_67_t(Structure):
+ _pack_ = 1 # 1字节对齐
+ _fields_ = [("analog_channel_number_code", c_uint8), ("units_code", c_uint8),
+ ("actual_analog_channel_level", c_float)]
+ pass
+
+
+class hart_command_68_t(Structure):
+ _pack_ = 1 # 1字节对齐
+ _fields_ = [("analog_channel_number_code", c_uint8), ("units_code", c_uint8),
+ ("externally_measured_analog_channel_level", c_float)]
+ pass
+
+
+class hart_command_69_t(Structure):
+ _pack_ = 1 # 1字节对齐
+ _fields_ = [("analog_channel_number_code", c_uint8),
+ ("transfer_function_code", c_uint8),]
+ pass
+
+
+class hart_command_70_t(Structure):
+ _pack_ = 1 # 1字节对齐
+ _fields_ = [("analog_channel_number_code", c_uint8)]
+ pass
+
+
+class hart_command_71_t(Structure):
+ _pack_ = 1 # 1字节对齐
+ _fields_ = [("lock_code", c_uint8)]
+ pass
+
+
+class hart_command_72_t(Structure):
+ _pack_ = 1 # 1字节对齐
+ _fields_ = [("squawk_control_code", c_uint8)]
+ pass
+
+
+class hart_command_75_t(Structure):
+ _pack_ = 1 # 1字节对齐
+ _fields_ = [("card", c_uint8), ("channel", c_uint8),
+ ("poll_address", c_uint8)]
+ pass
+
+
+class hart_command_78_command_t(Structure):
+ _pack_ = 1 # 1字节对齐
+ _fields_ = [("command", c_uint16),
+ ("count", c_uint8), ("payload", c_uint8)]
+ pass
+
+
+class hart_command_78_t(Structure):
+ _pack_ = 1 # 1字节对齐
+ _fields_ = [("number", c_uint8), ("command", hart_command_78_command_t)]
+ pass
+
+
+class hart_command_79_t(Structure):
+ _pack_ = 1 # 1字节对齐
+ _fields_ = [("device_ariable", c_uint8), ("device_ariable_command_code", c_uint8), ("device_ariable_unit_code", c_uint8),
+ ("device_ariable_value", c_float), ("status", c_uint8)]
+ pass
+
+
+class hart_command_80_t(Structure):
+ _pack_ = 1 # 1字节对齐
+ _fields_ = [("device_ariable", c_uint8)]
+ pass
+
+
+class hart_command_81_t(Structure):
+ _pack_ = 1 # 1字节对齐
+ _fields_ = [("device_ariable", c_uint8)]
+ pass
+
+
+class hart_command_82_t(Structure):
+ _pack_ = 1 # 1字节对齐
+ _fields_ = [("device_ariable", c_uint8), ("trim_points", c_uint8),
+ ("units_code", c_uint8), ("value", c_float)]
+ pass
+
+
+class hart_command_83_t(Structure):
+ _pack_ = 1 # 1字节对齐
+ _fields_ = [("device_ariable", c_uint8)]
+ pass
+
+
+class hart_command_84_t(Structure):
+ _pack_ = 1 # 1字节对齐
+ _fields_ = [("identifier", c_uint16)]
+ pass
+
+
+class hart_command_85_t(Structure):
+ _pack_ = 1 # 1字节对齐
+ _fields_ = [("card", c_uint8), ("channel", c_uint8)]
+ pass
+
+
+class hart_command_86_t(Structure):
+ _pack_ = 1 # 1字节对齐
+ _fields_ = [("identifier", c_uint16)]
+ pass
+
+
+class hart_command_87_t(Structure):
+ _pack_ = 1 # 1字节对齐
+ _fields_ = [("master_mode", c_uint8)]
+ pass
+
+
+class hart_command_88_t(Structure):
+ _pack_ = 1 # 1字节对齐
+ _fields_ = [("retry_count", c_uint8)]
+ pass
+
+
+class hart_command_89_t(Structure):
+ _pack_ = 1 # 1字节对齐
+ _fields_ = [("time_set_code", c_uint8), ("date", c_uint8 * 3),
+ ("time", c_uint32), ("transmission_time", c_uint16)]
+ pass
+
+
+class hart_command_91_t(Structure):
+ _pack_ = 1 # 1字节对齐
+ _fields_ = [("trend_number", c_uint8)]
+ pass
+
+
+class hart_command_92_t(Structure):
+ _pack_ = 1 # 1字节对齐
+ _fields_ = [("trend_number", c_uint8), ("trend_code", c_uint8),
+ ("device_variable_code", c_uint8), ("trend_sample_interval", c_uint32)]
+ pass
+
+
+class hart_command_93_t(Structure):
+ _pack_ = 1 # 1字节对齐
+ _fields_ = [("trend_number", c_uint8)]
+ pass
+
+
+class hart_command_96_t(Structure):
+ _pack_ = 1 # 1字节对齐
+ _fields_ = [("action_number", c_uint8)]
+ pass
+
+
+class hart_command_97_t(Structure):
+ _pack_ = 1 # 1字节对齐
+ _fields_ = [("action_number", c_uint8), ("action_control_code", c_uint8), ("device_variable_code",
+ c_uint8), ("command_number", c_uint16), ("trigger_date", c_uint8*3), ("trigger_time", c_uint32)]
+ pass
+
+
+class hart_command_98_t(Structure):
+ _pack_ = 1 # 1字节对齐
+ _fields_ = [("action_number", c_uint8)]
+ pass
+
+
+class hart_command_99_t(Structure):
+ _pack_ = 1 # 1字节对齐
+ _fields_ = [("action_number", c_uint8), ("command_number", c_uint16),
+ ("command_data_length", c_uint8), ("command_data", c_uint8*255)]
+ pass
+
+
+class hart_command_100_t(Structure):
+ _pack_ = 1 # 1字节对齐
+ _fields_ = [("pv_alarm_selection_code", c_uint8)]
+ pass
+
+
+class hart_command_101_t(Structure):
+ _pack_ = 1 # 1字节对齐
+ _fields_ = [("burst_message", c_uint8)]
+ pass
+
+
+class hart_command_102_t(Structure):
+ _pack_ = 1 # 1字节对齐
+ _fields_ = [("burst_message", c_uint8), ("sub_device_index", c_uint16)]
+ pass
+
+
+class hart_command_103_t(Structure):
+ _pack_ = 1 # 1字节对齐
+ _fields_ = [("burst_message", c_uint8), ("update_period_time",
+ c_uint32), ("max_update_period_time", c_uint32)]
+ pass
+
+
+class hart_command_104_t(Structure):
+ _pack_ = 1 # 1字节对齐
+ _fields_ = [("burst_message", c_uint8), ("burst_message_trigger_code", c_uint8),
+ ("device_variable_vlassification_for_trigger_level", c_uint8), ("units_code", c_uint8), ("trigger_level", c_float)]
+ pass
+
+
+class hart_command_105_t(Structure):
+ _pack_ = 1 # 1字节对齐
+ _fields_ = [("burst_message", c_uint8)]
+ pass
+
+
+class hart_command_107_t(Structure):
+ _pack_ = 1 # 1字节对齐
+ _fields_ = [("solts", c_uint8*8), ("burst_message", c_uint8)]
+ pass
+
+
+class hart_command_513_t(Structure):
+ _pack_ = 1 # 1字节对齐
+ _fields_ = [("country_code", c_uint16), ("si_units_control_code", c_uint8)]
+ pass
+
+class hart_command_31_t(BigEndianStructure):
+ _pack_ = 1 # 1字节对齐
+ _fields_ = [("command", c_uint16),("address", c_uint8), ("length", c_uint8)]
+ pass
+
+class hart_command_129_t(Structure):
+ _pack_ = 1 # 1字节对齐
+ _fields_ = [("data", c_uint8*5),
+ ]
+ pass
+
+class hart_command_130_t(Structure):
+ _pack_ = 1 # 1字节对齐
+ _fields_ = [("data", c_uint8*100),
+ ]
+ pass
+
+
+class hart_command_134_t(Structure):
+ _pack_ = 1 # 1字节对齐
+ _fields_ = [("file_index", c_uint8),
+ ("file_offset", c_uint16),
+ ("read_length", c_uint8),
+ ]
+ pass
+
+class hart_command_141_t(Structure):
+ _pack_ = 1 # 1字节对齐
+ _fields_ = [("write_protect_code", c_uint8),
+ ]
+ pass
+
+class hart_command_142_t(Structure):
+ _pack_ = 1 # 1字节对齐
+ _fields_ = [("code", c_uint8),
+ ]
+ pass
+
+class hart_command_155_t(BigEndianStructure):
+ _pack_ = 1 # 1字节对齐
+ _fields_ = [("reserved", c_uint8*7),
+ ("diagnostic_code",c_uint16),
+ ("sampling_time",c_uint8),
+ ("step",c_uint16),
+ ("reserved2", c_uint8*4),
+ ]
+ pass
+
+class hart_command_167_t(Structure):
+ _pack_ = 1 # 1字节对齐
+ _fields_ = [("operation_time", c_uint32),
+ ("operator", c_ubyte*26)
+ ]
+ pass
+
+class hart_command_170_t(Structure):
+ _pack_ = 1 # 1字节对齐
+ _fields_ = [("code", c_uint8)
+ ]
+ pass
+
+class hart_command_254_t(Structure):
+ _pack_ = 1 # 1字节对齐
+ _fields_ = [("model", c_uint8)]
+ pass
+
+
+class hart_command_260_t(Structure):
+ _pack_ = 1 # 1字节对齐
+ _fields_ = [
+ ("model", c_uint8),
+ ("threshold_control", c_float),
+ ("amplifier_circuit_control", c_float),
+ ("pressure_A", c_uint16),
+ ("pressure_B", c_uint16),
+ ("position_selector", c_uint8),
+ ("position_feedback_P", c_float),
+ ("position_feedback_I", c_float),
+ ("position_feedback_D", c_float),
+ ("position_feedback_amplifier_circuit_control_gain", c_uint16),
+ ("pressure_selector", c_uint8),
+ ("pressure_feedback_P", c_float),
+ ("pressure_feedback_I", c_float),
+ ("pressure_feedback_D", c_float),
+ ("pressure_feedback_amplifier_circuit_control_gain", c_uint16),
+ ("valve_model", c_uint8*32),
+ ("spring_coefficient", c_float),
+ ("gas_inlet_cross_sectional_area", c_float),
+ ("gas_opening_closing", c_uint8),
+ ]
+ pass
+
+
+class hart_command_500_t(Structure):
+ _pack_ = 1 # 1字节对齐
+ _fields_ = [("test_type", c_uint8), ("data_length", c_uint8),
+ ("data", c_uint8*32),]
+ pass
+
+
+class hart_command_500_rtc_data_t(Structure):
+ _pack_ = 1 # 1字节对齐
+ _fields_ = [("year", c_uint8),
+ ("month", c_uint8),
+ ("day", c_uint8),
+ ("weekday", c_uint8),
+ ("hour", c_uint8),
+ ("minute", c_uint8),
+ ("second", c_uint8)
+ ]
+
+ def get_bytes(self):
+ return bytes(self)
+ pass
+
+
+class hart_command_500_u16_data_t(Structure):
+ _pack_ = 1 # 1字节对齐
+ _fields_ = [("data", c_uint16),
+ ]
+
+ def get_bytes(self):
+ return bytes(self)
+ pass
+
+
+class hart_master_command_req_data_u(Union): # 模块初始化接口参数
+ _pack_ = 1 # 1字节对齐
+ _fields_ = [("command999", hart_command_none_t),
+ ("command6", hart_command_6_t),
+ ("command11", hart_command_11_t),
+ ("command17", hart_command_17_t),
+ ("command18", hart_command_18_t),
+ ("command19", hart_command_19_t),
+ ("command21", hart_command_21_t),
+ ("command22", hart_command_22_t),
+ ("command38", hart_command_38_t),
+ ("command31", hart_command_31_t),
+ ("command33", hart_command_33_t),
+ ("command34", hart_command_34_t),
+ ("command35", hart_command_35_t),
+ ("command39", hart_command_39_t),
+ ("command40", hart_command_40_t),
+ ("command44", hart_command_44_t),
+ ("command45", hart_command_45_t),
+ ("command46", hart_command_46_t),
+ ("command47", hart_command_47_t),
+ ("command49", hart_command_49_t),
+ ("command51", hart_command_51_t),
+ ("command52", hart_command_52_t),
+ ("command53", hart_command_53_t),
+ ("command54", hart_command_54_t),
+ ("command55", hart_command_55_t),
+ ("command56", hart_command_56_t),
+ ("command58", hart_command_58_t),
+ ("command59", hart_command_59_t),
+ ("command60", hart_command_60_t),
+ ("command62", hart_command_62_t),
+ ("command63", hart_command_63_t),
+ ("command64", hart_command_64_t),
+ ("command65", hart_command_65_t),
+ ("command66", hart_command_66_t),
+ ("command67", hart_command_67_t),
+ ("command68", hart_command_68_t),
+ ("command69", hart_command_69_t),
+ ("command70", hart_command_70_t),
+ ("command71", hart_command_71_t),
+ ("command72", hart_command_72_t),
+ ("command75", hart_command_75_t),
+ ("command79", hart_command_79_t),
+ ("command80", hart_command_80_t),
+ ("command81", hart_command_81_t),
+ ("command82", hart_command_82_t),
+ ("command83", hart_command_83_t),
+ ("command84", hart_command_84_t),
+ ("command85", hart_command_85_t),
+ ("command86", hart_command_86_t),
+ ("command87", hart_command_87_t),
+ ("command88", hart_command_88_t),
+ ("command89", hart_command_89_t),
+ ("command91", hart_command_91_t),
+ ("command92", hart_command_92_t),
+ ("command93", hart_command_93_t),
+ ("command96", hart_command_96_t),
+ ("command97", hart_command_97_t),
+ ("command98", hart_command_98_t),
+ ("command99", hart_command_99_t),
+ ("command100", hart_command_100_t),
+ ("command101", hart_command_101_t),
+ ("command102", hart_command_102_t),
+ ("command103", hart_command_103_t),
+ ("command104", hart_command_104_t),
+ ("command105", hart_command_105_t),
+ ("command107", hart_command_107_t),
+ ("command513", hart_command_513_t),
+ ("command129", hart_command_129_t),
+ ("command130", hart_command_130_t),
+ ("command132", hart_command_130_t),
+ ("command134", hart_command_134_t),
+ ("command141", hart_command_141_t),
+ ("command142", hart_command_142_t),
+ ("command155", hart_command_155_t),
+ ("command167", hart_command_167_t),
+ ("command170", hart_command_170_t),
+ ("command254", hart_command_254_t),
+ ("command260", hart_command_260_t),
+ ("command500", hart_command_500_t),
+ ]
+ pass
+
+
+def get_master_struct():
+ hart = hart_init_t()
+ hart.dir = 1
+ hart.master_address_bit = 0
+ hart.hart_interface_t.response = response_func(hart.hart_response_call)
+ return hart
+
+
+def get_slave_struct():
+ hart = hart_init_t()
+ hart.dir = 2
+ hart.hart_interface_t.response = response_func(hart.hart_response_call)
+ hart.hart_interface_t.flash_read = flash_read_func(hart.flash_read)
+ hart.hart_interface_t.flash_write = flash_write_func(hart.flash_write)
+ hart.hart_interface_t.perform_self_test = perform_self_test_func(
+ hart.perform_self_test)
+ hart.hart_interface_t.device_reset = device_reset_func(hart.device_reset)
+ hart.hart_interface_t.squawk_control = squawk_control_func(
+ hart.squawk_control)
+ hart.hart_interface_t.armed = armed_func(hart.armed)
+ # hart.hart_interface_t.user_common_event = user_common_event_func(hart.user_common_event)
+ return hart
+
+
+class hart_rsp_t(Structure):
+ _pack_ = 1 # 1字节对齐
+ _fields_ = [("address", c_ubyte*5),
+ ("address_length", c_ubyte),
+ ("command", c_uint32),
+ ("data_length", c_ubyte),
+ ("data", c_ubyte*254),
+ ]
+
+ def get_bytes(self):
+ return bytes(self)
+ pass
+
+
+class hart_init_t(Structure): # 模块初始化接口参数
+ _pack_ = 1 # 1字节对齐
+ _fields_ = [("hart_protocol_version", c_ubyte),
+ ("dir", c_ubyte),
+ ("master_address_bit", c_ubyte),
+ ("hart_interface_t", hart_interface_t),
+ ]
+ response = []
+
+ def __init__(self):
+ self.hart_protocol_version = 7
+ pass
+
+ def hart_response_call(self, index, ptr, length):
+ self.response = ptr[:length]
+ hart_response_call(index, ptr, length)
+
+ pass
+
+ def flash_read(self, addr, ptr, length):
+ print("flash_read:", addr, ptr, length)
+ return True
+
+ def flash_write(self, addr, ptr, length):
+ print("flash_write:", addr, ptr, length)
+ return True
+
+ def perform_self_test(self):
+ print("自检结束")
+ pass
+
+ def device_reset(self):
+ print("设备复位")
+ pass
+
+ def squawk_control(self, open, second):
+ print("squawk_control", open, second)
+
+ def armed(self):
+ print("armed")
+ return True
+
+ def user_common_event(self,evnet, data):
+ # print("user_common_event")
+ return True
+ pass
+
+
+class hart_command_req_t(Structure): # 主机请求指令接口参数
+ _pack_ = 1 # 1字节对齐
+ _anonymous_ = ("data",)
+ _fields_ = [("delimiter_type", c_ubyte),
+ # 短帧地址1个字节,长帧地址5个字节,上位机发送时从低位到高位填充,例如短地址:0x01,长地址:0x00 0x00 0x00 0x00 0x01
+ ("address", c_ubyte * 5),
+ ("command", c_uint32),
+ ("data", hart_master_command_req_data_u)]
+
+ def __init__(self):
+ self._address = (0xE6, 0x3F, 0x00, 0x00, 0x01) # 0x13, 0x09, 0x1A, 0xAA, 0x0C
+ self.command = 0
+
+ self.set_long_address() # 界定符类型: 0:短帧 1:长帧 默认1
+ pass
+
+ def set_short_address(self):
+ self.delimiter_type = 0
+ # 设置默认短地址为0
+ self.address = (0,0,0,0,0)
+ pass
+
+ def set_long_address(self):
+ self.delimiter_type = 1
+ self.address = self._address
+ pass
+
+ def set_address(self, address="0000000000"):
+ self._address = bytes_to_ctypes(bytearray.fromhex(address))
+ type(self._address)
+ self.address = self._address
+ pass
+
+ def set_command(self, cmd):
+ self.command = cmd
+ pass
+
+ def get_bytes(self):
+ return bytes(self)
+
+ pass
+
+
+def get_master_command6_req_struct():
+ req = hart_command_req_t()
+ req.set_command(6)
+ req.data.command6.poll_address = 1 # 轮询地址
+ req.data.command6.loop_current_mode = 1 # 回路电流模式 0:关闭 1:开启
+ return req
+
+
+def get_master_command11_req_struct():
+ req = hart_command_req_t()
+ req.set_command(11)
+ tag = "lapool"
+ copy_to_array(req.data.command11.tag, str_to_ascii(tag), 0)
+ return req
+
+
+def get_master_command17_req_struct():
+ req = hart_command_req_t()
+ req.set_command(17)
+ msg = "2023-05-11 14:02:00"
+ hex = str_to_ascii(msg)
+ bs = [0x20]*32
+ copy_to_array(bs, hex, 0)
+ encode_ascii_6(bs, 32, req.data.command17.message)
+ return req
+
+
+def get_master_command18_req_struct():
+ req = hart_command_req_t()
+ req.set_command(18)
+
+ tag = "LAPOOL"
+ descriptor = "HART-7"
+ date = (2023 - 1900, 5, 11)
+
+ bs = [0x20]*24
+ hex = str_to_ascii(tag)
+ copy_to_array(bs, hex, 0)
+ encode_ascii_6(bs, 8, req.data.command18.tag)
+
+ bs = [0x20]*24
+ hex = str_to_ascii(descriptor)
+ copy_to_array(bs, hex, 0)
+ encode_ascii_6(bs, 16, req.data.command18.descriptor)
+
+ copy_to_array(req.data.command18.date, date, 0)
+ return req
+
+
+def get_master_command19_req_struct():
+ req = hart_command_req_t()
+ req.set_command(19)
+ s = (0xA0, 0, 1)
+ copy_to_array(req.data.command19.final_assembly_number, s, 0)
+ return req
+
+
+def get_master_command21_req_struct():
+ req = hart_command_req_t()
+ req.set_command(21)
+ tag = "lapool-long"
+ copy_to_array(req.data.command21.long_tag, str_to_ascii(tag), 0)
+ return req
+
+
+def get_master_command22_req_struct():
+ req = hart_command_req_t()
+ req.set_command(22)
+ tag = "lapool-long-2"
+ copy_to_array(req.data.command22.long_tag, str_to_ascii(tag), 0)
+ return req
+
+
+def get_master_command38_req_struct():
+ req = hart_command_req_t()
+ req.set_command(38)
+ req.data.command38.configuration_change_counter = 2
+ return req
+
+
+def get_master_command33_req_struct():
+ req = hart_command_req_t()
+ req.set_command(33)
+ req.data.command33.slot_0 = 10
+ req.data.command33.slot_1 = 243
+ req.data.command33.slot_2 = 245
+ req.data.command33.slot_3 = 246
+ return req
+
+
+def get_master_command34_req_struct():
+ req = hart_command_req_t()
+ req.set_command(34)
+ req.data.command34.pv_damping_value = 10.0
+ return req
+
+
+def get_master_command35_req_struct():
+ req = hart_command_req_t()
+ req.set_command(35)
+ req.data.command35.pv_upper_and_lower_range_values_units_code = 32
+ req.data.command35.pv_upper_range_value = 20
+ req.data.command35.pv_lower_range_value = 4
+ return req
+
+
+def get_master_command39_req_struct():
+ req = hart_command_req_t()
+ req.set_command(39)
+ req.data.command39.control_code = 0
+ return req
+
+
+def get_master_command40_req_struct():
+ req = hart_command_req_t()
+ req.set_command(40)
+ req.data.command40.pv_fixed_current_level = 10.0
+ return req
+
+
+def get_master_command44_req_struct():
+ req = hart_command_req_t()
+ req.set_command(44)
+ req.data.command44.pv_units_code = 33
+ return req
+
+
+def get_master_command45_req_struct():
+ req = hart_command_req_t()
+ req.set_command(45)
+ req.data.command45.pv_loop_current_level = 4.0
+ return req
+
+
+def get_master_command46_req_struct():
+ req = hart_command_req_t()
+ req.set_command(46)
+ req.data.command46.pv_loop_current_level = 20.0
+ return req
+
+
+def get_master_command47_req_struct():
+ req = hart_command_req_t()
+ req.set_command(47)
+ req.data.command47.pv_transfer_function_code = 1
+ return req
+
+
+def get_master_command49_req_struct():
+ req = hart_command_req_t()
+ req.set_command(49)
+ req.data.command49.pv_transducer_serial_number = (0xa0, 0x00, 0x01)
+ return req
+
+
+def get_master_command51_req_struct():
+ req = hart_command_req_t()
+ req.set_command(51)
+ req.data.command51.device_ariables = (0x01, 0x02, 0x03, 250)
+ return req
+
+
+def get_master_command52_req_struct():
+ req = hart_command_req_t()
+ req.set_command(52)
+ req.data.command52.device_ariable = 246
+ return req
+
+
+def get_master_command53_req_struct():
+ req = hart_command_req_t()
+ req.set_command(53)
+ req.data.command53.device_ariable = 246
+ req.data.command53.device_ariable_unit_code = 35
+ return req
+
+
+def get_master_command54_req_struct():
+ req = hart_command_req_t()
+ req.set_command(54)
+ req.data.command54.device_ariable = 246
+ return req
+
+
+def get_master_command55_req_struct():
+ req = hart_command_req_t()
+ req.set_command(55)
+ req.data.command55.device_ariable = 246
+ req.data.command55.damping_value = 1
+ return req
+
+
+def get_master_command56_req_struct():
+ req = hart_command_req_t()
+ req.set_command(56)
+ req.data.command56.device_ariable = 246
+ req.data.command56.serial_number = (0xa0, 0x00, 0x01)
+ return req
+
+
+def get_master_command58_req_struct():
+ req = hart_command_req_t()
+ req.set_command(58)
+ tag = "tm001"
+ descriptor = "temperature"
+ date = (17, 5, 2023 - 1900)
+ copy_to_array(req.data.command58.unit_tag, str_to_ascii(tag), 0)
+ copy_to_array(req.data.command58.unit_descriptor,
+ str_to_ascii(descriptor), 0)
+ copy_to_array(req.data.command58.unit_date, date, 0)
+ return req
+
+
+def get_master_command59_req_struct():
+ req = hart_command_req_t()
+ req.set_command(59)
+ req.data.command59.s2m_preambles = 7
+ return req
+
+
+def get_master_command60_req_struct():
+ req = hart_command_req_t()
+ req.set_command(60)
+ req.data.command60.analog_channel_number_code = 0
+ return req
+
+
+def get_master_command62_req_struct():
+ req = hart_command_req_t()
+ req.set_command(62)
+ req.data.command62.slot0 = 0
+ req.data.command62.slot1 = 1
+ req.data.command62.slot2 = 2
+ req.data.command62.slot3 = 3
+ return req
+
+
+def get_master_command63_req_struct():
+ req = hart_command_req_t()
+ req.set_command(63)
+ req.data.command63.analog_channel_number_code = 0
+ return req
+
+
+def get_master_command64_req_struct():
+ req = hart_command_req_t()
+ req.set_command(64)
+ req.data.command64.analog_channel_number_code = 0
+ req.data.command64.damping_value = 1.1
+ return req
+
+
+def get_master_command65_req_struct():
+ req = hart_command_req_t()
+ req.set_command(65)
+ req.data.command65.analog_channel_number_code = 0
+ req.data.command65.upper_and_lower_range_values_units_code = 32
+ req.data.command65.upper_range_value = 20
+ req.data.command65.lower_range_value = 4
+ return req
+
+
+def get_master_command66_req_struct():
+ req = hart_command_req_t()
+ req.set_command(66)
+ req.data.command66.analog_channel_number_code = 0
+ req.data.command66.units_code = 32
+ bys = np.array([0x7f, 0xa0, 0x00, 0x00], dtype=np.uint8)
+ bs = bytes2float32slice(bys)
+ # req.data.command66.fixed_analog_channel_level = 1.2
+
+ req.data.command66.fixed_analog_channel_level = bs[0]
+ return req
+
+
+def get_master_command67_req_struct():
+ req = hart_command_req_t()
+ req.set_command(67)
+ req.data.command67.analog_channel_number_code = 0
+ req.data.command67.units_code = 32
+ req.data.command67.actual_analog_channel_level = 1.2
+ return req
+
+
+def get_master_command68_req_struct():
+ req = hart_command_req_t()
+ req.set_command(68)
+ req.data.command68.analog_channel_number_code = 0
+ req.data.command68.units_code = 32
+ req.data.command68.externally_measured_analog_channel_level = 1.2
+ return req
+
+
+def get_master_command69_req_struct():
+ req = hart_command_req_t()
+ req.set_command(69)
+ req.data.command69.analog_channel_number_code = 0
+ req.data.command69.transfer_function_code = 1
+ return req
+
+
+def get_master_command70_req_struct():
+ req = hart_command_req_t()
+ req.set_command(70)
+ req.data.command70.analog_channel_number_code = 0
+ return req
+
+
+def get_master_command71_req_struct():
+ req = hart_command_req_t()
+ req.set_command(71)
+ req.data.command71.lock_code = 0
+ return req
+
+
+def get_master_command72_req_struct():
+ req = hart_command_req_t()
+ req.set_command(72)
+ req.data.command72.squawk_control_code = 0
+ return req
+
+
+def get_master_command75_req_struct():
+ req = hart_command_req_t()
+ req.set_command(75)
+ req.set_address("0000000000")
+ req.data.command75.card = 0
+ req.data.command75.channel = 0
+ req.data.command75.poll_address = 0
+ return req
+
+
+def get_master_command79_req_struct():
+ req = hart_command_req_t()
+ req.set_command(79)
+ req.data.command79.device_ariable = 6
+ req.data.command79.device_ariable_command_code = 0
+ req.data.command79.device_ariable_unit_code = 32
+ req.data.command79.device_ariable_value = 25
+ req.data.command79.status = 0
+ return req
+
+
+def get_master_command80_req_struct():
+ req = hart_command_req_t()
+ req.set_command(80)
+ req.data.command80.device_ariable = 246
+ return req
+
+
+def get_master_command81_req_struct():
+ req = hart_command_req_t()
+ req.set_command(81)
+ req.data.command81.device_ariable = 246
+ return req
+
+
+def get_master_command82_req_struct():
+ req = hart_command_req_t()
+ req.set_command(82)
+ req.data.command82.device_ariable = 246
+ req.data.command82.trim_points = 3
+ req.data.command82.units_code = 32
+ req.data.command82.value = 1.2
+ return req
+
+
+def get_master_command83_req_struct():
+ req = hart_command_req_t()
+ req.set_command(83)
+ req.data.command83.device_ariable = 246
+ return req
+
+
+def get_master_command84_req_struct():
+ req = hart_command_req_t()
+ req.set_command(84)
+ req.set_address("0000000000")
+ req.data.command84.identifier = 0xA001
+ return req
+
+
+def get_master_command85_req_struct():
+ req = hart_command_req_t()
+ req.set_command(85)
+ req.set_address("0000000000")
+ req.data.command85.card = 0
+ req.data.command85.channel = 0
+ return req
+
+
+def get_master_command86_req_struct():
+ req = hart_command_req_t()
+ req.set_command(86)
+ req.set_address("0000000000")
+ req.data.command86.identifier = 0xA001
+ return req
+
+
+def get_master_command87_req_struct():
+ req = hart_command_req_t()
+ req.set_command(87)
+ req.set_address("0000000000")
+ req.data.command87.master_mode = 1
+ return req
+
+
+def get_master_command88_req_struct():
+ req = hart_command_req_t()
+ req.set_command(88)
+ req.set_address("0000000000")
+ req.data.command88.retry_count = 3
+ return req
+
+
+def get_master_command89_req_struct():
+ req = hart_command_req_t()
+ req.set_command(89)
+ date = (31, 5, 2023 - 1900)
+ req.data.command89.time_set_code = 0
+ copy_to_array(req.data.command89.date, date, 0)
+ req.data.command89.time = convert_timestrap(15, 0, 1, 999)
+ req.data.command89.transmission_time = 0
+
+ return req
+
+
+def get_master_command91_req_struct():
+ req = hart_command_req_t()
+ req.set_command(91)
+ req.data.command91.trend_number = 0
+ return req
+
+
+def get_master_command92_req_struct():
+ req = hart_command_req_t()
+ req.set_command(92)
+ req.data.command92.trend_number = 0
+ req.data.command92.trend_code = 0
+ req.data.command92.device_variable_code = 32
+ req.data.command92.trend_sample_interval = 3600000+320
+ return req
+
+
+def get_master_command93_req_struct():
+ req = hart_command_req_t()
+ req.set_command(93)
+ req.data.command93.trend_number = 0
+ return req
+
+
+def get_master_command96_req_struct():
+ req = hart_command_req_t()
+ req.set_command(96)
+ req.data.command96.action_number = 0
+ return req
+
+
+def get_master_command97_req_struct():
+ req = hart_command_req_t()
+ req.set_command(97)
+ date = (31, 5, 2024 - 1900)
+ ts = (12 * 3600 + 1 * 60 + 0) * 1000
+ req.data.command97.action_number = 0
+ req.data.command97.action_control_code = 0x10
+ req.data.command97.device_variable_code = 246
+ req.data.command97.command_number = 0xffff
+ copy_to_array(req.data.command97.trigger_date, date, 0)
+ req.data.command97.trigger_time = ts
+ return req
+
+
+def get_master_command98_req_struct():
+ req = hart_command_req_t()
+ req.set_command(98)
+ req.data.command98.action_number = 0
+ return req
+
+
+def get_master_command99_req_struct():
+ req = hart_command_req_t()
+ req.set_command(99)
+ command_data_length = 10
+ req.data.command99.action_number = 0
+ req.data.command99.command_number = 1
+ req.data.command99.command_data_length = command_data_length
+ array = np.arange(command_data_length)
+ copy_to_array(req.data.command99.command_data, array, 0)
+ return req
+
+
+def get_master_command100_req_struct():
+ req = hart_command_req_t()
+ req.set_command(100)
+ req.data.command100.pv_alarm_selection_code = 239
+ return req
+
+
+def get_master_command101_req_struct():
+ req = hart_command_req_t()
+ req.set_command(101)
+ req.data.command101.burst_message = 0
+ return req
+
+
+def get_master_command102_req_struct():
+ req = hart_command_req_t()
+ req.set_command(102)
+ req.data.command102.burst_message = 0
+ req.data.command102.sub_device_index = 0
+ return req
+
+
+def get_master_command103_req_struct():
+ req = hart_command_req_t()
+ ts = 3600*1000
+ req.set_command(103)
+ req.data.command103.burst_message = 0
+ req.data.command103.update_period_time = ts
+ req.data.command103.max_update_period_time = ts
+ return req
+
+
+def get_master_command104_req_struct():
+ req = hart_command_req_t()
+ req.set_command(104)
+ req.data.command104.burst_message = 0
+ req.data.command104.burst_message_trigger_code = 1
+ req.data.command104.device_variable_vlassification_for_trigger_level = 0x40
+ req.data.command104.units_code = 0x20
+ req.data.command104.trigger_level = 1.2
+ return req
+
+
+def get_master_command105_req_struct():
+ req = hart_command_req_t()
+ req.set_command(105)
+ req.data.command105.burst_message = 0
+ return req
+
+
+def get_master_command107_req_struct():
+ req = hart_command_req_t()
+ req.set_command(107)
+ req.data.command107.solts = (1, 2, 3, 4, 5, 6, 7, 8)
+ req.data.command107.burst_message = 0
+ return req
+
+
+def get_master_command513_req_struct():
+ req = hart_command_req_t()
+ req.set_command(513)
+ req.data.command513.country_code = 852
+ req.data.command513.si_units_control_code = 1
+ return req
+
+
+def get_master_command254_req_struct():
+ req = hart_command_req_t()
+ req.set_command(254)
+ req.data.command254.model = 1
+ return req
+
+
+def get_master_command260_req_struct():
+ req = hart_command_req_t()
+ req.set_command(260)
+ req.data.command260.model = 1
+ req.data.command260.threshold_control = 1.1
+ req.data.command260.amplifier_circuit_control = 1.1
+ req.data.command260.pressure_A = 100
+ req.data.command260.pressure_B = 100
+ req.data.command260.position_selector = 1
+ req.data.command260.position_feedback_P = 0.1
+ req.data.command260.position_feedback_I = 0.2
+ req.data.command260.position_feedback_D = 0.3
+ req.data.command260.position_feedback_amplifier_circuit_control_gain = 10
+ req.data.command260.pressure_selector = 1
+ req.data.command260.pressure_feedback_P = 0.1
+ req.data.command260.pressure_feedback_I = 0.1
+ req.data.command260.pressure_feedback_D = 0.1
+ req.data.command260.pressure_feedback_amplifier_circuit_control_gain = 10
+ array = np.arange(32)
+ copy_to_array(req.data.command260.valve_model, array, 0)
+
+ req.data.command260.spring_coefficient = 0.1
+ req.data.command260.gas_inlet_cross_sectional_area = 0.1
+ req.data.command260.gas_opening_closing = 1
+
+ return req
+
+
+def get_master_command500_req_struct(test_type, data_length, data):
+ req = hart_command_req_t()
+ req.set_command(500)
+ req.data.command500.test_type = test_type
+ req.data.command500.data_length = data_length
+ if data_length > 0:
+ copy_to_array(req.data.command500.data, data, 0)
+ return req
+
+
+# RTC写入测试
+def get_master_command500_req_struct_TEST_TYPE_RTC_WRITE():
+ req = hart_command_req_t()
+ req.set_command(500)
+ req.data.command500.test_type = 0
+ req.data.command500.data_length = 7
+ rtc = hart_command_500_rtc_data_t()
+ rtc.year = 0x23
+ rtc.month = 0x05
+ rtc.day = 0x31
+ rtc.hour = 0x12
+ rtc.minute = 0x59
+ rtc.second = 0x59
+ rtc.weekday = 0x01
+ copy_to_array(req.data.command500.data, rtc.get_bytes(), 0)
+
+ return req
+
+
+def get_master_command500_req_struct_TEST_TYPE_DAC():
+ req = hart_command_req_t()
+ req.set_command(500)
+ req.data.command500.test_type = 7
+ req.data.command500.data_length = 2
+ u16 = hart_command_500_u16_data_t()
+ u16.data = 2000
+ copy_to_array(req.data.command500.data, u16.get_bytes(), 0)
+
+ return req
+
+
+def get_master_command500_req_struct_PWM():
+ req = hart_command_req_t()
+ req.set_command(500)
+ req.data.command500.test_type = 14
+ req.data.command500.data_length = 2
+ u16 = hart_command_500_u16_data_t()
+ u16.data = 2000
+ copy_to_array(req.data.command500.data, u16.get_bytes(), 0)
+
+ return req
+
+def get_master_command31_req_struct(cmd,addr,len):
+ req = hart_command_req_t()
+ req.set_command(31)
+ req.data.command31.command = cmd
+ req.data.command31.address = addr
+ req.data.command31.length = len
+ return req
+
+def get_master_command129_req_struct():
+ req = hart_command_req_t()
+ req.set_command(129)
+ bs1 = (48,)
+ bs2 = [251 for x in range(0, 5)]
+ copy_to_array(req.data.command129.data, bs2, 0)
+ copy_to_array(req.data.command129.data, bs1, 0)
+ return req
+
+def get_master_command130_req_struct():
+ req = hart_command_req_t()
+ req.set_command(130)
+ bs1 = (48, 2)
+ bs2 = [251 for x in range(0, 100)]
+ copy_to_array(req.data.command130.data, bs2, 0)
+ copy_to_array(req.data.command130.data, bs1, 0)
+ return req
+
+def get_master_command132_req_struct(code):
+ req = hart_command_req_t()
+ req.set_command(132)
+ req.data.command132.code = code
+ return req
+
+def get_master_command134_req_struct():
+ req = hart_command_req_t()
+ req.set_command(134)
+ req.data.command134.file_index = 3
+ req.data.command134.file_offset = 0
+ req.data.command134.read_length = 18+2
+ return req
+
+def get_master_command141_req_struct(code):
+ req = hart_command_req_t()
+ req.set_command(141)
+ req.data.command141.write_protect_code = code
+ return req
+
+def get_master_command142_req_struct(code):
+ req = hart_command_req_t()
+ req.set_command(142)
+ req.data.command142.code = code
+ return req
+
+def get_master_command155_req_struct():
+ req = hart_command_req_t()
+ req.set_command(155)
+ req.data.command155.diagnostic_code = 0x0921
+ req.data.command155.sampling_time = 0x0c
+ req.data.command155.step = 1
+ return req
+
+def get_master_command167_req_struct():
+ req = hart_command_req_t()
+ req.set_command(167)
+ req.data.command167.operation_time = 0x52bd64bc
+ operator = "liujia"
+ copy_to_array(req.data.command167.operator, str_to_ascii(operator), 0)
+ return req
+
+def get_master_command170_req_struct():
+ req = hart_command_req_t()
+ req.set_command(170)
+ req.data.command170.code = 0
+ return req
+
+def hart_response_call(index, ptr, length):
+ bs = ptr[:length]
+ print_hex_data_space(bs, True)
+ pass
diff --git a/User/hart/test/src/run.py b/User/hart/test/src/run.py
new file mode 100644
index 0000000..8a20563
--- /dev/null
+++ b/User/hart/test/src/run.py
@@ -0,0 +1,26 @@
+'''
+Author: shenghao.xu
+Date: 2023-03-20 19:27:47
+LastEditors: Please set LastEditors
+LastEditTime: 2024-09-10 09:15:11
+FilePath: \hart\test\run.py
+Description:
+email:545403892@qq.com
+Copyright (c) 2023 by shenghao.xu, All Rights Reserved.
+'''
+
+import unittest
+from unittestreport import TestRunner
+import os
+
+
+case_path = "test/src/"
+suite = unittest . defaultTestLoader . discover(case_path, pattern="test_*.py")
+BasePath = os.path.dirname(__file__) # 获取当前文件所在路径
+
+if __name__ == "__main__":
+ fp = BasePath + "\\report"
+ # filename为文件名称,report_dir报告输出位置,title测试标题,tester测试测试人员,desc描述
+ runner = TestRunner(suite, filename="report.html", report_dir=fp,
+ title="测试报告", tester="许晟昊", desc="许晟昊执行的测试用例", templates=2)
+ runner.run()
diff --git a/User/hart/test/src/test_hart_master_req.py b/User/hart/test/src/test_hart_master_req.py
new file mode 100644
index 0000000..8790917
--- /dev/null
+++ b/User/hart/test/src/test_hart_master_req.py
@@ -0,0 +1,1160 @@
+'''
+Author: shenghao.xu
+Date: 2023-03-29 22:15:39
+LastEditors: Please set LastEditors
+LastEditTime: 2024-09-10 09:16:31
+FilePath: \hart\test\test_hart_master_req.py
+Description:测试主机发送指令
+email:545403892@qq.com
+Copyright (c) 2023 by shenghao.xu, All Rights Reserved.
+'''
+
+import unittest
+from ctypes import *
+from ctypes import cdll
+
+import pkg.entity as entity
+import pkg.common as common
+
+case_count = 0
+
+
+class TestHartMasterReqCases(unittest.TestCase):
+
+ def init(cls) -> None:
+ cls.dll = cdll.LoadLibrary('./hart.dll')
+ pass
+
+ @classmethod
+ def setUpClass(cls) -> None:
+ cls.init(cls)
+ print('[TestHartMasterReqCases] 主机接口开始测试...')
+ pass
+
+ @classmethod
+ def tearDownClass(cls) -> None:
+ print('[TestHartMasterReqCases] 结束测试,测试用例%d个' % case_count)
+ print('----------------------------------------------------------------------')
+ print("\r")
+ pass
+
+ def setUp(self) -> None:
+ global case_count
+ case_count += 1
+ print("\r")
+ self.master_init()
+ pass
+
+ def tearDown(self) -> None:
+ pass
+
+ def master_init(self):
+ self.hart = entity.get_master_struct()
+ ret = self.dll.hart_init(byref(self.hart))
+ self.assertTrue(bool(ret), "hart_init failed")
+ pass
+
+ # def testReqCommand999(self):
+ # data = [0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x06, 0x80, 0x00, 0x18, 0x00, 0x10, 0xfe, 0x00, 0x00, 0x08,
+ # 0x07, 0x00, 0x07, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x08, 0xf6, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x44, 0xd8]
+ # rsp = entity.hart_rsp_t()
+ # self.dll.hart_handle_parse(byref(common.bytes_to_ctypes(
+ # data)), len(data), byref(rsp))
+ # pass
+
+ def testReqCommand000Short(self): # Command 0 读取唯一标识命令V5
+ """[主机指令]读取唯一标识命令V5"""
+ print('Command 0 读取唯一标识命令V5 短帧', end=" : ")
+ data = entity.hart_command_req_t()
+ data.set_short_address()
+ ret = self.dll.hart_master_command_req(byref(data))
+ self.assertTrue(bool(ret), "testReqCommand0 failed")
+ pass
+
+ # def testReqCommand000Long(self): # Command 0 读取唯一标识命令V5
+ # """[主机指令]读取唯一标识命令V5"""
+ # print('Command 0 读取唯一标识命令V5 长帧', end=" : ")
+ # data = entity.hart_command_req_t()
+ # data.set_long_address()
+ # # common.print_hex_data_space(data.get_bytes())
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand0 failed")
+ # pass
+
+ # def testReqCommand001(self): # 读取主变量V5
+ # """[主机指令]读取主变量V5"""
+ # print('Command 1 读取主变量V5', end=" : ")
+ # data = entity.hart_command_req_t()
+ # data.set_command(1)
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand002(self): # 读取环路电流和量程百分比V5
+ # """[主机指令]读取环路电流和量程百分比V5"""
+ # print('Command 2 读取环路电流和量程百分比V5', end=" : ")
+ # data = entity.hart_command_req_t()
+ # data.set_command(2)
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand003(self): # 读取动态变量和环路电流
+ # """[主机指令]读取动态变量和环路电流"""
+ # print('Command 3 读取动态变量和环路电流', end=" : ")
+ # data = entity.hart_command_req_t()
+ # data.set_command(3)
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand006(self): # 写入轮训地址V5
+ # """[主机指令]写入轮训地址V5"""
+ # print('Command 6 写入轮训地址V5', end=" : ")
+ # data = entity.get_master_command6_req_struct()
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand007(self): # 读取循环配置
+ # """[主机指令]读取循环配置"""
+ # print('Command 7 读取循环配置', end=" : ")
+ # data = entity.hart_command_req_t()
+ # data.set_command(7)
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand008(self):
+ # """[主机指令]读取动态变量分类"""
+ # print('Command 8 读取动态变量分类', end=" : ")
+ # data = entity.hart_command_req_t()
+ # data.set_command(8)
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand009(self):
+ # """[主机指令]读取具有状态的设备变量"""
+ # print('Command 9 读取具有状态的设备变量', end=" : ")
+ # data = entity.hart_command_req_t()
+ # data.set_command(9)
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand011(self):
+ # """[主机指令]读取与标签关联的唯一标识符"""
+ # print('Command 11 读取与标签关联的唯一标识符', end=" : ")
+ # data = entity.get_master_command11_req_struct()
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # print(common.ascii_to_str(self.hart.response[13:13+6]))
+ # pass
+
+ # def testReqCommand012(self):
+ # """[主机指令]读取消息"""
+ # print('Command 12 读取消息', end=" : ")
+ # data = entity.hart_command_req_t()
+ # data.set_command(12)
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # print(common.ascii_to_str(self.hart.response[15:15+24]))
+ # pass
+
+ # def testReqCommand013(self):
+ # """[主机指令]读取标签、描述符、日期"""
+ # print('Command 13 读取标签、描述符、日期', end=" : ")
+ # data = entity.hart_command_req_t()
+ # data.set_command(13)
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand014(self):
+ # """[主机指令]读取主变量传感器信息"""
+ # print('Command 14 读取主变量传感器信息', end=" : ")
+ # data = entity.hart_command_req_t()
+ # data.set_command(14)
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand015(self):
+ # """[主机指令]读取设备信息"""
+ # print('Command 15 读取设备信息', end=" : ")
+ # data = entity.hart_command_req_t()
+ # data.set_command(15)
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand016(self):
+ # """[主机指令]读取最终总装编号"""
+ # print('Command 16 读取最终总装编号', end=" : ")
+ # data = entity.hart_command_req_t()
+ # data.set_command(16)
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand017(self):
+ # """[主机指令]写入消息"""
+ # print('Command 17 写入消息', end=" : ")
+ # data = entity.get_master_command17_req_struct()
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand018(self):
+ # """[主机指令]写标签、描述符、日期"""
+ # print('Command 18 写标签、描述符、日期', end=" : ")
+ # data = entity.get_master_command18_req_struct()
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand019(self):
+ # """[主机指令]总装编号"""
+ # print('Command 19 总装编号', end=" : ")
+ # data = entity.get_master_command19_req_struct()
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand020(self):
+ # """[主机指令]读取长标签"""
+ # print('Command 20 读取长标签', end=" : ")
+ # data = entity.hart_command_req_t()
+ # data.set_command(20)
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand021(self):
+ # """[主机指令]读取与长标签关联的唯一标识符"""
+ # print('Command 21 读取与长标签关联的唯一标识符', end=" : ")
+ # data = entity.get_master_command21_req_struct()
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand022(self):
+ # """[主机指令]写长标签"""
+ # print('Command 22 写长标签', end=" : ")
+ # data = entity.get_master_command22_req_struct()
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand038(self):
+ # """[主机指令]重置配置更改标志"""
+ # print('Command 38 重置配置更改标志', end=" : ")
+ # data = entity.get_master_command38_req_struct()
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand048(self):
+ # """[主机指令]读取附加设备状态"""
+ # print('Command 48 读取附加设备状态', end=" : ")
+ # data = entity.hart_command_req_t()
+ # data.set_command(48)
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand033(self):
+ # """[主机指令]读取设备变量V5"""
+ # print('Command 33 读取设备变量V5', end=" : ")
+ # data = entity.get_master_command33_req_struct()
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand034(self):
+ # """[主机指令]写入主变量阻尼值V5"""
+ # print('Command 34 写入主变量阻尼值V5', end=" : ")
+ # data = entity.get_master_command34_req_struct()
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand035(self):
+ # """[主机指令]写入主变量范围值V5"""
+ # print('Command 35 写入主变量阻尼值V5', end=" : ")
+ # data = entity.get_master_command35_req_struct()
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand036(self):
+ # """[主机指令]设置主变量上限值V5"""
+ # print('Command 36 设置主变量上限值V5', end=" : ")
+ # data = entity.hart_command_req_t()
+ # data.set_command(36)
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand037(self):
+ # """[主机指令]设置主变量下限值V5"""
+ # print('Command 37 设置主变量下限值V5', end=" : ")
+ # data = entity.hart_command_req_t()
+ # data.set_command(37)
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand039(self):
+ # """[主机指令]EEPROM控制V5"""
+ # print('Command 39 EEPROM控制V5', end=" : ")
+ # data = entity.get_master_command39_req_struct()
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand040(self):
+ # """[主机指令]进入/退出固定电流模式V5"""
+ # print('Command 40 进入/退出固定电流模式V5', end=" : ")
+ # data = entity.get_master_command40_req_struct()
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand041(self):
+ # """[主机指令]执行自检V5"""
+ # print('Command 41 执行自检V5', end=" : ")
+ # data = entity.hart_command_req_t()
+ # data.set_command(41)
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand042(self):
+ # """[主机指令]设备复位"""
+ # print('Command 42 设备复位', end=" : ")
+ # data = entity.hart_command_req_t()
+ # data.set_command(42)
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand043(self):
+ # """[主机指令]设置主变量零V5"""
+ # print('Command 43 设置主变量零V5', end=" : ")
+ # data = entity.hart_command_req_t()
+ # data.set_command(43)
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand044(self):
+ # """[主机指令]编写主变量单元V5"""
+ # print('Command 44 编写主变量单元V5', end=" : ")
+ # data = entity.get_master_command44_req_struct()
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand045(self):
+ # """[主机指令]微调回路电流归零V5"""
+ # print('Command 45 微调回路电流归零V5', end=" : ")
+ # data = entity.get_master_command45_req_struct()
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand046(self):
+ # """[主机指令]微调回路电流增益V5"""
+ # print('Command 46 微调回路电流增益V5', end=" : ")
+ # data = entity.get_master_command46_req_struct()
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand047(self):
+ # """[主机指令]编写主变量传递函数V5"""
+ # print('Command 47 编写主变量传递函数V5', end=" : ")
+ # data = entity.get_master_command47_req_struct()
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand049(self):
+ # """[主机指令]写入主变量传感器序列号V5"""
+ # print('Command 49 写入主变量传感器序列号V5', end=" : ")
+ # data = entity.get_master_command49_req_struct()
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand050(self):
+ # """[主机指令]读取动态变量赋值V5"""
+ # print('Command 50 读取动态变量赋值V5', end=" : ")
+ # data = entity.hart_command_req_t()
+ # data.set_command(50)
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand051(self):
+ # """[主机指令]编写动态变量赋值V5"""
+ # print('Command 51 编写动态变量赋值V5', end=" : ")
+ # data = entity.get_master_command51_req_struct()
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand052(self):
+ # """[主机指令]设置设备变量零V5"""
+ # print('Command 52 设置设备变量零V5', end=" : ")
+ # data = entity.get_master_command52_req_struct()
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand053(self):
+ # """[主机指令]写入设备变量单位V5"""
+ # print('Command 53 写入设备变量单位V5', end=" : ")
+ # data = entity.get_master_command53_req_struct()
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand054(self):
+ # """[主机指令]读取设备变量信息V5"""
+ # print('Command 54 读取设备变量信息V5', end=" : ")
+ # data = entity.get_master_command54_req_struct()
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand055(self):
+ # """[主机指令]写入设备可变阻尼值V5"""
+ # print('Command 55 写入设备可变阻尼值V5', end=" : ")
+ # data = entity.get_master_command55_req_struct()
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand056(self):
+ # """[主机指令]写入设备可变传感器序列号V5"""
+ # print('Command 56 写入设备可变传感器序列号V5', end=" : ")
+ # data = entity.get_master_command56_req_struct()
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand057(self):
+ # """[主机指令]读取单位标签、描述符、日期V5"""
+ # print('Command 57 读取单位标签、描述符、日期V5', end=" : ")
+ # data = entity.hart_command_req_t()
+ # data.set_command(57)
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand058(self):
+ # """[主机指令]编写单位标签、描述符、日期V5"""
+ # print('Command 58 编写单位标签、描述符、日期V5', end=" : ")
+ # data = entity.get_master_command58_req_struct()
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand059(self):
+ # """[主机指令]写入响应序码数V5"""
+ # print('Command 59 写入响应序码数V5', end=" : ")
+ # data = entity.get_master_command59_req_struct()
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand060(self):
+ # """[主机指令]读取模拟通道和范围百分比V5"""
+ # print('Command 60 读取模拟通道和范围百分比V5', end=" : ")
+ # data = entity.get_master_command60_req_struct()
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand061(self):
+ # """[主机指令]读取动态变量和主变量模拟通道"""
+ # print('Command 61 读取动态变量和主变量模拟通道', end=" : ")
+ # data = entity.hart_command_req_t()
+ # data.set_command(61)
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand062(self):
+ # """[主机指令]读取模拟通道"""
+ # print('Command 62 读取模拟通道', end=" : ")
+ # data = entity.get_master_command62_req_struct()
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand063(self):
+ # """[主机指令]读取模拟通道信息V5"""
+ # print('Command 63 读取模拟通道信息V5', end=" : ")
+ # data = entity.get_master_command63_req_struct()
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand064(self):
+ # """[主机指令]写入模拟通道附加阻尼值V5"""
+ # print('Command 64 写入模拟通道附加阻尼值V5', end=" : ")
+ # data = entity.get_master_command64_req_struct()
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand065(self):
+ # """[主机指令]写入模拟通道范围值V5"""
+ # print('Command 65 写入模拟通道范围值V5', end=" : ")
+ # data = entity.get_master_command65_req_struct()
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand066(self):
+ # """[主机指令]进入/退出固定模拟通道模式V5"""
+ # print('Command 66 进入/退出固定模拟通道模式V5', end=" : ")
+ # data = entity.get_master_command66_req_struct()
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand067(self):
+ # """[主机指令]调整模拟通道零V5"""
+ # print('Command 67 调整模拟通道零V5', end=" : ")
+ # data = entity.get_master_command67_req_struct()
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand068(self):
+ # """[主机指令]微调模拟通道增益V5"""
+ # print('Command 68 微调模拟通道增益V5', end=" : ")
+ # data = entity.get_master_command68_req_struct()
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand069(self):
+ # """[主机指令]写入模拟通道传递函数代码"""
+ # print('Command 69 写入模拟通道传递函数代码', end=" : ")
+ # data = entity.get_master_command69_req_struct()
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand070(self):
+ # """[主机指令]读取模拟通道端点值V5"""
+ # print('Command 70 读取模拟通道端点值V5', end=" : ")
+ # data = entity.get_master_command70_req_struct()
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand071(self):
+ # """[主机指令]锁定装置"""
+ # print('Command 71 锁定装置', end=" : ")
+ # data = entity.get_master_command71_req_struct()
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand072(self):
+ # """[主机指令]呼叫"""
+ # print('Command 72 呼叫', end=" : ")
+ # data = entity.get_master_command72_req_struct()
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand073(self):
+ # """[主机指令]查找设备"""
+ # print('Command 73 查找设备', end=" : ")
+ # data = entity.hart_command_req_t()
+ # data.set_command(73)
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand074(self):
+ # """[主机指令]读取I/O系统功能"""
+ # print('Command 74 读取I/O系统功能', end=" : ")
+ # data = entity.hart_command_req_t()
+ # data.set_command(74)
+ # data.set_address("0000000000")
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand075(self):
+ # """[主机指令]轮询子设备"""
+ # print('Command 75 轮询子设备', end=" : ")
+ # data = entity.get_master_command75_req_struct()
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand076(self):
+ # """[主机指令]读锁定设备状态"""
+ # print('Command 76 读锁定设备状态', end=" : ")
+ # data = entity.hart_command_req_t()
+ # data.set_command(76)
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand079(self):
+ # """[主机指令]写入设备变量"""
+ # print('Command 79 写入设备变量', end=" : ")
+ # data = entity.get_master_command79_req_struct()
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand080(self):
+ # """[主机指令]读取设备可变微调点"""
+ # print('Command 80 读取设备可变微调点', end=" : ")
+ # data = entity.get_master_command80_req_struct()
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand081(self):
+ # """[主机指令]读取设备变量调整指南"""
+ # print('Command 81 读取设备变量调整指南', end=" : ")
+ # data = entity.get_master_command81_req_struct()
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand082(self):
+ # """[主机指令]写入设备可变微调点"""
+ # print('Command 82 写入设备可变微调点', end=" : ")
+ # data = entity.get_master_command82_req_struct()
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand083(self):
+ # """[主机指令]重置设备变量调整"""
+ # print('Command 83 重置设备变量调整', end=" : ")
+ # data = entity.get_master_command83_req_struct()
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand084(self):
+ # """[主机指令]读取子设备标识摘要"""
+ # print('Command 84 读取子设备标识摘要', end=" : ")
+ # data = entity.get_master_command84_req_struct()
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand085(self):
+ # """[主机指令]读取I/O通道统计信息"""
+ # print('Command 85 读取I/O通道统计信息', end=" : ")
+ # data = entity.get_master_command85_req_struct()
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand086(self):
+ # """[主机指令]读取子设备统计信息"""
+ # print('Command 86 读取子设备统计信息', end=" : ")
+ # data = entity.get_master_command86_req_struct()
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand087(self):
+ # """[主机指令]写入I/O系统主模式"""
+ # print('Command 87 写入I/O系统主模式', end=" : ")
+ # data = entity.get_master_command87_req_struct()
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand088(self):
+ # """[主机指令]写入I/O系统重试计数"""
+ # print('Command 88 写入I/O系统重试计数', end=" : ")
+ # data = entity.get_master_command88_req_struct()
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand089(self):
+ # """[主机指令]设置实时时钟"""
+ # print('Command 89 设置实时时钟', end=" : ")
+ # data = entity.get_master_command89_req_struct()
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand090(self):
+ # """[主机指令]读取实时时钟"""
+ # print('Command 90 读取实时时钟', end=" : ")
+ # data = entity.hart_command_req_t()
+ # data.set_command(90)
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand091(self):
+ # """[主机指令]读取趋势配置"""
+ # print('Command 91 读取趋势配置', end=" : ")
+ # data = entity.get_master_command91_req_struct()
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand092(self):
+ # """[主机指令]写入趋势配置"""
+ # print('Command 92 写入趋势配置', end=" : ")
+ # data = entity.get_master_command92_req_struct()
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand093(self):
+ # """[主机指令]读取趋势"""
+ # print('Command 93 读取趋势', end=" : ")
+ # data = entity.get_master_command93_req_struct()
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand095(self):
+ # """[主机指令]读取I/O系统客户端通信统计信息"""
+ # print('Command 95 读取I/O系统客户端通信统计信息', end=" : ")
+ # data = entity.hart_command_req_t()
+ # data.set_command(95)
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand096(self):
+ # """[主机指令]读取同步操作"""
+ # print('Command 96 读取同步操作', end=" : ")
+ # data = entity.get_master_command96_req_struct()
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand097(self):
+ # """[主机指令]配置同步操作"""
+ # print('Command 97 配置同步操作', end=" : ")
+ # data = entity.get_master_command97_req_struct()
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand098(self):
+ # """[主机指令]读取命令操作"""
+ # print('Command 98 读取命令操作', end=" : ")
+ # data = entity.get_master_command98_req_struct()
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand099(self):
+ # """[主机指令]配置命令操作"""
+ # print('Command 99 配置命令操作', end=" : ")
+ # data = entity.get_master_command99_req_struct()
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand100(self):
+ # """[主机指令]写入主变量报警码"""
+ # print('Command 100 写入主变量报警码', end=" : ")
+ # data = entity.get_master_command100_req_struct()
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand101(self):
+ # """[主机指令]读取子设备到突发消息映射"""
+ # print('Command 101 读取子设备到突发消息映射', end=" : ")
+ # data = entity.get_master_command101_req_struct()
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand102(self):
+ # """[主机指令]将子设备映射到突发信息"""
+ # print('Command 102 将子设备映射到突发信息', end=" : ")
+ # data = entity.get_master_command102_req_struct()
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand103(self):
+ # """[主机指令]写入突发周期"""
+ # print('Command 103 写入突发周期', end=" : ")
+ # data = entity.get_master_command103_req_struct()
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand104(self):
+ # """[主机指令]写入突发触发器"""
+ # print('Command 104 写入突发触发器', end=" : ")
+ # data = entity.get_master_command104_req_struct()
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand105(self):
+ # """[主机指令]读取突发模式配置"""
+ # print('Command 105 读取突发模式配置', end=" : ")
+ # data = entity.get_master_command105_req_struct()
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand107(self):
+ # """[主机指令]写入突发设备变量"""
+ # print('Command 107 写入突发设备变量', end=" : ")
+ # data = entity.get_master_command107_req_struct()
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand110(self):
+ # """[主机指令]读取所有动态变量V5"""
+ # print('Command 110 读取所有动态变量V5', end=" : ")
+ # data = entity.hart_command_req_t()
+ # data.set_command(110)
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand512(self):
+ # """[主机指令]读取国家代码"""
+ # print('Command 512 读取国家代码', end=" : ")
+ # data = entity.hart_command_req_t()
+ # data.set_command(512)
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand513(self):
+ # """[主机指令]编写国家代码"""
+ # print('Command 513 编写国家代码', end=" : ")
+ # data = entity.get_master_command513_req_struct()
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand254(self):
+ # """[主机指令]数据样品型号(气开\气关)"""
+ # print('Command 254 数据样品型号(气开\气关)', end=" : ")
+ # data = entity.get_master_command254_req_struct()
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand255(self):
+ # """[主机指令]读取模拟量数值"""
+ # print('Command 255 读取模拟量数值', end=" : ")
+ # data = entity.hart_command_req_t()
+ # data.set_command(255)
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand256(self):
+ # """[主机指令]读取转化的数值"""
+ # print('Command 256 读取转化的数值', end=" : ")
+ # data = entity.hart_command_req_t()
+ # data.set_command(256)
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand257(self):
+ # """[主机指令]寻找、计算P / I / D"""
+ # print('Command 257 寻找、计算P / I / D', end=" : ")
+ # data = entity.hart_command_req_t()
+ # data.set_command(257)
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand258(self):
+ # """[主机指令]计算 摩擦力"""
+ # print('Command 258 计算 摩擦力', end=" : ")
+ # data = entity.hart_command_req_t()
+ # data.set_command(258)
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand259(self):
+ # """[主机指令]计算 弹簧力"""
+ # print('Command 259 计算 弹簧力', end=" : ")
+ # data = entity.hart_command_req_t()
+ # data.set_command(259)
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand260(self):
+ # """[主机指令]编写参数配置"""
+ # print('Command 260 编写参数配置', end=" : ")
+ # data = entity.get_master_command260_req_struct()
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand261(self):
+ # """[主机指令]读取参数配置"""
+ # print('Command 261 读取参数配置', end=" : ")
+ # data = entity.hart_command_req_t()
+ # data.set_command(261)
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+ # def testReqCommand500(self):
+ # """[主机指令]测试指令-通用指令"""
+ # print('Command 500 测试指令-通用指令', end=" : ")
+ # data = entity.get_master_command500_req_struct(
+ # 23, 0, "")
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand500_TEST_TYPE_RTC_WRITE(self): # RTC写入测试
+ # """[主机指令]测试指令-RTC写入"""
+ # print('Command 500 测试指令-RTC写入', end=" : ")
+ # data = entity.get_master_command500_req_struct_TEST_TYPE_RTC_WRITE()
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand500_TEST_TYPE_RTC_READ(self): # RTC读取测试
+ # """[主机指令]测试指令-RTC读取"""
+ # print('Command 500 测试指令-RTC读取', end=" : ")
+ # data = entity.get_master_command500_req_struct(1, 0, "")
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand500_TEST_TYPE_ADC0(self):
+ # """[主机指令]测试指令-回路电流"""
+ # print('Command 500 测试指令-回路电流', end=" : ")
+ # data = entity.get_master_command500_req_struct(2, 0, "")
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand500_TEST_TYPE_DAC(self):
+ # """[主机指令]测试指令-DAC输出"""
+ # print('Command 500 测试指令-DAC输出', end=" : ")
+ # data = entity.get_master_command500_req_struct_TEST_TYPE_DAC()
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand500_TEST_TYPE_PWM(self):
+ # """[主机指令]测试指令-PWM"""
+ # print('Command 500 测试指令-PWM', end=" : ")
+ # data = entity.get_master_command500_req_struct_PWM()
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand500_TEST_TYPE_EEPROM_M95_WRITE(self):
+ # """[主机指令]测试指令-m95写入测试"""
+ # print('Command 500 测试指令-m95写入测试', end=" : ")
+ # data = entity.get_master_command500_req_struct(
+ # 16, 9, (1, 2, 3, 4, 5, 6, 7, 8, 9))
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+
+ # def testReqCommand31(self):
+ # """[主机指令]扩展指令(读取压缩状态映射)"""
+ # print('Command 31 扩展指令(读取压缩状态映射)', end=" : ")
+ # data = entity.get_master_command31_req_struct(0x020B,0x00,0x28)
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand129(self):
+ # """[主机指令]自定义参数读取"""
+ # print('Command 129 自定义参数读取', end=" : ")
+ # data = entity.get_master_command129_req_struct()
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand130(self):
+ # """[主机指令]自定义参数设置"""
+ # print('Command 130 自定义参数设置', end=" : ")
+ # data = entity.get_master_command130_req_struct()
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand132(self):
+ # """[主机指令]自定义参数读取(拓展)"""
+ # print('Command 132 自定义参数读取(拓展)', end=" : ")
+ # data = entity.get_master_command132_req_struct(15)
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand134(self):
+ # """[主机指令]读取文件内容"""
+ # print('Command 134 读取文件内容', end=" : ")
+ # data = entity.get_master_command134_req_struct()
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand138(self):
+ # """[主机指令]读取其他状态"""
+ # print('Command 138 读取其他状态', end=" : ")
+ # data = entity.hart_command_req_t()
+ # data.set_command(138)
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand140(self):
+ # """[主机指令]返回出厂设置"""
+ # print('Command 140 返回出厂设置', end=" : ")
+ # data = entity.hart_command_req_t()
+ # data.set_command(140)
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand141(self):
+ # """[主机指令]设置写入保护"""
+ # print('Command 141 设置写入保护', end=" : ")
+ # data = entity.get_master_command141_req_struct(1)
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand142(self):
+ # """[主机指令]自整定"""
+ # print('Command 142 自整定', end=" : ")
+ # data = entity.get_master_command142_req_struct(1)
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand144(self):
+ # """[主机指令]读取阀门序列号"""
+ # print('Command 144 读取阀门序列号', end=" : ")
+ # data = entity.hart_command_req_t()
+ # data.set_command(144)
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand145(self):
+ # """[主机指令]读取仪器序列号"""
+ # print('Command 145 读取仪器序列号', end=" : ")
+ # data = entity.hart_command_req_t()
+ # data.set_command(145)
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand146(self):
+ # """[主机指令]读取标准跨度信息"""
+ # print('Command 146 读取标准跨度信息', end=" : ")
+ # data = entity.hart_command_req_t()
+ # data.set_command(146)
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand147(self):
+ # """[主机指令]读取设备等级"""
+ # print('Command 147 读取设备等级', end=" : ")
+ # data = entity.hart_command_req_t()
+ # data.set_command(147)
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand151(self):
+ # """[主机指令]读取版本信息"""
+ # print('Command 151 读取版本信息', end=" : ")
+ # data = entity.hart_command_req_t()
+ # data.set_command(151)
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand153(self):
+ # """[主机指令]读取校准记录"""
+ # print('Command 153 读取校准记录', end=" : ")
+ # data = entity.hart_command_req_t()
+ # data.set_command(153)
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+
+ # def testReqCommand155(self):
+ # """[主机指令]执行诊断"""
+ # print('Command 155 执行诊断', end=" : ")
+ # data = entity.get_master_command155_req_struct()
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand157(self):
+ # """[主机指令]停止诊断"""
+ # print('Command 157 停止诊断', end=" : ")
+ # data = entity.hart_command_req_t()
+ # data.set_command(157)
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand167(self):
+ # """[主机指令]写入操作日期和用户"""
+ # print('Command 167 写入操作日期和用户', end=" : ")
+ # data = entity.get_master_command167_req_struct()
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+
+ # def testReqCommand168(self):
+ # """[主机指令]读取部分行程警报"""
+ # print('Command 168 读取部分行程警报', end=" : ")
+ # data = entity.hart_command_req_t()
+ # data.set_command(168)
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+ # def testReqCommand170(self):
+ # """[主机指令]读取制造信息序列号"""
+ # print('Command 170 读取制造信息序列号', end=" : ")
+ # data = entity.get_master_command170_req_struct()
+ # ret = self.dll.hart_master_command_req(byref(data))
+ # self.assertTrue(bool(ret), "testReqCommand failed")
+ # pass
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/User/hart/test/src/test_hart_slave_req.py b/User/hart/test/src/test_hart_slave_req.py
new file mode 100644
index 0000000..7468524
--- /dev/null
+++ b/User/hart/test/src/test_hart_slave_req.py
@@ -0,0 +1,893 @@
+'''
+Author: shenghao.xu
+Date: 2023-03-30 23:12:20
+LastEditors: Please set LastEditors
+LastEditTime: 2024-09-10 09:16:02
+FilePath: \hart\test\test_hart_slave_req.py
+Description: 测试从机接收指令
+email:545403892@qq.com
+Copyright (c) 2023 by shenghao.xu, All Rights Reserved.
+'''
+
+import os
+import sys
+import unittest
+from ctypes import *
+from ctypes import cdll
+
+import pkg.entity as entity
+import pkg.common as common
+import test_hart_master_req as master
+case_count = 0
+
+
+class TestHartSlaveReqCases(unittest.TestCase):
+ def init(cls) -> None:
+ cls.dll = cdll.LoadLibrary('./hart.dll')
+ pass
+
+ @classmethod
+ def setUpClass(cls) -> None:
+ cls.master = master.TestHartMasterReqCases()
+ cls.master.init()
+
+ cls.init(cls)
+ print('[TestHartSlaveReqCases] 从机接口开始测试...')
+ pass
+
+ @classmethod
+ def tearDownClass(cls) -> None:
+ print('[TestHartSlaveReqCases] 结束测试,测试用例%d个' % case_count)
+ print('----------------------------------------------------------------------')
+ print("\r")
+ pass
+
+ def setUp(self) -> None:
+ global case_count
+ case_count += 1
+ print("\r")
+ self.master.master_init()
+ pass
+
+ def tearDown(self) -> None:
+ pass
+
+ def slaver_send(self):
+ self.slaver_init()
+ ret = self.dll.hart_handle(0,
+ byref(common.bytes_to_ctypes(self.master.hart.response)), len(self.master.hart.response))
+ self.assertTrue(bool(ret), "hart_handle failed")
+
+ def master_send(self):
+ self.master_init()
+ ret = self.dll.hart_handle(0,
+ byref(common.bytes_to_ctypes(self.master.hart.response)), len(self.master.hart.response))
+ self.assertTrue(bool(ret), "hart_handle failed")
+
+ def response_parse(self, data, len):
+ self.master_init()
+ ret = self.dll.hart_handle_parse(byref(common.bytes_to_ctypes(
+ data)), len)
+ self.assertTrue(bool(ret), "hart_handle_parse failed")
+ pass
+
+ def slaver_init(self):
+ self.hart = entity.get_slave_struct()
+ ret = self.dll.hart_init(byref(self.hart))
+ self.assertTrue(bool(ret), "hart_init failed")
+ pass
+
+ def master_init(self):
+ self.hart = entity.get_master_struct()
+ ret = self.dll.hart_init(byref(self.hart))
+ self.assertTrue(bool(ret), "hart_init failed")
+ pass
+
+ def testReqCommand000(self):
+ """[从机指令]读取唯一标识命令V5"""
+ print('Command 0 读取唯一标识命令V5 短帧回复', end=" : ")
+ with common.HiddenPrints():
+ self.master.testReqCommand000Short() # 模拟主机发送指令
+ self.slaver_send()
+
+ # self.master.master_init()
+ # print('Command 0 读取唯一标识命令V5 长帧回复', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand000Long() # 模拟主机发送指令
+ # self.slaver_send()
+ # pass
+
+ # def testReqCommand001(self):
+ # print('Command 1 读取主变量V5 长帧回复', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand001() # 模拟主机发送指令
+
+ # self.slaver_send()
+ # pass
+
+ # def testReqCommand002(self):
+ # print('Command 2 读取回路电流和量程百分比 长帧回复', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand002() # 模拟主机发送指令
+
+ # self.slaver_send()
+ # pass
+
+ # def testReqCommand003(self):
+ # print('Command 3 读取动态变量和回路电流 长帧回复', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand003() # 模拟主机发送指令
+
+ # self.slaver_send()
+ # pass
+
+ # def testReqCommand006(self):
+ # print('Command 6 写入轮训地址 长帧回复', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand006() # 模拟主机发送指令
+
+ # self.slaver_send()
+ # pass
+
+ # def testReqCommand007(self):
+ # print('Command 7 读取循环配置 长帧回复', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand007() # 模拟主机发送指令
+
+ # self.slaver_send()
+ # pass
+
+ # def testReqCommand008(self):
+ # print('Command 8 读取动态变量分类 长帧回复', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand008() # 模拟主机发送指令
+
+ # self.slaver_send()
+ # pass
+
+ # def testReqCommand009(self):
+ # print('Command 9 读取具有状态的设备变量 长帧回复', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand009() # 模拟主机发送指令
+
+ # self.slaver_send()
+ # pass
+
+ # def testReqCommand011(self):
+ # print('Command 11 读取与标签关联的唯一标识符 长帧回复', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand011() # 模拟主机发送指令
+
+ # self.slaver_send()
+ # pass
+
+ # def testReqCommand012(self):
+ # print('Command 12 读取消息 长帧回复', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand012() # 模拟主机发送指令
+
+ # self.slaver_send()
+ # print(common.ascii_to_str(self.hart.response[15:15+24]))
+ # pass
+
+ # def testReqCommand013(self):
+ # print('Command 13 读取标签、描述符、日期 长帧回复', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand013() # 模拟主机发送指令
+
+ # self.slaver_send()
+ # offset = 15
+ # # 读取标签
+ # print(common.ascii_to_str(self.hart.response[offset:offset+6]))
+ # offset += 6
+ # # 读取描述
+ # print(common.ascii_to_str(self.hart.response[offset:offset+12]))
+ # offset += 12
+ # # 读取日期
+ # print(self.hart.response[offset]+1900,
+ # self.hart.response[offset+1], self.hart.response[offset+2])
+ # pass
+
+ # def testReqCommand014(self):
+ # print('Command 14 读取主变量传感器信息', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand014() # 模拟主机发送指令
+
+ # self.slaver_send()
+ # pass
+
+ # def testReqCommand015(self):
+ # print('Command 15 读取设备信息', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand015() # 模拟主机发送指令
+
+ # self.slaver_send()
+ # pass
+
+ # def testReqCommand016(self):
+ # print('Command 16 读取最终总装编号', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand016() # 模拟主机发送指令
+
+ # self.slaver_send()
+ # pass
+
+ # def testReqCommand017(self):
+ # print('Command 17 写入消息', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand017() # 模拟主机发送指令
+
+ # self.slaver_send()
+ # print(common.ascii_to_str(self.hart.response[15:15+24]))
+ # pass
+
+ # def testReqCommand018(self):
+ # print('Command 18 写标签、描述符、日期', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand018() # 模拟主机发送指令
+
+ # self.slaver_send()
+ # offset=15
+ # # 读取标签
+ # print(common.ascii_to_str(self.hart.response[offset:offset+6]))
+ # offset+=6
+ # # 读取描述
+ # print(common.ascii_to_str(self.hart.response[offset:offset+12]))
+ # offset+=12
+ # # 读取日期
+ # print(self.hart.response[offset],self.hart.response[offset+1],self.hart.response[offset+2]+1900)
+ # pass
+
+ # def testReqCommand019(self):
+ # print('Command 19 总装编号', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand019() # 模拟主机发送指令
+
+ # self.slaver_send()
+ # offset=15
+ # # 读取总装编号
+ # common.print_hex_data_space(self.hart.response[offset:offset+3],True)
+ # pass
+
+ # def testReqCommand020(self):
+ # print('Command 20 读取长标签', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand020() # 模拟主机发送指令
+
+ # self.slaver_send()
+ # # 读取长标签
+ # offset = 18
+ # print(common.ascii_to_str(self.hart.response[offset:offset+32]))
+
+ # def testReqCommand021(self):
+ # print('Command 21 读取与长标签关联的唯一标识符', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand021() # 模拟主机发送指令
+ # self.slaver_send()
+
+ # def testReqCommand022(self):
+ # print('Command 22 写长标签', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand022() # 模拟主机发送指令
+
+ # self.slaver_send()
+ # # 读取长标签
+ # offset=18
+ # print(common.ascii_to_str(self.hart.response[offset:offset+32]))
+
+ # def testReqCommand038(self):
+ # print('Command 38 重置配置更改标志', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand038() # 模拟主机发送指令
+ # self.slaver_send()
+
+ # def testReqCommand048(self):
+ # print('Command 48 读取附加设备状态', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand048() # 模拟主机发送指令
+ # self.slaver_send()
+
+ # def testReqCommand033(self):
+ # print('Command 33 读取设备变量', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand033() # 模拟主机发送指令
+ # self.slaver_send()
+
+ # def testReqCommand034(self):
+ # print('Command 34 写入主变量阻尼值V5', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand034() # 模拟主机发送指令
+ # self.slaver_send()
+
+ # def testReqCommand035(self):
+ # print('Command 35 写入主变量范围值V5', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand035() # 模拟主机发送指令
+ # self.slaver_send()
+
+ # def testReqCommand036(self):
+ # print('Command 36 设置主变量上限值V5', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand036() # 模拟主机发送指令
+ # self.slaver_send()
+
+ # def testReqCommand037(self):
+ # print('Command 37 设置主变量下限值V5', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand037() # 模拟主机发送指令
+ # self.slaver_send()
+
+ # def testReqCommand039(self):
+ # print('Command 39 EEPROM控制V5', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand039() # 模拟主机发送指令
+ # self.slaver_send()
+
+ # def testReqCommand040(self):
+ # print('Command 40 进入/退出固定电流模式V5', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand040() # 模拟主机发送指令
+ # self.slaver_send()
+
+ # def testReqCommand041(self):
+ # print('Command 41 执行自检V5', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand041() # 模拟主机发送指令
+ # self.slaver_send()
+
+ # def testReqCommand042(self):
+ # print('Command 42 设备复位', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand042() # 模拟主机发送指令
+ # self.slaver_send()
+
+ # def testReqCommand043(self):
+ # print('Command 43 设置主变量零V5', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand043() # 模拟主机发送指令
+ # self.slaver_send()
+
+ # def testReqCommand044(self):
+ # print('Command 44 编写主变量单元V5', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand044() # 模拟主机发送指令
+ # self.slaver_send()
+
+ # def testReqCommand045(self):
+ # print('Command 45 微调回路电流归零V5', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand045() # 模拟主机发送指令
+ # self.slaver_send()
+
+ # def testReqCommand046(self):
+ # print('Command 46 微调回路电流增益V5', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand046() # 模拟主机发送指令
+ # self.slaver_send()
+
+ # def testReqCommand047(self):
+ # print('Command 47 编写主变量传递函数V5', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand047() # 模拟主机发送指令
+ # self.slaver_send()
+
+ # def testReqCommand049(self):
+ # print('Command 49 写入主变量传感器序列号V5', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand049() # 模拟主机发送指令
+ # self.slaver_send()
+
+ # def testReqCommand050(self):
+ # print('Command 50 读取动态变量赋值V5', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand050() # 模拟主机发送指令
+ # self.slaver_send()
+
+ # def testReqCommand051(self):
+ # print('Command 51 编写动态变量赋值V5', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand051() # 模拟主机发送指令
+ # self.slaver_send()
+
+ # def testReqCommand052(self):
+ # print('Command 52 设置设备变量零V5', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand052() # 模拟主机发送指令
+ # self.slaver_send()
+
+ # def testReqCommand053(self):
+ # print('Command 53 写入设备变量单位V5', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand053() # 模拟主机发送指令
+ # self.slaver_send()
+
+ # def testReqCommand054(self):
+ # print('Command 54 读取设备变量信息V5', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand054() # 模拟主机发送指令
+ # self.slaver_send()
+
+ # def testReqCommand055(self):
+ # print('Command 55 写入设备可变阻尼值V5', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand055() # 模拟主机发送指令
+ # self.slaver_send()
+
+ # def testReqCommand056(self):
+ # print('Command 56 写入设备可变传感器序列号V5', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand056() # 模拟主机发送指令
+ # self.slaver_send()
+
+ # def testReqCommand057(self):
+ # print('Command 57 读取单位标签、描述符、日期V5', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand057() # 模拟主机发送指令
+ # self.slaver_send()
+ # offset=15
+ # # 读取标签
+ # print(common.ascii_to_str(self.hart.response[offset:offset+6]))
+ # offset+=6
+ # # 读取描述
+ # print(common.ascii_to_str(self.hart.response[offset:offset+12]))
+ # offset+=12
+ # # 读取日期
+ # print(self.hart.response[offset],self.hart.response[offset+1],self.hart.response[offset+2]+1900)
+
+ # def testReqCommand058(self):
+ # print('Command 58 编写单位标签、描述符、日期V5', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand058() # 模拟主机发送指令
+ # self.slaver_send()
+ # offset=15
+ # # 读取标签
+ # print(common.ascii_to_str(self.hart.response[offset:offset+6]))
+ # offset+=6
+ # # 读取描述
+ # print(common.ascii_to_str(self.hart.response[offset:offset+12]))
+ # offset+=12
+ # # 读取日期
+ # print(self.hart.response[offset],self.hart.response[offset+1],self.hart.response[offset+2]+1900)
+
+ # def testReqCommand059(self):
+ # print('Command 59 写入响应序码数V5', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand059() # 模拟主机发送指令
+ # self.slaver_send()
+
+ # def testReqCommand060(self):
+ # print('Command 60 读取模拟通道和范围百分比V5', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand060() # 模拟主机发送指令
+ # self.slaver_send()
+
+ # def testReqCommand061(self):
+ # print('Command 61 读取模拟通道和范围百分比V5', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand061() # 模拟主机发送指令
+ # self.slaver_send()
+
+ # def testReqCommand062(self):
+ # print('Command 62 读取模拟通道V5', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand062() # 模拟主机发送指令
+ # self.slaver_send()
+
+ # def testReqCommand063(self):
+ # print('Command 63 读取模拟通道信息V5', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand063() # 模拟主机发送指令
+ # self.slaver_send()
+
+ # def testReqCommand064(self):
+ # print('Command 64 写入模拟通道附加阻尼值V5', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand064() # 模拟主机发送指令
+ # self.slaver_send()
+
+ # def testReqCommand065(self):
+ # print('Command 65 写入模拟通道范围值V5', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand065() # 模拟主机发送指令
+ # self.slaver_send()
+
+ # def testReqCommand066(self):
+ # print('Command 66 进入/退出固定模拟通道模式V5', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand066() # 模拟主机发送指令
+ # self.slaver_send()
+
+ # def testReqCommand067(self):
+ # print('Command 67 调整模拟通道零V5', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand066()
+ # self.slaver_send()
+ # self.master.master_init()
+ # with common.HiddenPrints():
+ # self.master.testReqCommand067() # 模拟主机发送指令
+ # self.slaver_send()
+
+ # def testReqCommand068(self):
+ # print('Command 68 微调模拟通道增益V5', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand066()
+ # self.slaver_send()
+ # self.master.master_init()
+ # with common.HiddenPrints():
+ # self.master.testReqCommand068() # 模拟主机发送指令
+ # self.slaver_send()
+
+ # def testReqCommand069(self):
+ # print('Command 69 写入模拟通道传递函数代码', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand069() # 模拟主机发送指令
+ # self.slaver_send()
+
+ # def testReqCommand070(self):
+ # print('Command 70 读取模拟通道端点值V5', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand070() # 模拟主机发送指令
+ # self.slaver_send()
+
+ # def testReqCommand071(self):
+ # print('Command 71 锁定装置', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand071() # 模拟主机发送指令
+ # self.slaver_send()
+
+ # def testReqCommand072(self):
+ # print('Command 72 呼叫', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand072() # 模拟主机发送指令
+ # self.slaver_send()
+
+ # def testReqCommand073(self):
+ # print('Command 73 查找设备', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand073() # 模拟主机发送指令
+ # self.slaver_send()
+
+ # def testReqCommand074(self):
+ # print('Command 74 读取I/O系统功能', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand074() # 模拟主机发送指令
+ # self.master_send()
+
+ # def testReqCommand075(self):
+ # print('Command 75 轮询子设备', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand075() # 模拟主机发送指令
+ # self.master_send()
+
+ # def testReqCommand076(self):
+ # print('Command 76 读锁定设备状态', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand076() # 模拟主机发送指令
+ # self.slaver_send()
+
+ # def testReqCommand079(self):
+ # print('Command 79 写入设备变量', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand079() # 模拟主机发送指令
+ # self.slaver_send()
+
+ # def testReqCommand080(self):
+ # print('Command 80 读取设备可变微调点', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand080() # 模拟主机发送指令
+ # self.slaver_send()
+
+ # def testReqCommand081(self):
+ # print('Command 81 读取设备变量调整指南', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand081() # 模拟主机发送指令
+ # self.slaver_send()
+
+ # def testReqCommand082(self):
+ # print('Command 82 写入设备可变微调点', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand082() # 模拟主机发送指令
+ # self.slaver_send()
+
+ # def testReqCommand083(self):
+ # print('Command 83 重置设备变量调整', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand083() # 模拟主机发送指令
+ # self.slaver_send()
+
+ # def testReqCommand084(self):
+ # print('Command 84 读取子设备标识摘要', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand084() # 模拟主机发送指令
+ # self.master_send()
+
+ # def testReqCommand085(self):
+ # print('Command 85 读取I/O通道统计信息', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand085() # 模拟主机发送指令
+ # self.master_send()
+
+ # def testReqCommand086(self):
+ # print('Command 86 读取子设备统计信息', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand086() # 模拟主机发送指令
+ # self.master_send()
+
+ # def testReqCommand087(self):
+ # print('Command 87 写入I/O系统主模式', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand087() # 模拟主机发送指令
+ # self.master_send()
+
+ # def testReqCommand088(self):
+ # print('Command 88 写入I/O系统重试计数', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand088() # 模拟主机发送指令
+ # self.master_send()
+
+ # def testReqCommand089(self):
+ # print('Command 89 设置实时时钟', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand089() # 模拟主机发送指令
+ # self.slaver_send()
+
+ # offset = 19
+ # # 读取日期
+ # print(self.hart.response[offset]+1900, self.hart.response[offset+1],
+ # self.hart.response[offset+2])
+
+ # def testReqCommand090(self):
+ # print('Command 90 读取实时时钟', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand090() # 模拟主机发送指令
+ # self.slaver_send()
+
+ # def testReqCommand091(self):
+ # print('Command 91 读取趋势配置', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand091() # 模拟主机发送指令
+ # self.slaver_send()
+
+ # def testReqCommand092(self):
+ # print('Command 92 写入趋势配置', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand092() # 模拟主机发送指令
+ # self.slaver_send()
+
+ # def testReqCommand093(self):
+ # print('Command 93 写入趋势配置', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand093() # 模拟主机发送指令
+ # self.slaver_send()
+
+ # def testReqCommand095(self):
+ # print('Command 95 读取I/O系统客户端通信统计信息', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand095() # 模拟主机发送指令
+ # self.slaver_send()
+
+ # def testReqCommand096(self):
+ # print('Command 96 读取同步操作', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand096() # 模拟主机发送指令
+ # self.slaver_send()
+
+ # def testReqCommand097(self):
+ # print('Command 97 配置同步操作', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand097() # 模拟主机发送指令
+ # self.slaver_send()
+
+ # def testReqCommand098(self):
+ # print('Command 98 读取命令操作', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand098() # 模拟主机发送指令
+ # self.slaver_send()
+
+ # def testReqCommand099(self):
+ # print('Command 99 配置命令操作', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand099() # 模拟主机发送指令
+ # self.slaver_send()
+
+ # def testReqCommand100(self):
+ # print('Command 100 写入主变量报警码', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand100() # 模拟主机发送指令
+ # self.slaver_send()
+
+ # def testReqCommand101(self):
+ # print('Command 101 读取子设备到突发消息映射', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand101() # 模拟主机发送指令
+ # self.slaver_send()
+
+ # def testReqCommand102(self):
+ # print('Command 102 将子设备映射到突发信息', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand102() # 模拟主机发送指令
+ # self.slaver_send()
+
+ # def testReqCommand103(self):
+ # print('Command 103 写入突发周期', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand103() # 模拟主机发送指令
+ # self.slaver_send()
+
+ # def testReqCommand104(self):
+ # print('Command 104 写入突发触发器', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand104() # 模拟主机发送指令
+ # self.slaver_send()
+
+ # def testReqCommand105(self):
+ # print('Command 105 读取突发模式配置', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand105() # 模拟主机发送指令
+ # self.slaver_send()
+
+ # def testReqCommand107(self):
+ # print('Command 107 写入突发设备变量', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand107() # 模拟主机发送指令
+ # self.slaver_send()
+
+ # def testReqCommand110(self):
+ # print('Command 110 读取所有动态变量V5', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand110() # 模拟主机发送指令
+ # self.slaver_send()
+
+ # def testReqCommand512(self):
+ # print('Command 512 读取国家代码', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand512() # 模拟主机发送指令
+ # self.slaver_send()
+
+ # def testReqCommand513(self):
+ # print('Command 513 编写国家代码', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand513() # 模拟主机发送指令
+ # self.slaver_send()
+
+# 用户自定义
+ # def testReqCommand254(self):
+ # print('Command 254 数据样品型号(气开\气关)', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand254() # 模拟主机发送指令
+ # self.slaver_send()
+
+ # def testReqCommand255(self):
+ # print('Command 255 读取模拟量数值', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand255() # 模拟主机发送指令
+ # self.slaver_send()
+
+ # def testReqCommand256(self):
+ # print('Command 256 读取转化的数值', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand256() # 模拟主机发送指令
+ # self.slaver_send()
+
+ # def testReqCommand257(self):
+ # print('Command 257 寻找、计算P / I / D', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand257() # 模拟主机发送指令
+ # self.slaver_send()
+
+ # def testReqCommand258(self):
+ # print('Command 258 计算 摩擦力', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand258() # 模拟主机发送指令
+ # self.slaver_send()
+
+ # def testReqCommand259(self):
+ # print('Command 259 计算 弹簧力', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand259() # 模拟主机发送指令
+ # self.slaver_send()
+
+ # def testReqCommand260(self):
+ # print('Command 260 编写参数配置', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand260() # 模拟主机发送指令
+ # self.slaver_send()
+
+ # def testReqCommand261(self):
+ # print('Command 261 读取参数配置', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand261() # 模拟主机发送指令
+ # self.slaver_send()
+
+ # def testReqCommand500(self):
+ # print('Command 500 测试指令-通用指令', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand500() # 模拟主机发送指令
+ # self.slaver_send()
+
+ # def testReqCommand500_TEST_TYPE_RTC_WRITE(self):
+ # print('Command 500 测试指令-RTC写入', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand500_TEST_TYPE_RTC_WRITE() # 模拟主机发送指令
+ # self.slaver_send()
+
+ # def testReqCommand500_TEST_TYPE_RTC_READ(self):
+ # print('Command 500 测试指令-RTC读取', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand500_TEST_TYPE_RTC_READ() # 模拟主机发送指令
+ # self.slaver_send()
+
+ # def testReqCommand500_TEST_TYPE_ADC0(self):
+ # print('Command 500 测试指令-回路电流', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand500_TEST_TYPE_ADC0() # 模拟主机发送指令
+ # self.slaver_send()
+
+ # def testReqCommand500_TEST_TYPE_DAC(self):
+ # print('Command 500 测试指令-DAC输出', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand500_TEST_TYPE_DAC() # 模拟主机发送指令
+ # self.slaver_send()
+
+ # def testReqCommand500_TEST_TYPE_PWM(self):
+ # print('Command 500 测试指令-PWM', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand500_TEST_TYPE_PWM() # 模拟主机发送指令
+ # self.slaver_send()
+
+ # def testReqCommand500_TEST_TYPE_EEPROM_M95_WRITE(self):
+ # print('Command 500 测试指令-m95写入测试', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand500_TEST_TYPE_EEPROM_M95_WRITE() # 模拟主机发送指令
+ # self.slaver_send()
+
+ # def testReqCommand129(self):
+ # print('Command 129 自定义参数读取', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand129() # 模拟主机发送指令
+ # self.slaver_send()
+
+ # def testReqCommand130(self):
+ # print('Command 130 自定义参数设置', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand130() # 模拟主机发送指令
+ # self.slaver_send()
+
+ # def testReqCommand140(self):
+ # print('Command 140 返回出厂设置', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand140() # 模拟主机发送指令
+ # self.slaver_send()
+
+ # def testReqCommand141(self):
+ # print('Command 141 设置写入保护', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand141() # 模拟主机发送指令
+ # self.slaver_send()
+
+ # def testReqCommand142(self):
+ # print('Command 142 设置写入保护', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand142() # 模拟主机发送指令
+ # self.slaver_send()
+
+ # def testReqCommand155(self):
+ # print('Command 155 执行诊断', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand155() # 模拟主机发送指令
+ # self.slaver_send()
+
+ # def testReqCommand157(self):
+ # print('Command 157 停止诊断', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand157() # 模拟主机发送指令
+ # self.slaver_send()
+
+ # def testReqCommand167(self):
+ # print('Command 167 写入操作日期和用户', end=" : ")
+ # with common.HiddenPrints():
+ # self.master.testReqCommand167() # 模拟主机发送指令
+ # self.slaver_send()
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/User/lib/bootload/bootload.c b/User/lib/bootload/bootload.c
deleted file mode 100644
index 6dacd43..0000000
--- a/User/lib/bootload/bootload.c
+++ /dev/null
@@ -1,229 +0,0 @@
-#include "bootload.h"
-#include "ymodem.h"
-#include "sys.h"
-#include "delay.h"
-#include "cmac.h"
-#define AES_CMAC_DIGEST_LENGTH 16
-typedef void (*fnc_ptr)(void); // 用于跳转到应用程序的函数指针
-static bootload_transmit_callback transmit_callback = NULL;
-static bootload_end_callback end_callback = NULL;
-uint8_t upgrade_key[] =
- {
- 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6,
- 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C}; // 密钥
-
-static AES_CMAC_CTX upgrade_ctx; /**< AES CMAC context for upgrade process */
-static uint8_t pre_upgrade_mic[AES_CMAC_DIGEST_LENGTH]; /**< MIC (Message Integrity Code) before upgrade */
-static uint8_t upgrade_mic[AES_CMAC_DIGEST_LENGTH]; /**< MIC (Message Integrity Code) after upgrade */
-static uint32_t flashdestination = BOOTLOAD_APP_BACKUP_ADDR_START; /**< Flash destination address for bootloading */
-static uint32_t upgrade_size = 0; /**< Size of the upgrade */
-static uint8_t read_cache[LL_FLASH_PAGE_SIZE]; /**< Read cache for flash pages */
-static uint8_t data_src_from; /**< Data source for bootloading */
-
-/**
- * @brief Perform bootload inspection.
- *
- * This function calls the `rym_process()` function to perform bootload inspection.
- */
-void bootload_inspection(void)
-{
- rym_process();
-}
-
-/**
- * @brief Checks if the bootload timeout has occurred.
- *
- * This function calls the `rym_timeout()` function to determine if the bootload timeout has occurred.
- *
- * @return TRUE if the bootload timeout has occurred, FALSE otherwise.
- */
-BOOL bootload_timeout(void)
-{
- return rym_timeout();
-}
-
-/**
- * @brief Handles the beginning of the bootloading process.
- *
- * This function is responsible for handling the initial steps of the bootloading process.
- * It checks if the length of the data to be bootloaded is greater than the end address of the application area.
- * If the length is greater, it returns an error code indicating that the bootloading cannot proceed.
- * Otherwise, it sets the flash destination address to the start address of the backup area,
- * erases the bank of the flash memory where the application is stored,
- * and initializes the AES-CMAC context for the upgrade process.
- *
- * @param p Pointer to the data to be bootloaded.
- * @param len Length of the data to be bootloaded.
- * @return Error code indicating the result of the operation.
- * - RYM_CODE_CAN: If the length of the data is greater than the end address of the application area.
- * - RYM_CODE_NONE: If the operation is successful.
- */
-static rym_code_e on_begin(uint8_t *p, uint32_t len)
-{
- if (len > BOOTLOAD_APP_END_ADDRESS)
- {
- return RYM_CODE_CAN;
- }
-
- flashdestination = BOOTLOAD_APP_BACKUP_ADDR_START;
- LL_FLASH_Unlock(FLASH);
- LL_FLASH_EraseBank(LL_FLASH_BANK2);
- LL_FLASH_Lock(FLASH);
-
- AES_CMAC_Init(&upgrade_ctx);
- AES_CMAC_SetKey(&upgrade_ctx, upgrade_key);
- return RYM_CODE_NONE;
-}
-
-/**
- * @brief Handles the received data and programs it into the flash memory.
- *
- * This function unlocks the flash memory, programs the received data into the specified flash destination,
- * locks the flash memory again, updates the AES-CMAC context with the received data, and increments the flash destination.
- *
- * @param p Pointer to the data buffer.
- * @param len Length of the data buffer.
- * @return The result code indicating the success or failure of the operation.
- */
-static rym_code_e on_data(uint8_t *p, uint32_t len)
-{
- LL_FLASH_Unlock(FLASH);
- LL_FLASH_Program(flashdestination, p, len);
- LL_FLASH_Lock(FLASH);
- AES_CMAC_Update(&upgrade_ctx, p, len);
- flashdestination += len;
- return RYM_CODE_NONE;
-}
-
-/**
- * @brief Calculate the MIC (Message Integrity Code) for the firmware upgrade.
- *
- * This function calculates the MIC using AES-CMAC algorithm for the firmware upgrade data.
- * It reads the firmware data from flash memory in pages and updates the MIC calculation.
- * Finally, it compares the calculated MIC with the pre-upgrade MIC to determine the success of the upgrade.
- *
- * @param p Pointer to the firmware data.
- * @param len Length of the firmware data.
- * @return The result code indicating the success or failure of the upgrade process.
- */
-static rym_code_e on_end(uint8_t *p, uint32_t len)
-{
- AES_CMAC_Final(pre_upgrade_mic, &upgrade_ctx);
- upgrade_size = flashdestination - BOOTLOAD_APP_BACKUP_ADDR_START;
-
- AES_CMAC_Init(&upgrade_ctx);
- AES_CMAC_SetKey(&upgrade_ctx, upgrade_key);
- uint32_t start = BOOTLOAD_APP_BACKUP_ADDR_START;
- uint16_t num = (upgrade_size / LL_FLASH_PAGE_SIZE);
- uint16_t remain = (upgrade_size % LL_FLASH_PAGE_SIZE);
-
- // STM32L476RG的flash页大小为2K,先读取整数页,再读取余数
- for (uint16_t i = 0; i < num; i++)
- {
- LL_FLASH_Read((start + i * (LL_FLASH_PAGE_SIZE)), read_cache, LL_FLASH_PAGE_SIZE);
- AES_CMAC_Update(&upgrade_ctx, read_cache, LL_FLASH_PAGE_SIZE);
- }
-
- if (remain)
- {
- osel_memset(read_cache, 0, LL_FLASH_PAGE_SIZE);
- LL_FLASH_Read((start + num * (LL_FLASH_PAGE_SIZE)), read_cache, remain);
- AES_CMAC_Update(&upgrade_ctx, read_cache, remain);
- }
-
- AES_CMAC_Final(upgrade_mic, &upgrade_ctx);
-
- // 比较mic,相同可以写入标志位告知应用程序升级成功
- if (osel_memcmp(upgrade_mic, pre_upgrade_mic, AES_CMAC_DIGEST_LENGTH) == 0)
- {
- end_callback(TRUE);
- }
- else
- {
- end_callback(FALSE);
- }
- return RYM_CODE_NONE;
-}
-
-/**
- * @brief Handles the transmission of data.
- *
- * This function calls the transmit_callback function to transmit the data from the specified source.
- *
- * @param p Pointer to the data buffer.
- * @param len Length of the data buffer.
- * @return The return code indicating the status of the transmission.
- */
-static rym_code_e on_transmit(uint8_t *p, uint32_t len)
-{
- transmit_callback(data_src_from, p, (uint16_t)len);
- return RYM_CODE_NONE;
-}
-
-/**
- * @brief Initializes the bootload module.
- *
- * This function initializes the bootload module by setting the transmit callback
- * and configuring the RYM module. It asserts if the initialization fails.
- *
- * @param transmit The transmit callback function.
- */
-void bootload_init(bootload_transmit_callback transmit, bootload_end_callback end)
-{
- BOOL res = FALSE;
-
- transmit_callback = transmit;
- end_callback = end;
-
- res = rym_init();
- DBG_ASSERT(res == TRUE __DBG_LINE);
-
- res = rym_config(on_begin, on_data, on_end, on_transmit, BOOTLOAD_TIMEOUT);
- DBG_ASSERT(res == TRUE __DBG_LINE);
-}
-
-/**
- * @brief Sets the data source index for bootload transmission.
- *
- * This function sets the data source index for bootload transmission. The data source index
- * determines the starting point from which the data will be transmitted.
- *
- * @param to_index The index of the data source.
- */
-void bootload_transmit_from(const uint8_t to_index)
-{
- data_src_from = to_index;
-}
-
-/**
- * @brief Jump to the specified address and execute the bootloader.
- *
- * @param address The entry address of the bootloader.
- */
-void bootload_jump(uint32_t address)
-{
- // Get the entry address of the application program
- fnc_ptr jump_to_bootload;
- jump_to_bootload = (fnc_ptr)(*(__IO uint32_t *)(address + 4));
-
- // Disable RCC
- RCC->APB1ENR1 = 0;
- RCC->APB1ENR2 = 0;
- RCC->APB2ENR = 0;
- RCC->AHB1ENR = 0;
- RCC->AHB2ENR = 0;
- RCC->AHB3ENR = 0;
-
- // Disable SysTick
- SysTick->CTRL = 0;
- // 清空SysTick
- SysTick->LOAD = 0;
- // 清空SysTick
- SysTick->VAL = 0;
- // 设置向量表偏移地址
- SCB->VTOR = address;
- // 设置堆栈指针
- sys_msr_msp(*(__IO uint32_t *)address);
- // 跳转
- jump_to_bootload();
-}
diff --git a/User/lib/bootload/bootload.h b/User/lib/bootload/bootload.h
index f888e28..e42c506 100644
--- a/User/lib/bootload/bootload.h
+++ b/User/lib/bootload/bootload.h
@@ -5,7 +5,7 @@
#include "flow.h"
#define BOOTLOAD_SET_FLAG 0xbb01
-#define BOOTLOAD_UNSET_FLAG 0xbb01
+#define BOOTLOAD_UNSET_FLAG 0xbb02
/**
* @brief Defines the start address of the application in flash memory.
*/
diff --git a/User/lib/bootload/test_ymodem.c b/User/lib/bootload/test_ymodem.c
deleted file mode 100644
index d7c6b08..0000000
--- a/User/lib/bootload/test_ymodem.c
+++ /dev/null
@@ -1,79 +0,0 @@
-#include "unity.h"
-#include "ymodem.c"
-
-void setUp(void)
-{
- // 这里可以进行每个测试用例开始前的设置
-}
-
-void tearDown(void)
-{
- // 这里可以进行每个测试用例结束后的清理
-}
-
-void test_CRC16(void)
-{
- unsigned char data[] = {0x01, 0x02, 0x03, 0x04, 0x05};
- TEST_ASSERT_EQUAL_HEX16(EXPECTED_CRC_VALUE, CRC16(data, sizeof(data)));
-}
-
-void test_IS_CAP_LETTER(void)
-{
- TEST_ASSERT_TRUE(IS_CAP_LETTER('A'));
- TEST_ASSERT_FALSE(IS_CAP_LETTER('a'));
-}
-
-void test_IS_LC_LETTER(void)
-{
- TEST_ASSERT_TRUE(IS_LC_LETTER('a'));
- TEST_ASSERT_FALSE(IS_LC_LETTER('A'));
-}
-
-void test_IS_09(void)
-{
- TEST_ASSERT_TRUE(IS_09('0'));
- TEST_ASSERT_FALSE(IS_09('A'));
-}
-
-void test_ISVALIDHEX(void)
-{
- TEST_ASSERT_TRUE(ISVALIDHEX('A'));
- TEST_ASSERT_TRUE(ISVALIDHEX('a'));
- TEST_ASSERT_TRUE(ISVALIDHEX('0'));
- TEST_ASSERT_FALSE(ISVALIDHEX('G'));
-}
-
-void test_ISVALIDDEC(void)
-{
- TEST_ASSERT_TRUE(ISVALIDDEC('0'));
- TEST_ASSERT_FALSE(ISVALIDDEC('A'));
-}
-
-void test_CONVERTDEC(void)
-{
- TEST_ASSERT_EQUAL_HEX8(0, CONVERTDEC('0'));
- TEST_ASSERT_EQUAL_HEX8(9, CONVERTDEC('9'));
-}
-
-void test_CONVERTHEX(void)
-{
- TEST_ASSERT_EQUAL_HEX8(10, CONVERTHEX('A'));
- TEST_ASSERT_EQUAL_HEX8(10, CONVERTHEX('a'));
- TEST_ASSERT_EQUAL_HEX8(0, CONVERTHEX('0'));
-}
-
-int main(void)
-{
- UNITY_BEGIN();
-
- RUN_TEST(test_CRC16);
- RUN_TEST(test_IS_CAP_LETTER);
- RUN_TEST(test_IS_LC_LETTER);
- RUN_TEST(test_IS_09);
- RUN_TEST(test_ISVALIDHEX);
- RUN_TEST(test_ISVALIDDEC);
- RUN_TEST(test_CONVERTDEC);
- RUN_TEST(test_CONVERTHEX);
-
- return UNITY_END();
-}
diff --git a/User/lib/bootload/ymodem.c b/User/lib/bootload/ymodem.c
deleted file mode 100644
index 8bafe13..0000000
--- a/User/lib/bootload/ymodem.c
+++ /dev/null
@@ -1,633 +0,0 @@
-/**
- * @file ymodem.c
- * @author xxx
- * @date 2024-02-18 19:32:40
- * @brief
- * 该模块实现了YMODEM协议的核心功能,包括初始化、配置、数据接收、握手、数据传输和结束处理。
- * 它使用了回调函数来处理不同阶段的事件,并使用信号量来同步不同的流程。CRC校验是用来确保数据传输的完整性和准确性
- * @copyright Copyright (c) 2024 by xxx, All Rights Reserved.
- */
-#include "ymodem.h"
-#include "sys.h"
-#include "delay.h"
-#include "flow.h"
-
-sqqueue_ctrl_t rym_sqqueue; // 一个接收队列控制结构体,用于管理接收到的数据。
-static uint32_t tm_sec = 0; // 握手超时时间,用于握手阶段的超时计时
-static enum rym_stage stage = RYM_STAGE_NONE; // 当前的阶段
-static int32_t rym_tm_sec = 0; // YMODEM超时计时器
-
-static uint8_t aPacketData[_RYM_PKG_SZ]; // 数据包缓冲区
-
-// 回调函数,用于处理不同阶段的事件
-static rym_callback rym_on_begin = NULL;
-static rym_callback rym_on_data = NULL;
-static rym_callback rym_on_end = NULL;
-static rym_callback rym_transmit = NULL;
-
-static struct flow handshake_fw; // 握手流程
-static struct flow trans_fw; // 传输流程
-static struct flow finsh_fw; // 结束流程
-static struct flow_sem msg_sem; // 消息信号量,用于同步
-
-static const uint16_t ccitt_table[256] =
- {
- 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7,
- 0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF,
- 0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6,
- 0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE,
- 0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485,
- 0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D,
- 0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4,
- 0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC,
- 0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823,
- 0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B,
- 0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12,
- 0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A,
- 0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41,
- 0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49,
- 0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70,
- 0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78,
- 0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F,
- 0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067,
- 0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E,
- 0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256,
- 0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D,
- 0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
- 0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C,
- 0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634,
- 0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB,
- 0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3,
- 0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A,
- 0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92,
- 0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9,
- 0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1,
- 0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8,
- 0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0};
-
-uint16_t CRC16(unsigned char *q, int len)
-{
- uint16_t crc = 0;
-
- while (len-- > 0)
- crc = (crc << 8) ^ ccitt_table[((crc >> 8) ^ *q++) & 0xff];
- return crc;
-}
-
-/* Exported macro ------------------------------------------------------------*/
-#define IS_CAP_LETTER(c) (((c) >= 'A') && ((c) <= 'F'))
-#define IS_LC_LETTER(c) (((c) >= 'a') && ((c) <= 'f'))
-#define IS_09(c) (((c) >= '0') && ((c) <= '9'))
-#define ISVALIDHEX(c) (IS_CAP_LETTER(c) || IS_LC_LETTER(c) || IS_09(c))
-#define ISVALIDDEC(c) IS_09(c)
-#define CONVERTDEC(c) (c - '0')
-
-#define CONVERTHEX_ALPHA(c) (IS_CAP_LETTER(c) ? ((c) - 'A' + 10) : ((c) - 'a' + 10))
-#define CONVERTHEX(c) (IS_09(c) ? ((c) - '0') : CONVERTHEX_ALPHA(c))
-/**
- * @brief Convert a string to an integer
- * @param p_inputstr: The string to be converted
- * @param p_intnum: The integer value
- * @retval 1: Correct
- * 0: Error
- */
-uint32_t Str2Int(uint8_t *p_inputstr, uint32_t *p_intnum)
-{
- uint32_t i = 0, res = 0;
- uint32_t val = 0;
-
- if ((p_inputstr[0] == '0') && ((p_inputstr[1] == 'x') || (p_inputstr[1] == 'X')))
- {
- i = 2;
- while ((i < 11) && (p_inputstr[i] != '\0'))
- {
- if (ISVALIDHEX(p_inputstr[i]))
- {
- val = (val << 4) + CONVERTHEX(p_inputstr[i]);
- }
- else
- {
- /* Return 0, Invalid input */
- res = 0;
- break;
- }
- i++;
- }
-
- /* valid result */
- if (p_inputstr[i] == '\0')
- {
- *p_intnum = val;
- res = 1;
- }
- }
- else /* max 10-digit decimal input */
- {
- while ((i < 11) && (res != 1))
- {
- if (p_inputstr[i] == '\0')
- {
- *p_intnum = val;
- /* return 1 */
- res = 1;
- }
- else if (((p_inputstr[i] == 'k') || (p_inputstr[i] == 'K')) && (i > 0))
- {
- val = val << 10;
- *p_intnum = val;
- res = 1;
- }
- else if (((p_inputstr[i] == 'm') || (p_inputstr[i] == 'M')) && (i > 0))
- {
- val = val << 20;
- *p_intnum = val;
- res = 1;
- }
- else if (ISVALIDDEC(p_inputstr[i]))
- {
- val = val * 10 + CONVERTDEC(p_inputstr[i]);
- }
- else
- {
- /* return 0, Invalid input */
- res = 0;
- break;
- }
- i++;
- }
- }
-
- return res;
-}
-
-/**
- * @brief Read data from the circular queue.
- *
- * This function reads the specified length of data from the circular queue and stores it in the given buffer.
- * If the length of data in the queue is greater than or equal to the specified length, it directly reads the specified length of data.
- * If the length of data in the queue is less than the specified length, it reads all the data in the queue.
- *
- * @param buffer The buffer to store the data.
- * @param len The length of data to read.
- *
- * @return The actual length of data read.
- */
-static uint16_t rym_sqqueue_read(void *buffer, uint16_t len)
-{
- uint16_t i = 0;
- uint8_t *buf = buffer;
- if (rym_sqqueue.get_len(&rym_sqqueue) >= len)
- {
- for (i = 0; i < len; i++)
- {
- buf[i] = *((uint8_t *)rym_sqqueue.del(&rym_sqqueue));
- }
- }
- else
- {
- while ((rym_sqqueue.get_len(&rym_sqqueue) != 0) && (i < len))
- {
- buf[i] = *((uint8_t *)rym_sqqueue.del(&rym_sqqueue));
- }
- }
-
- return i;
-}
-
-/**
- * @brief Initializes the parameters for the YMODEM process.
- *
- * This function sets the stage variable to the specified stage and initializes the rym_tm_sec variable with the value of tm_sec.
- * If the stage is RYM_STAGE_ESTABLISHING, it also clears the rym_sqqueue.
- *
- * @param st The stage of the YMODEM process.
- */
-static void rym_process_params_init(enum rym_stage st)
-{
- stage = st;
- rym_tm_sec = tm_sec;
- if (st == RYM_STAGE_ESTABLISHING)
- {
- rym_sqqueue.clear_sqq(&rym_sqqueue);
- }
-}
-
-/**
- * @brief Performs the handshake process for the YMODEM protocol.
- *
- * This function reads packets from the input queue and performs the necessary checks and actions
- * to establish a connection and initiate file transfer using the YMODEM protocol.
- *
- * @param fl The flow structure containing the necessary variables and synchronization mechanisms.
- * @return The result of the handshake process.
- * - 0: Handshake process completed successfully.
- * - Non-zero: Handshake process failed.
- */
-static uint8_t rym_do_handshake_process(struct flow *fl)
-{
- uint8_t index = 0;
- FL_HEAD(fl);
- static uint16_t rym_recv_len = 0;
- static uint16_t recv_crc, cal_crc;
- static uint8_t *file_ptr = NULL;
- static uint8_t file_name[FILE_NAME_LENGTH];
- static uint8_t file_size[FILE_SIZE_LENGTH];
- static uint32_t filesize;
- for (;;)
- {
- FL_LOCK_WAIT_SEM_OR_TIMEOUT(fl, &msg_sem, FL_CLOCK_SEC);
- if (FL_SEM_IS_RELEASE(fl, &msg_sem))
- {
- rym_recv_len = rym_sqqueue_read(&aPacketData[PACKET_START_INDEX], 1);
- if (rym_recv_len == 1)
- {
- if (aPacketData[PACKET_START_INDEX] != RYM_CODE_SOH && aPacketData[PACKET_START_INDEX] != RYM_CODE_STX)
- continue;
-
- /* SOH/STX + seq + payload + crc */
- rym_recv_len = rym_sqqueue_read(&aPacketData[PACKET_NUMBER_INDEX],
- _RYM_PKG_SZ - 1);
- if (rym_recv_len != (_RYM_PKG_SZ - 1))
- continue;
- /* sanity check */
- if ((aPacketData[PACKET_NUMBER_INDEX] != 0) || (aPacketData[PACKET_CNUMBER_INDEX] != 0xFF))
- continue;
- recv_crc = (uint16_t)(*(&aPacketData[PACKET_START_INDEX] + _RYM_PKG_SZ - 2) << 8) |
- *(&aPacketData[PACKET_START_INDEX] + _RYM_PKG_SZ - 1);
- cal_crc = CRC16(aPacketData + PACKET_DATA_INDEX, _RYM_PKG_SZ - 5);
- if (recv_crc != cal_crc)
- continue;
-
- if (rym_on_begin != NULL)
- {
- file_ptr = aPacketData + PACKET_DATA_INDEX;
- while ((*file_ptr != 0) && (index < FILE_NAME_LENGTH))
- {
- file_name[index++] = *file_ptr++;
- }
- file_name[index++] = '\0';
- index = 0;
- file_ptr++;
- while ((*file_ptr != ' ') && (index < FILE_SIZE_LENGTH))
- {
- file_size[index++] = *file_ptr++;
- }
- file_size[index++] = '\0';
- Str2Int(file_size, &filesize);
-
- if (RYM_CODE_NONE != rym_on_begin(file_name, filesize))
- {
- for (uint8_t i = 0; i < RYM_END_SESSION_SEND_CAN_NUM; i++)
- {
- aPacketData[0] = RYM_CODE_CAN;
- rym_transmit(aPacketData, 1);
- }
- }
- else
- {
- aPacketData[0] = RYM_CODE_ACK;
- rym_transmit(aPacketData, 1);
- FL_LOCK_DELAY(fl, FL_CLOCK_100MSEC * 5);
- aPacketData[0] = RYM_CODE_C;
- rym_transmit(aPacketData, 1);
- rym_process_params_init(RYM_STAGE_TRANSMITTING);
- FL_LOCK_DELAY(fl, FL_CLOCK_SEC);
- }
- }
- }
- }
- else
- {
- aPacketData[0] = RYM_CODE_C;
- rym_transmit(aPacketData, 1);
- rym_tm_sec--;
- }
- }
- FL_TAIL(fl);
-}
-
-/**
- * @brief Transfers data using the YMODEM protocol.
- *
- * This function is responsible for transferring data using the YMODEM protocol.
- * It receives the size of the data to be transferred and a pointer to the code
- * that will be returned. It performs various checks on the received data and
- * calculates the CRC to ensure data integrity. If all checks pass, it sets the
- * code to RYM_CODE_ACK and returns 0. Otherwise, it returns an error code.
- *
- * @param data_size The size of the data to be transferred.
- * @param code Pointer to the code that will be returned.
- * @return 0 if successful, otherwise an error code.
- */
-static int8_t rym_tran_data(uint16_t data_size, uint8_t *code)
-{
- DBG_ASSERT(NULL != code __DBG_LINE);
- uint16_t recv_len = 0;
- uint16_t recv_crc, cal_crc;
- const uint16_t tran_size = PACKET_HEADER_SIZE - 1 + data_size + PACKET_TRAILER_SIZE;
-
- /* seq + data + crc */
- recv_len = rym_sqqueue_read(&aPacketData[PACKET_NUMBER_INDEX],
- tran_size);
- if (recv_len != tran_size)
- return -RYM_ERR_DSZ;
- /* sanity check */
- if ((aPacketData[PACKET_NUMBER_INDEX] + aPacketData[PACKET_CNUMBER_INDEX]) != 0xFF)
- return -RYM_ERR_SEQ;
- /* As we are sending C continuously, there is a chance that the
- * sender(remote) receive an C after sending the first handshake package.
- * So the sender will interpret it as NAK and re-send the package. So we
- * just ignore it and proceed. */
- if (stage == RYM_STAGE_ESTABLISHED && aPacketData[PACKET_NUMBER_INDEX] == RYM_CODE_NONE)
- {
- *code = RYM_CODE_NONE;
- return 0;
- }
-
- stage = RYM_STAGE_TRANSMITTING;
-
- recv_crc = (uint16_t)(*(&aPacketData[PACKET_START_INDEX] + tran_size - 1) << 8) |
- *(&aPacketData[PACKET_START_INDEX] + tran_size);
- cal_crc = CRC16(aPacketData + PACKET_DATA_INDEX, data_size);
- if (recv_crc != cal_crc)
- return -RYM_ERR_CRC;
-
- *code = RYM_CODE_ACK;
- return 0;
-}
-
-/**
- * @brief Performs the YMODEM transmission process.
- *
- * This function is responsible for handling the YMODEM transmission process.
- * It receives packets of data and performs the necessary operations based on the received data.
- * It handles timeouts and retransmissions if necessary.
- *
- * @param fl The flow structure pointer.
- * @return The status of the transmission process.
- */
-static uint8_t rym_do_trans_process(struct flow *fl)
-{
- FL_HEAD(fl);
- static uint16_t data_size, rym_recv_len;
- static uint8_t rym_code;
- static uint16_t tran_timeout = 0;
- for (;;)
- {
- FL_LOCK_WAIT_SEM_OR_TIMEOUT(fl, &msg_sem, FL_CLOCK_SEC);
- if (FALSE == FL_SEM_IS_RELEASE(fl, &msg_sem))
- {
- if (tran_timeout++ >= 5)
- {
- tran_timeout = 0;
- rym_process_params_init(RYM_STAGE_ESTABLISHING);
- FL_LOCK_DELAY(fl, FL_CLOCK_SEC);
- }
- }
- else
- {
- tran_timeout = 0;
- rym_recv_len = rym_sqqueue_read(&aPacketData[PACKET_START_INDEX], 1);
- if (rym_recv_len == 1)
- {
- if (aPacketData[PACKET_START_INDEX] == RYM_CODE_SOH)
- data_size = PACKET_SIZE;
- else if (aPacketData[PACKET_START_INDEX] == RYM_CODE_STX)
- data_size = PACKET_1K_SIZE;
- else if (aPacketData[PACKET_START_INDEX] == RYM_CODE_EOT)
- {
- aPacketData[0] = RYM_CODE_NAK;
- rym_transmit(aPacketData, 1);
- rym_process_params_init(RYM_STAGE_FINISHING);
- FL_LOCK_DELAY(fl, FL_CLOCK_SEC);
- continue;
- }
- else
- {
- rym_process_params_init(RYM_STAGE_ESTABLISHING);
- FL_LOCK_DELAY(fl, FL_CLOCK_SEC);
- continue;
- }
-
- if (rym_tran_data(data_size, &rym_code) == 0)
- {
- if (rym_on_data != NULL)
- rym_on_data(aPacketData + PACKET_DATA_INDEX, data_size);
-
- if (rym_code == RYM_CODE_CAN)
- {
- for (uint8_t i = 0; i < RYM_END_SESSION_SEND_CAN_NUM; i++)
- {
- aPacketData[0] = RYM_CODE_CAN;
- rym_transmit(aPacketData, 1);
- }
- }
- else if (rym_code == RYM_CODE_ACK)
- {
- aPacketData[0] = RYM_CODE_ACK;
- rym_transmit(aPacketData, 1);
- }
- }
- }
- }
- }
- FL_TAIL(fl);
-}
-
-/**
- * @brief Performs the finishing process for the YMODEM protocol.
- *
- * This function is responsible for handling the final stage of the YMODEM protocol,
- * where the receiver receives the end of transmission (EOT) signal from the sender.
- * It verifies the received EOT signal, sends an acknowledgement (ACK) signal back to
- * the sender, and waits for the start of header (SOH) signal to receive the final
- * packet containing the payload and checksum. If the received packet is valid, it
- * calculates the checksum and compares it with the received checksum. If they match,
- * it sets the stage to RYM_STAGE_FINISHED and invokes the callback function if
- * available. This function also handles timeout conditions and reinitializes the
- * protocol parameters if necessary.
- *
- * @param fl The flow structure pointer.
- * @return The result of the finishing process.
- */
-static uint8_t rym_do_finish_process(struct flow *fl)
-{
- FL_HEAD(fl);
- static uint16_t rym_recv_len;
- static uint16_t recv_crc, cal_crc;
- static uint16_t tran_timeout = 0;
-
- for (;;)
- {
- FL_LOCK_WAIT_SEM_OR_TIMEOUT(fl, &msg_sem, FL_CLOCK_SEC);
- if (FALSE == FL_SEM_IS_RELEASE(fl, &msg_sem))
- {
- if (tran_timeout++ >= 5)
- {
- tran_timeout = 0;
- rym_process_params_init(RYM_STAGE_ESTABLISHING);
- FL_LOCK_DELAY(fl, FL_CLOCK_SEC);
- }
- }
- else
- {
- tran_timeout = 0;
- /* read the length of the packet */
- rym_recv_len = rym_sqqueue_read(&aPacketData[PACKET_START_INDEX], 1);
- if (rym_recv_len == 1)
- {
- if (aPacketData[PACKET_START_INDEX] != RYM_CODE_EOT)
- continue;
-
- /* send an ACK */
- aPacketData[0] = RYM_CODE_ACK;
- rym_transmit(aPacketData, 1);
- FL_LOCK_DELAY(fl, FL_CLOCK_100MSEC * 5);
- /* send a C */
- aPacketData[0] = RYM_CODE_C;
- rym_transmit(aPacketData, 1);
-
- FL_LOCK_WAIT_SEM_OR_TIMEOUT(fl, &msg_sem, FL_CLOCK_SEC);
- if (FALSE == FL_SEM_IS_RELEASE(fl, &msg_sem))
- continue;
- /* read the length of the packet */
- rym_recv_len = rym_sqqueue_read(&aPacketData[PACKET_START_INDEX], 1);
- if (rym_recv_len == 1)
- {
- if (aPacketData[PACKET_START_INDEX] != RYM_CODE_SOH)
- continue;
-
- /* SOH/STX + seq + payload + crc */
- rym_recv_len = rym_sqqueue_read(&aPacketData[PACKET_NUMBER_INDEX],
- _RYM_SOH_PKG_SZ - 1);
- if (rym_recv_len != (_RYM_SOH_PKG_SZ - 1))
- continue;
- /* sanity check */
- if ((aPacketData[PACKET_NUMBER_INDEX] != 0) || (aPacketData[PACKET_CNUMBER_INDEX] != 0xFF))
- continue;
- recv_crc = (uint16_t)(*(&aPacketData[PACKET_START_INDEX] + _RYM_SOH_PKG_SZ - 2) << 8) |
- *(&aPacketData[PACKET_START_INDEX] + _RYM_SOH_PKG_SZ - 1);
- cal_crc = CRC16(aPacketData + PACKET_DATA_INDEX, _RYM_SOH_PKG_SZ - 5);
- if (recv_crc != cal_crc)
- continue;
-
- /* we got a valid packet. invoke the callback if there is one. */
- stage = RYM_STAGE_FINISHED;
- aPacketData[0] = RYM_CODE_ACK;
- rym_transmit(aPacketData, 1);
- /* we already got one EOT in the caller. invoke the callback if there is
- * one. */
- if (rym_on_end)
- rym_on_end(&aPacketData[PACKET_DATA_INDEX], PACKET_SIZE);
- }
- }
- }
- }
- FL_TAIL(fl);
-}
-
-/**
- * @brief Process the Ymodem protocol stages.
- *
- * This function is responsible for handling the different stages of the Ymodem protocol.
- * It performs the necessary actions based on the current stage.
- *
- * @note The stages include establishing connection, transmitting data, finishing, and others.
- *
- * @param None
- * @return None
- */
-void rym_process(void)
-{
- switch (stage)
- {
- case RYM_STAGE_ESTABLISHING: // 建立连接 (Establishing connection)
- rym_do_handshake_process(&handshake_fw);
- break;
- case RYM_STAGE_TRANSMITTING: // 传输中 (Transmitting)
- rym_do_trans_process(&trans_fw);
- break;
- case RYM_STAGE_FINISHING: // 结束 (Finishing)
- rym_do_finish_process(&finsh_fw);
- break;
- case RYM_STAGE_NONE:
- rym_process_params_init(RYM_STAGE_ESTABLISHING);
- break;
- case RYM_STAGE_FINISHED:
- rym_tm_sec = 0;
- break;
- default:
- // rym_process_params_init(RYM_STAGE_ESTABLISHING);
- break;
- }
-}
-
-/**
- * @brief Checks if the YMODEM receive timeout has occurred.
- * @return TRUE if the timeout has occurred, FALSE otherwise.
- */
-BOOL rym_timeout(void)
-{
- return rym_tm_sec == 0;
-}
-
-/**
- * @brief Initializes the YMODEM protocol for receiving files.
- *
- * This function initializes the necessary data structures and variables
- * for receiving files using the YMODEM protocol.
- *
- * @return TRUE if initialization is successful, FALSE otherwise.
- */
-BOOL rym_init(void)
-{
- sqqueue_ctrl_init(&rym_sqqueue, sizeof(uint8_t), _RYM_PKG_SZ);
- FL_INIT(&handshake_fw);
- FL_INIT(&trans_fw);
- FL_INIT(&finsh_fw);
- return TRUE;
-}
-
-/**
- * @brief Receive data using the Ymodem protocol.
- *
- * This function is used to receive data transmitted using the Ymodem protocol and store it in the specified buffer.
- *
- * @param p Pointer to the data storage buffer.
- */
-uint16_t rym_receive(void *p, uint16_t size)
-{
- rym_sqqueue.string_enter(&rym_sqqueue, p, size);
- FLOW_SEM_RELEASE(&msg_sem);
- return 0;
-}
-
-/**
- * @brief Configures the YMODEM protocol with the specified callbacks and handshake timeout.
- *
- * This function sets the callback functions for the YMODEM protocol, which will be called during different stages of the protocol.
- * The `on_begin` callback is called when the YMODEM transfer begins.
- * The `on_data` callback is called when a data packet is received during the transfer.
- * The `on_end` callback is called when the YMODEM transfer ends.
- * The `on_transmit` callback is called when a data packet needs to be transmitted during the transfer.
- * The `handshake_timeout` parameter specifies the timeout duration for the handshake phase of the YMODEM protocol.
- *
- * @param on_begin The callback function to be called when the YMODEM transfer begins.
- * @param on_data The callback function to be called when a data packet is received during the transfer.
- * @param on_end The callback function to be called when the YMODEM transfer ends.
- * @param on_transmit The callback function to be called when a data packet needs to be transmitted during the transfer.
- * @param handshake_timeout The timeout duration for the handshake phase of the YMODEM protocol.
- *
- * @return TRUE if the configuration was successful, FALSE otherwise.
- */
-BOOL rym_config(rym_callback on_begin, rym_callback on_data,
- rym_callback on_end, rym_callback on_transmit,
- int handshake_timeout)
-{
- rym_on_begin = on_begin;
- rym_on_data = on_data;
- rym_on_end = on_end;
- rym_transmit = on_transmit;
- tm_sec = handshake_timeout;
- return TRUE;
-}
diff --git a/User/lib/control/custom/pid_g.c b/User/lib/control/custom/pid_g.c
index 0759d5f..615ec17 100644
--- a/User/lib/control/custom/pid_g.c
+++ b/User/lib/control/custom/pid_g.c
@@ -129,58 +129,71 @@ static void _set_cfg(struct PID_G *self, float32 max_err, BOOL mode)
self->pri.detach = mode == FALSE ? FALSE : TRUE;
}
+/**
+ * @brief 设置积分权重
+ * @param {PID_G} *self
+ * @param {float32} max_weight
+ * @return {*}
+ * @note
+ */
+static void _set_weight(struct PID_G *self, float32 max_ratio, BOOL mode)
+{
+ self->pri.ui_ratio = max_ratio;
+ self->pri.weight = mode == FALSE ? FALSE : TRUE;
+}
+
/**
* @brief PID算法函数
* @param {PID_G} *self
- * @param {float32} target
- * @param {float32} feedback
+ * @param {float32} target 目标位置
+ * @param {float32} feedback 实际位置
* @return {*}
* @note
*/
static float32 _PID(struct PID_G *self, float32 target, float32 feedback)
{
float32 error = 0.0f;
- float32 insert = 0.0f;
+ float32 insert = 0.0f; ///< 该值为0时积分不介入计算
float32 temp_iterm = 0.0f;
float32 temp_kd = 0.0f;
g_param_t *pri = &self->pri;
- pri->ref = target;
- pri->feed_back = feedback;
- pri->error = pri->ref - pri->feed_back;
+ pri->ref = target; ///< 目标位置
+ pri->feed_back = feedback; ///< 实际位置
+ pri->error = pri->ref - pri->feed_back; /// 误差
error = pri->error;
- if (fabs(pri->error) <= pri->err_dead)
+ if (fabs(pri->error) <= pri->err_dead) ///< 误差小于死区,不计算
{
error = 0;
}
/*根据PID配置的模式,获取积分数据,进行积分累加*/
- if (pri->out >= pri->out_max)
+ if (pri->out >= pri->out_max) ///< 到达输出上限
{
- if (fabs(error) > pri->err_limit && pri->detach)
+ if (fabs(error) > pri->err_limit && pri->detach) ///< 误差大于积分介入区间,积分不介入计算
{
- insert = 0;
+ insert = 0;
}
else
{
insert = 1;
- if (error < 0)
+ if (error < 0)
{
temp_iterm = pri->ki * error;
}
}
}
- else if (pri->out <= pri->out_min)
+ else if (pri->out <= pri->out_min) ///< 到达输出下限
{
- if (fabs(error) > pri->err_limit && pri->detach)
+ if (fabs(error) > pri->err_limit && pri->detach) ///< 误差大于积分介入区间,积分不介入计算
{
insert = 0;
}
else
{
insert = 1;
- if (error > 0)
+ if (error > 0)
{
temp_iterm = pri->ki * error;
}
@@ -200,19 +213,34 @@ static float32 _PID(struct PID_G *self, float32 target, float32 feedback)
}
if (pri->ki_enable == FALSE)
{
+ temp_iterm = 0;
insert = 0;
}
/* integral */
pri->sum_iterm += temp_iterm;
- if (pri->sum_iterm > pri->out_max)
+ if (pri->weight == TRUE)
{
- pri->sum_iterm = pri->out_max;
+ if (pri->sum_iterm > pri->ui_ratio)
+ {
+ pri->sum_iterm = pri->ui_ratio;
+ }
+ else if (pri->sum_iterm < -pri->ui_ratio)
+ {
+ pri->sum_iterm = -pri->ui_ratio;
+ }
}
- else if (pri->sum_iterm < pri->out_min)
+ else
{
- pri->sum_iterm = pri->out_min;
+ if (pri->sum_iterm > pri->out_max)
+ {
+ pri->sum_iterm = pri->out_max;
+ }
+ else if (pri->sum_iterm < pri->out_min)
+ {
+ pri->sum_iterm = pri->out_min;
+ }
}
/* differential */
@@ -226,14 +254,20 @@ static float32 _PID(struct PID_G *self, float32 target, float32 feedback)
}
pri->out = pri->kp * pri->error + pri->sum_iterm * insert + (pri->error - pri->pre_error) * temp_kd;
- pri->pre_error = pri->error;
+ pri->pre_error = pri->error; ///< 记录这次误差,为下次微分计算做准备
pri->pre_feed_back = pri->feed_back;
/*limt pid output*/
- pri->out = RANGE(pri->out, pri->out_min, pri->out_max);
+ pri->out = RANGE(pri->out, pri->out_min, pri->out_max); ///< 限制输出
return pri->out;
}
+/**
+ * @brief PID接口
+ * @param {PID_G} *self
+ * @return {*}
+ * @note
+ */
void pid_g_constructor(struct PID_G *self)
{
self->set_ctrl_prm = _set_ctrl_prm;
@@ -247,4 +281,5 @@ void pid_g_constructor(struct PID_G *self)
self->set_range = _set_range;
self->restctrl = _restctrl;
self->PID = _PID;
+ self->set_weight = _set_weight;
}
diff --git a/User/lib/control/custom/pid_g.h b/User/lib/control/custom/pid_g.h
index c16b96d..143051d 100644
--- a/User/lib/control/custom/pid_g.h
+++ b/User/lib/control/custom/pid_g.h
@@ -20,11 +20,13 @@ typedef struct
float32 minimum; /*输出值的下限*/
float32 out; /*输出值*/
float32 sum_iterm; /*积分累加*/
+ float32 ui_ratio; /*积分权重*/
BOOL ki_enable; /*积分使能*/
BOOL kd_enable; /*微分使能*/
- BOOL detach;
- uint16_t out_max;
- uint16_t out_min;
+ BOOL detach; /*积分分离标志*/
+ BOOL weight; /*积分权重标志*/
+ float32 out_max; /*输出最大值*/
+ float32 out_min; /*输出最小值*/
} g_param_t;
typedef struct PID_G
@@ -39,6 +41,8 @@ typedef struct PID_G
void (*set_range)(struct PID_G *self, float32 out_min, float32 out_max);
/* 设置积分分离 */
void (*set_cfg)(struct PID_G *self, float32 max_err, BOOL mode);
+ /* 设置积分权重 */
+ void (*set_weight)(struct PID_G *self, float32 max_ratio, BOOL mode);
/* 更新kp */
void (*set_kp)(struct PID_G *self, float32 kp);
/* 使能ki */
diff --git a/User/lib/control/custom/pid_hd.c b/User/lib/control/custom/pid_hd.c
index f3d0336..0a98366 100644
--- a/User/lib/control/custom/pid_hd.c
+++ b/User/lib/control/custom/pid_hd.c
@@ -2,59 +2,31 @@
#include
#include "sys.h"
#include "app.h"
-#include "mode_pwmp_hd.h"
-extern execute_rsp_hd_t rsp; // 执行结果
-
-/*PID控制器重启后的初始化*/
-
-static void initialize(struct PID_HD *self)
-{
- self->pri_u.position.pre_feed_back = mode_pwmp_hd->control.ctrl_feedback;
- self->pri_u.position.ki_error = (float32)((rsp.dac - mode_pwmp_hd->pwmp_save->storage.pwmp_min_origin) * (1 / (mode_pwmp_hd->pwmp_save->storage.pwmp_max_origin - mode_pwmp_hd->pwmp_save->storage.pwmp_min_origin)) * 100);
- if (self->pri_u.position.ki_error > 100)
- {
- self->pri_u.position.ki_error = 100;
- }
- else if (self->pri_u.position.ki_error < 0)
- {
- self->pri_u.position.ki_error = 0;
- }
-}
-/*模式设置*/
-static void _set_mode(struct PID_HD *self, pid_mode_e mode)
-{
- self->pri_u.position.pid_mode = mode;
- if (mode != INAUTO)
- {
- initialize(&_pid.pid_u.hd);
- }
-}
#if INCOMPLETE_DIFFEREN_HD == 1 // 积分分离
/*计算微分项,使用追随误差微分项*/
static float32 td_derivative(struct PID_HD *self, float32 current_err, float32 pre_err, float32 dt)
{
pid_hd_position_t *pri = &self->pri_u.position;
- float32 derivative = (current_err - pre_err) / dt; // 计算微分项
+ float32 derivative = (current_err - pre_err) / dt; // 计算积分项
derivative = pri->td_alpha * derivative + (1 - pri->td_alpha) * pri->td_beta * pri->pre_derivative; // 追随误差微分器平滑输出
pri->pre_derivative = derivative; // 更新上一次误差
return derivative;
}
#endif
-/*杭电:设置增量式PID参数*/
+/*杭电:设置位置式PID参数*/
static void _set_ctrl_prm_position(struct PID_HD *self, float32 kp, float32 ki, float32 kd)
{
pid_hd_position_t *pri = &self->pri_u.position;
osel_memset((uint8_t *)pri, 0, sizeof(pid_hd_position_t));
- /*设置模式*/
- self->pri_u.position.pid_mode = INAUTO;
/*观测传进来的Kp、Ki、Kd*/
+
pri->kp = kp;
pri->ki = ki;
pri->kd = kd;
- pri->ki_limit = 20; // 积分分离界限
+ pri->ki_limit = 10; // 积分分离界限
pri->err_dead = 0.5; // 控制死区范围
#if INCOMPLETE_DIFFEREN_HD == 1
/*不完全微分系数*/
@@ -73,12 +45,6 @@ static void _set_out_prm_position(struct PID_HD *self, float32 maximum, float32
/*杭电:位置式PID控制算法*/
static float32 _pid_position(struct PID_HD *self, float32 err)
{
- /*模式设置*/
- self->pri_u.position.pid_mode = (pid_mode_e)mode_pwmp_hd->pid_mode;
- _set_mode(self, self->pri_u.position.pid_mode);
- /*判断是否在自动模式*/
- if (self->pri_u.position.pid_mode != INAUTO)
- return self->pri_u.position.pre_out;
/*计算控制的运行时间*/
// sys_millis_reset();
self->pri_u.position.control_time = sys_millis();
@@ -89,8 +55,9 @@ static float32 _pid_position(struct PID_HD *self, float32 err)
{
err = 0;
}
+
+ float32 x[3];
self->pri_u.position.err = err;
- self->pri_u.position.feed_back = mode_pwmp_hd->control.ctrl_feedback;
/*抗积分饱和*/
#if INTEGRAL_SEPARATION == 1 // 积分分离
@@ -104,7 +71,7 @@ static float32 _pid_position(struct PID_HD *self, float32 err)
{
if (self->pri_u.position.err < 0) // 若偏差为负值,执行负偏差的累加
{
- self->pri_u.position.ki_error += self->pri_u.position.ki * self->pri_u.position.err;
+ self->pri_u.position.ki_error += self->pri_u.position.err;
}
}
}
@@ -118,7 +85,7 @@ static float32 _pid_position(struct PID_HD *self, float32 err)
{
if (self->pri_u.position.err > 0) // 若偏差为正值,执行正偏差的累加
{
- self->pri_u.position.ki_error += self->pri_u.position.ki * self->pri_u.position.err;
+ self->pri_u.position.ki_error += self->pri_u.position.err;
}
}
}
@@ -130,7 +97,7 @@ static float32 _pid_position(struct PID_HD *self, float32 err)
}
else
{
- self->pri_u.position.ki_error += self->pri_u.position.ki * self->pri_u.position.err;
+ self->pri_u.position.ki_error += self->pri_u.position.err;
}
}
#else /*无积分分离操作*/
@@ -144,42 +111,32 @@ static float32 _pid_position(struct PID_HD *self, float32 err)
}
#endif
- if (self->pri_u.position.ki_error > 100)
- {
- self->pri_u.position.ki_error = 100;
- }
- else if (self->pri_u.position.ki_error < 0)
- {
- self->pri_u.position.ki_error = 0;
- }
-
/*输出*/
if (fabs(err) < self->pri_u.position.err_dead)
{
/*输出上一次的值*/
// self->pri_u.position.out = self->pri_u.position.pre_out;
- self->pri_u.position.x[0] = self->pri_u.position.err;
- self->pri_u.position.x[1] = self->pri_u.position.ki_error;
- self->pri_u.position.out = self->pri_u.position.kp * self->pri_u.position.x[0] + self->pri_u.position.x[1] + self->pri_u.position.kd * self->pri_u.position.x[2];
+ x[0] = self->pri_u.position.err;
+ x[1] = self->pri_u.position.ki_error;
+ self->pri_u.position.out = self->pri_u.position.kp * x[0] + self->pri_u.position.ki * x[1] + self->pri_u.position.kd * x[2];
}
else
{
- self->pri_u.position.x[0] = self->pri_u.position.err;
- self->pri_u.position.x[1] = self->pri_u.position.ki_error;
+ x[0] = self->pri_u.position.err;
+ x[1] = self->pri_u.position.ki_error;
#if INCOMPLETE_DIFFEREN_HD == 1
/*不完全微分项,为了解决普通PID为微分环节容易振荡的问题*/
self->pri_u.position.tmp_time = sys_millis();
self->pri_u.position.control_time -= self->pri_u.position.tmp_time;
self->pri_u.position.control_time /= 1000.0; // 将单位转换为秒
- // x[2] = td_derivative(&_pid.pid_u.hd, err, self->pri_u.position.pre_error, self->pri_u.position.control_time);
- self->pri_u.position.x[2] = -(td_derivative(&_pid.pid_u.hd, self->pri_u.position.feed_back, self->pri_u.position.pre_feed_back, self->pri_u.position.control_time));
+ x[2] = td_derivative(&_pid.pid_u.hd, err, self->pri_u.position.pre_error, self->pri_u.position.control_time);
#else
// 普通的微分环节
- self->pri_u.position.x[2] = self->pri_u.position.err - self->pri_u.position.pre_error;
+ x[2] = self->pri_u.position.err - self->pri_u.position.pre_error;
#endif
- self->pri_u.position.out = self->pri_u.position.kp * self->pri_u.position.x[0] + self->pri_u.position.x[1] + self->pri_u.position.kd * self->pri_u.position.x[2];
+ self->pri_u.position.out = self->pri_u.position.kp * x[0] + self->pri_u.position.ki * x[1] + self->pri_u.position.kd * x[2];
}
/*输出限幅*/
@@ -196,8 +153,6 @@ static float32 _pid_position(struct PID_HD *self, float32 err)
self->pri_u.position.pre_error = self->pri_u.position.err; /*上一次误差值*/
// 更新输出历史
self->pri_u.position.pre_out = self->pri_u.position.out; /*上一次输出值*/
- // 更新反馈历史
- self->pri_u.position.pre_feed_back = self->pri_u.position.feed_back; /*上一次反馈值*/
return self->pri_u.position.out;
}
@@ -208,5 +163,4 @@ void pid_hd_constructor(struct PID_HD *self)
self->set_ctrl_prm_position = _set_ctrl_prm_position;
self->set_out_prm_position = _set_out_prm_position;
self->pid_position = _pid_position;
- self->set_mode = _set_mode;
}
diff --git a/User/lib/control/custom/pid_hd.h b/User/lib/control/custom/pid_hd.h
index fa52895..2fa96f0 100644
--- a/User/lib/control/custom/pid_hd.h
+++ b/User/lib/control/custom/pid_hd.h
@@ -5,16 +5,8 @@
#define INTEGRAL_SEPARATION 1 // 积分分离
#define INCOMPLETE_DIFFEREN_HD 1 // 不完全微分
-typedef enum
-{
- INAUTO,
- OFFAUTO,
-} pid_mode_e;
-
typedef struct
{
- pid_mode_e pid_mode;
- float32 x[3];
float32 ref;
float32 feed_back;
float32 pre_feed_back;
@@ -53,8 +45,6 @@ typedef struct PID_HD
void (*set_ctrl_prm_position)(struct PID_HD *self, float32 kp, float32 ki, float32 kd);
/* 设置输出范围 */
void (*set_out_prm_position)(struct PID_HD *self, float32 maximum, float32 minimum);
- /*设置模式*/
- void (*set_mode)(struct PID_HD *self, pid_mode_e mode);
/* 控制接口 */
float32 (*pid_position)(struct PID_HD *self, float32 err);
diff --git a/User/lib/control/custom/pid_x.c b/User/lib/control/custom/pid_x.c
index 177d563..747049c 100644
--- a/User/lib/control/custom/pid_x.c
+++ b/User/lib/control/custom/pid_x.c
@@ -347,12 +347,12 @@ static void calculation_parameters(struct PID_X *self)
{
CLASSIC_AUTOTUNE *tune = &self->tune;
CLASSICPID *vPID = &self->pri;
- float32 kc = 0.0;
- float32 tc = 0.0;
- float32 zn[3][3] = {{0.5, 100000.0, 0.0}, {0.45, 0.8, 0.0}, {0.6, 0.5, 0.125}};
+ float32 kc = 0.0f;
+ float32 tc = 0.0f;
+ float32 zn[3][3] = {{0.5f, 100000.0f, 0.0f}, {0.45f, 0.8f, 0.0f}, {0.6f, 0.5f, 0.125f}};
tc = (tune->endTime - tune->startTime) * tune->tunePeriod / 1000.0;
- kc = (8.0 * tune->outputStep) / (PI * (tune->maxPV - tune->minPV));
+ kc = (8.0f * tune->outputStep) / (PI * (tune->maxPV - tune->minPV));
vPID->pKp = zn[tune->controllerType][0] * kc; // 比例系数
vPID->pKi = vPID->pKp * tune->tunePeriod / (zn[tune->controllerType][1] * tc); // 积分系数
diff --git a/User/lib/control/custom/pid_zh.c b/User/lib/control/custom/pid_zh.c
index 5a4ac54..2156d3a 100644
--- a/User/lib/control/custom/pid_zh.c
+++ b/User/lib/control/custom/pid_zh.c
@@ -1,10 +1,18 @@
#include "pid_zh.h"
#include "sys.h"
#include
+
// 定义输出量比例因子
-#define KUP 10.0f
-#define KUI 0.03f
-#define KUD 3.0f
+#ifdef GPS3000
+#define KUP 0.0f // #define KUP 3.0f
+#define KUI 0.00f
+#define KUD 0.0f // #define KUP 3.0f
+#else
+#define KUP 3.0f
+#define KUI 0.0f
+#define KUD 0.0f
+#endif
+
// 模糊集合
#define NL -3
#define NM -2
@@ -32,6 +40,16 @@ static const float32 fuzzyRuleKp[7][7] = {
PS, PS, PS, PS, PS, PM, PM,
PM, PM, PM, PM, PL, PL, PL,
PM, PL, PL, PL, PL, PL, PL};
+
+static const float32 fuzzyRuleKi[7][7] = {
+ PL, PL, PL, PL, PM, PL, PL,
+ PL, PL, PM, PM, PM, PL, PL,
+ PM, PM, PS, PS, PS, PM, PM,
+ PM, PS, ZE, ZE, ZE, PS, PM,
+ PM, PS, PS, PS, PS, PM, PM,
+ PM, PM, PS, PM, PM, PL, PL,
+ PM, PL, PM, PL, PL, PL, PL};
+
/*
static const float32 fuzzyRuleKi[7][7] = {
NL, NL, NL, NL, NM, NL, NL,
@@ -42,24 +60,7 @@ static const float32 fuzzyRuleKi[7][7] = {
NM, NM, NS, NM, NM, NL, NL,
NM, NL, NM, NL, NL, NL, NL};
*/
-static const float32 fuzzyRuleKi[7][7] = {
- PL, PL, PL, PL, PM, PL, PL,
- PL, PL, PM, PM, PM, PL, PL,
- PM, PM, PS, PS, PS, PM, PM,
- PM, PS, ZE, ZE, ZE, PS, PM,
- PM, PS, PS, PS, PS, PM, PM,
- PM, PM, PS, PM, PM, PL, PL,
- PM, PL, PM, PL, PL, PL, PL};
-/*
-static const float32 fuzzyRuleKd[7][7] = {
- PS, PS, ZE, ZE, ZE, PL, PL,
- NS, NS, NS, NS, ZE, NS, PM,
- NL, NL, NM, NS, ZE, PS, PM,
- NL, NM, NM, NS, ZE, PS, PM,
- NL, NM, NS, NS, ZE, PS, PS,
- NM, NS, NS, NS, ZE, PS, PS,
- PS, ZE, ZE, ZE, ZE, PL, PL};
-*/
+
static const float32 fuzzyRuleKd[7][7] = {
PS, PS, ZE, ZE, ZE, PL, PL,
PS, PS, PS, PS, ZE, PS, PM,
@@ -69,6 +70,36 @@ static const float32 fuzzyRuleKd[7][7] = {
PM, PS, PS, PS, ZE, PS, PS,
PS, ZE, ZE, ZE, ZE, PL, PL};
+/*
+static const float32 fuzzyRuleKp[7][7] = {
+ PL, PL, PM, PM, PS, ZE, ZE,
+ PL, PL, PM, PS, PS, ZE, NS,
+ PM, PM, PM, PS, ZE, NS, NS,
+ PM, PM, PS, ZE, NS, NM, NM,
+ PS, PS, ZE, NS, NS, NM, NM,
+ PS, ZE, NS, NM, NM, NM, NL,
+ ZE, ZE, NM, NM, NM, NL, NL};
+
+static const float32 fuzzyRuleKi[7][7] = {
+ NL, NL, NM, NM, NS, ZE, ZE,
+ NL, NL, NM, NS, NS, ZE, ZE,
+ NL, NM, NS, NS, ZE, PS, PS,
+ NM, NM, NS, ZE, PS, PM, PM,
+ NM, NS, ZE, PS, PS, NM, PL,
+ ZE, ZE, PS, PS, PM, PL, PL,
+ ZE, ZE, PS, PM, PM, PL, PL};
+
+static const float32 fuzzyRuleKd[7][7] = {
+ PS, NS, NL, NL, NL, NM, PS,
+ PS, NS, NL, NM, NM, NS, ZE,
+ ZE, NS, NM, NM, NS, NS, ZE,
+ ZE, NS, NS, NS, NS, NS, ZE,
+
+ ZE, ZE, ZE, ZE, ZE, ZE, ZE,
+ PL, NS, PS, PS, PS, PS, PL,
+ PL, PM, PM, PM, PS, PS, PL};
+*/
+
static void fuzzy(float32 e, float32 ec, FUZZY_PID_ZH_t *fuzzy_pid)
{
@@ -84,13 +115,13 @@ static void fuzzy(float32 e, float32 ec, FUZZY_PID_ZH_t *fuzzy_pid)
ec = ec * KEC;
etemp = e > 3.0f ? 0.0f : (e < -3.0f ? 0.0f : (e >= 0.0f ? (e >= 2.0f ? 2.5f : (e >= 1.0f ? 1.5f : 0.5f)) : (e >= -1.0f ? -0.5f : (e >= -2.0f ? -1.5f : (e >= -3.0f ? -2.5f : 0.0f)))));
- eLeftIndex = (int)((etemp - 0.5f) + 3); //[-3,3] -> [0,6]
+ eLeftIndex = (int)((etemp - 0.5f) + 3); //[-3,2] -> [0,5]
eRightIndex = (int)((etemp + 0.5f) + 3);
eLefttemp = etemp == 0.0f ? 0.0f : ((etemp + 0.5f) - e);
eRighttemp = etemp == 0.0f ? 0.0f : (e - (etemp - 0.5f));
ectemp = ec > 3.0f ? 0.0f : (ec < -3.0f ? 0.0f : (ec >= 0.0f ? (ec >= 2.0f ? 2.5f : (ec >= 1.0f ? 1.5f : 0.5f)) : (ec >= -1.0f ? -0.5f : (ec >= -2.0f ? -1.5f : (ec >= -3.0f ? -2.5f : 0.0f)))));
- ecLeftIndex = (int)((ectemp - 0.5f) + 3); //[-3,3] -> [0,6]
+ ecLeftIndex = (int)((ectemp - 0.5f) + 3); //[-3,2] -> [0,5]
ecRightIndex = (int)((ectemp + 0.5f) + 3);
ecLefttemp = ectemp == 0.0f ? 0.0f : ((ectemp + 0.5f) - ec);
ecRighttemp = ectemp == 0.0f ? 0.0f : (ec - (ectemp - 0.5f));
@@ -381,11 +412,13 @@ static float32 _PID(struct PID_FUZZY_ZH *self, float32 target, float32 feedback)
}
pri->sum_iterm += temp_iterm;
/* limt integral */
+ pri->sum_iterm = RANGE(pri->sum_iterm, pri->out_min, pri->out_max);
+ /*
if (pri->sum_ref)
pri->sum_iterm = RANGE(pri->sum_iterm, pri->sum_ref - 1.0f, pri->sum_ref + 1.0f);
else
pri->sum_iterm = RANGE(pri->sum_iterm, pri->out_min, pri->out_max);
-
+ */
#if INCOMPLETE_DIFFEREN == 1
/*不完全微分*/
thisdev = (pri->kd + self->fuzzy.kd) * (1.0 - pri->alpha) * (error - pri->pre_error) + pri->alpha * pri->lastdev;
@@ -406,6 +439,8 @@ static float32 _PID(struct PID_FUZZY_ZH *self, float32 target, float32 feedback)
}
pri->out = (pri->kp + self->fuzzy.kp) * error + pri->sum_iterm * insert + (error - pri->pre_error) * (kd);
+ // pri->out += pri->sum_ref;
+
#endif
pri->pre_error = error;
diff --git a/User/lib/control/custom/pid_zh.h b/User/lib/control/custom/pid_zh.h
index 7a50129..06f551a 100644
--- a/User/lib/control/custom/pid_zh.h
+++ b/User/lib/control/custom/pid_zh.h
@@ -3,6 +3,8 @@
#include "lib.h"
#include "pid_auto_tune.h"
+#define GPS2000
+
typedef struct
{
float32 ref;
@@ -18,8 +20,8 @@ typedef struct
BOOL detach;
float32 err_dead;
#if INCOMPLETE_DIFFEREN == 1
- dc_t alpha;
- dc_t lastdev;
+ float32 alpha;
+ float32 lastdev;
#endif
float32 out;
float32 out_max;
diff --git a/User/lib/control/custom/pid_zh1.c b/User/lib/control/custom/pid_zh1.c
new file mode 100644
index 0000000..977f169
--- /dev/null
+++ b/User/lib/control/custom/pid_zh1.c
@@ -0,0 +1,619 @@
+
+#include
+#include "pid_zh1.h"
+
+// 定义输出量比例因子
+#define KUP 1.0f
+#define KUI 1.0f
+#define KUD 1.0f
+
+// 模糊集合
+#define NL -3
+#define NM -2
+#define NS -1
+#define ZE 0
+#define PS 1
+#define PM 2
+#define PL 3
+
+// 定义偏差E的范围,因为设置了非线性区间,误差在10时才开始进行PID调节,这里E的范围为10
+#define MAXE (10)
+#define MINE (-MAXE)
+// 定义EC的范围,因为变化非常缓慢!,每次的EC都非常小,这里可以根据实际需求来调整,
+#define MAXEC (10)
+#define MINEC (-MAXEC)
+// 定义e,ec的量化因子
+#define KE 3 / MAXE
+#define KEC 3 / MAXEC
+/*
+static const float fuzzyRuleKp[7][7] = {
+ PL, PL, PM, PL, PS, PM, PL,
+ PL, PM, PM, PM, PS, PM, PL,
+ PM, PS, PS, PS, PS, PS, PM,
+ PM, PS, ZE, ZE, ZE, PS, PM,
+ PS, PS, PS, PS, PS, PM, PM,
+ PM, PM, PM, PM, PL, PL, PL,
+ PM, PL, PL, PL, PL, PL, PL};
+
+static const float fuzzyRuleKi[7][7] = {
+ PL, PL, PL, PL, PM, PL, PL,
+ PL, PL, PM, PM, PM, PL, PL,
+ PM, PM, PS, PS, PS, PM, PM,
+ PM, PS, ZE, ZE, ZE, PS, PM,
+ PM, PS, PS, PS, PS, PM, PM,
+ PM, PM, PS, PM, PM, PL, PL,
+ PM, PL, PM, PL, PL, PL, PL};
+
+static const float fuzzyRuleKd[7][7] = {
+ PS, PS, ZE, ZE, ZE, PL, PL,
+ PS, PS, PS, PS, ZE, PS, PM,
+ PL, PL, PM, PS, ZE, PS, PM,
+ PL, PM, PM, PS, ZE, PS, PM,
+ PL, PM, PS, PS, ZE, PS, PS,
+ PM, PS, PS, PS, ZE, PS, PS,
+ PS, ZE, ZE, ZE, ZE, PL, PL};
+*/
+static const float fuzzyRuleKp[7][7] = {
+ PL, PL, PM, PL, PS, PM, PL,
+ PL, PM, PM, PM, PS, PM, PL,
+ PM, PS, PS, PS, PS, PS, PM,
+ PM, PS, ZE, ZE, ZE, PS, PM,
+ PS, PS, PS, PS, PS, PM, PM,
+ PM, PM, PM, PM, PL, PL, PL,
+ PM, PL, PL, PL, PL, PL, PL};
+
+static const float fuzzyRuleKi[7][7] = {
+ PL, PL, PL, PL, PM, PL, PL,
+ PL, PL, PM, PM, PM, PL, PL,
+ PM, PM, PS, PS, PS, PM, PM,
+ PM, PS, ZE, ZE, ZE, PS, PM,
+ PM, PS, PS, PS, PS, PM, PM,
+ PM, PM, PS, PM, PM, PL, PL,
+ PM, PL, PM, PL, PL, PL, PL};
+
+static const float fuzzyRuleKd[7][7] = {
+ PS, PS, ZE, ZE, ZE, PL, PL,
+ PS, PS, PS, PS, ZE, PS, PM,
+ PL, PL, PM, PS, ZE, PS, PM,
+ PL, PM, PM, PS, ZE, PS, PM,
+ PL, PM, PS, PS, ZE, PS, PS,
+ PM, PS, PS, PS, ZE, PS, PS,
+ PS, ZE, ZE, ZE, ZE, PL, PL};
+
+static void fuzzy(float e, float ec, fuzzy_pid_t *fuzzy_pid)
+{
+
+ float etemp, ectemp;
+ float eLefttemp, ecLefttemp; // 左隶属度
+ float eRighttemp, ecRighttemp; // 右隶属度
+
+ int eLeftIndex, ecLeftIndex; // 模糊位置标号
+ int eRightIndex, ecRightIndex;
+ e = RANGE(e, MINE, MAXE);
+ ec = RANGE(ec, MINEC, MAXEC);
+ e = e * KE;
+ ec = ec * KEC;
+
+ etemp = e > 3.0f ? 0.0f : (e < -3.0f ? 0.0f : (e >= 0.0f ? (e >= 2.0f ? 2.5f : (e >= 1.0f ? 1.5f : 0.5f)) : (e >= -1.0f ? -0.5f : (e >= -2.0f ? -1.5f : (e >= -3.0f ? -2.5f : 0.0f)))));
+ eLeftIndex = (int)((etemp - 0.5f) + 3);
+ eRightIndex = (int)((etemp + 0.5f) + 3);
+ eLefttemp = etemp == 0.0f ? 0.0f : ((etemp + 0.5f) - e);
+ eRighttemp = etemp == 0.0f ? 0.0f : (e - (etemp - 0.5f));
+
+ ectemp = ec > 3.0f ? 0.0f : (ec < -3.0f ? 0.0f : (ec >= 0.0f ? (ec >= 2.0f ? 2.5f : (ec >= 1.0f ? 1.5f : 0.5f)) : (ec >= -1.0f ? -0.5f : (ec >= -2.0f ? -1.5f : (ec >= -3.0f ? -2.5f : 0.0f)))));
+ ecLeftIndex = (int)((ectemp - 0.5f) + 3);
+ ecRightIndex = (int)((ectemp + 0.5f) + 3);
+ ecLefttemp = ectemp == 0.0f ? 0.0f : ((ectemp + 0.5f) - ec);
+ ecRighttemp = ectemp == 0.0f ? 0.0f : (ec - (ectemp - 0.5f));
+
+ /*************************************反模糊*************************************/
+
+ fuzzy_pid->kp = (eLefttemp * ecLefttemp * fuzzyRuleKp[eLeftIndex][ecLeftIndex] + eLefttemp * ecRighttemp * fuzzyRuleKp[eLeftIndex][ecRightIndex] + eRighttemp * ecLefttemp * fuzzyRuleKp[eRightIndex][ecLeftIndex] + eRighttemp * ecRighttemp * fuzzyRuleKp[eRightIndex][ecRightIndex]);
+
+ fuzzy_pid->ki = (eLefttemp * ecLefttemp * fuzzyRuleKi[eLeftIndex][ecLeftIndex] + eLefttemp * ecRighttemp * fuzzyRuleKi[eLeftIndex][ecRightIndex] + eRighttemp * ecLefttemp * fuzzyRuleKi[eRightIndex][ecLeftIndex] + eRighttemp * ecRighttemp * fuzzyRuleKi[eRightIndex][ecRightIndex]);
+
+ fuzzy_pid->kd = (eLefttemp * ecLefttemp * fuzzyRuleKd[eLeftIndex][ecLeftIndex] + eLefttemp * ecRighttemp * fuzzyRuleKd[eLeftIndex][ecRightIndex] + eRighttemp * ecLefttemp * fuzzyRuleKd[eRightIndex][ecLeftIndex] + eRighttemp * ecRighttemp * fuzzyRuleKd[eRightIndex][ecRightIndex]);
+ // 对解算出的KP,KI,KD进行量化映射
+ fuzzy_pid->kp = fuzzy_pid->kp * fuzzy_pid->kup;
+ fuzzy_pid->ki = fuzzy_pid->ki * fuzzy_pid->kui;
+ fuzzy_pid->kd = fuzzy_pid->kd * fuzzy_pid->kud;
+}
+
+static void smooth_init(smart_pid_t *pid, BOOL sm_open, float maxTarget)
+{
+ if (!pid)
+ return;
+
+ pid->sm_open = sm_open;
+ pid->maxTarget = maxTarget;
+}
+
+static void smooth_target(smart_pid_t *pid, float *target)
+{
+
+ if ((!pid) || (!target))
+ return;
+
+ if (!pid->maxTarget)
+ return;
+
+ float sm_step = (pid->maxTarget) * 0.1f;
+ float k = 0.0f;
+
+ if (fabs(pid->target - *target) <= sm_step)
+ {
+ pid->target = *target;
+ }
+ else
+ {
+ if (pid->target - *target > 0)
+ {
+ k = -1.0f;
+ }
+ else if (pid->target - *target < 0)
+ {
+ k = 1.0f;
+ }
+ else
+ {
+ k = 0.0f;
+ }
+ pid->target += k * sm_step;
+ }
+}
+
+static void smart_pid_init(smart_pid_t *pid, float *duty, float *kp, float *ki, float *kd, float *errorDead, float *iDetachCondation, float *maxOut)
+{
+ if ((!pid) || (!duty) || (!kp) || (!ki) || (!kd) || (!iDetachCondation) || (!maxOut))
+ return;
+
+ pid->duty = *duty;
+ pid->kp = *kp;
+ pid->ki = *ki;
+ pid->kd = *kd;
+ pid->errorDead = *errorDead;
+ pid->iDetachCondation = *iDetachCondation;
+ pid->maxOutput = *maxOut;
+}
+
+void cascade_pid_init(cascade_pid_t *pid, smart_pid_t *pid_outer, smart_pid_t *pid_inner)
+{
+
+ smooth_init(&pid->outer, pid_outer->sm_open, pid_outer->maxTarget);
+ smooth_init(&pid->inner, pid_inner->sm_open, pid_inner->maxTarget);
+
+ smart_pid_init(&pid->outer, &pid_outer->duty, &pid_outer->kp, &pid_outer->ki, &pid_outer->kd, &pid_outer->errorDead, &pid_outer->iDetachCondation, &pid_outer->maxOutput);
+ smart_pid_init(&pid->inner, &pid_inner->duty, &pid_inner->kp, &pid_inner->ki, &pid_inner->kd, &pid_inner->errorDead, &pid_inner->iDetachCondation, &pid_inner->maxOutput);
+}
+
+void smart_pid_calc(smart_pid_t *pid, float *target, float *feedback)
+{
+ // 将旧error存起来
+ pid->lastError = pid->error;
+ // 平滑处理目标值
+ if (pid->sm_open == TRUE)
+ smooth_target(pid, target);
+ else
+ pid->target = *target;
+ // 计算新error
+ pid->error = pid->target - *feedback;
+ if (fabs(pid->error) <= pid->errorDead)
+ pid->error = 0.0f;
+ // 计算误差变化
+ pid->dError = pid->error - pid->lastError;
+ // 选用模糊规则
+ if (pid->fuzzy_open == TRUE)
+ {
+ fuzzy(pid->error, pid->dError, &pid->fuzzy_pid);
+ }
+ // 计算微分
+ float dout = pid->dError * (pid->kd + pid->fuzzy_pid.kd);
+ // 计算比例
+ float pout = pid->error * (pid->kp + pid->fuzzy_pid.kp);
+ // 积分分离
+ if (fabs(pid->error) <= pid->iDetachCondation)
+ {
+ pid->integral += pid->error * (pid->ki + pid->fuzzy_pid.ki);
+ pid->iDetach = FALSE;
+ }
+ else
+ {
+ pid->iDetach = TRUE;
+ pid->integral = 0;
+ }
+ // 积分限幅
+ if (pid->integral > pid->maxOutput)
+ pid->integral = pid->maxOutput;
+ else if (pid->integral < -pid->maxOutput)
+ pid->integral = -pid->maxOutput;
+ // 计算输出
+ pid->output = pout + dout + pid->integral * (!pid->iDetach);
+ // 输出限幅
+ if (pid->output > pid->maxOutput)
+ pid->output = pid->maxOutput;
+ else if (pid->output < -pid->maxOutput)
+ pid->output = -pid->maxOutput;
+}
+
+void cascade_pid_calc(struct CascadePID *pid, float *outerRef, float *outerFdb, float *innerFdb)
+{
+ // 外环位置控制
+ smart_pid_calc(&pid->cascade_pid.outer, outerRef, outerFdb);
+ // 内环速度控制
+ smart_pid_calc(&pid->cascade_pid.inner, &pid->cascade_pid.outer.output, innerFdb);
+ // 内环输出就是串级PID的输出
+ // pid->cascade_pid.output = pid->cascade_pid.inner.output;
+ pid->cascade_pid.output = pid->cascade_pid.outer.output;
+}
+
+void pid_zh_constructor1(struct CascadePID *pid)
+{
+ pid->smart_pid_init = smart_pid_init;
+ pid->smart_pid_calc = smart_pid_calc;
+ pid->cascade_pid_init = cascade_pid_init;
+ pid->cascade_pid_calc = cascade_pid_calc;
+}
+
+/*
+典型输入信号
+L[1] -> 1/s
+L[t] -> 1/s^2
+L[1/2t^2] -> 1/s^3
+系统传递函数
+G(s) = k/(TS+1)
+G(s) = k/S^i(TS+1)
+i = 0 0型系统 i = 1 I 型系统 I = 2 II 型系统
+系统开环传递函数: G(s)
+系统闭环传递函数: G闭(s) = G(s) / 1 + G(s)
+系统静差: R(s) = 1/1+G(s)
+终值定理:limf(t) = lim s*G(s)
+ t->无穷 s->0
+o型系统,单位输入:r/s
+ e = lim f(t) = lim s*G(s) = G(s) = k/1+G(s) = k/ 1 + (Ts+1+k)..
+ t->无穷 s->0 s->0 s->0 = s->0
+*系统误差有给定和扰动引起的
+*线性系统符合叠加原理
+*动态性能指标
+超调 、过度过程时间、上升时间 tr 延迟时间 td 峰值指标tp
+误差积分指标大 好小 好?
+典型二阶系统
+G(s) = 1/ s^2 *(2ξwn)s + wn^2
+ξ:阻尼系统
+wn = 1/T:震荡频率
+如果有一个极点和零点很接近,可以忽略该极点。
+主导极点用二阶系统定义的
+开环传递函数 K T
+复变函数
+频率特性
+阻容RC电路 一阶低通滤波器 一阶惰性系统
+Gs = 1/Ts+1
+正弦稳态
+
+控制系统设计依据:
+考虑到被控对象包含 弹簧储能、填料阻尼、EPM气压控制等主导环节,忽略其它非主导惯性、阻尼环节,将被控系统模型归纳为典型二阶阻尼震荡系统:
+被控对象开环传递函数:G(s) = wn^2/ s*( s + 2ξwn)
+未加控制器被控对象闭环传递函数:G(s) = wn^2/ (s^2 + (2ξwn)s + wn^2)
+ ξ :为系统阻尼比。跟阀座填料材、压力正相关(忽略其他非主导阻尼环节)
+ Wn :无阻尼自然震荡角频率。跟弹簧的固有振荡频率正相关(忽略其他非主导惯性环节)
+
+阀杆填料阻尼比: 0 < ξ < 1
+
+系统特征方程s^2 + (2ξwn)s + wn^2 = 0 时,有两个共轭复根,要想系统稳定,根的实部要远离虚轴,且在允许情况下,越远越稳定。
+标准二阶系统是零型系统,存在静差。而且,考虑气体压缩比大,导致系统的惯性环节增大。
+因此需要控制器将系统变为I型系统来消除静差(增加积分环节),而且需要在控制器传递函数的零点增加最小项来克服系统的大惯性(增加微分环节)。因此,设计控制器类型为PID控制器。
+
+※ 难点在于系统的无阻尼自然震荡角频率和阀座阻尼系数无法准确获得,整定算法计算的特性参数不一定合理。
+※ 另一个难点在于EPM本身的控制特性线性度差,会导致控制器的矫正环节达不到理想效果或在部分区间达不到理想效果,因此,
+ 系统会不稳定或在部分区间不稳定。
+※ EMP本身的控制线性度差,通过控制器弥补EPM性能的不足。
+(因为阀杆速度变化快慢,直接由EPM IP开度大小决定,因此考虑增加阀杆速度环控制来弥补EPM本身的不足)
+
+算法核心原理说明 :
+核心算法: PID
+ u(t) = k*(e(t) +∫e(t)dt + de(t)dt)
+ u(n) = k*(e(n) + ∑e(n)/Ti + Td*(e(n) - e(n-1)))
+
+位置控制:PID + PD控制
+ 误差在[-5%,5%] 内 PID 控制,控制静差 < 0.3%
+ 误差在[-100%,5%] 或 [5%,100%] 时,PD控制,防止积分引起的系统不稳定
+
+ 积分分离:当误差<= 5% 时,加入积分
+ 当误差> 5%时,积分分离、积分项清零
+ 积分限幅:
+ 当积分项 >= 100% 积分项 = 100%
+ 当积分项 <= -100% 积分项 = -100%
+
+整定算法: 继电反馈整定
+ 设定目标位置:额定行程 60%
+ 控制初始位置: < 60%
+ 施加最大控制量 ->检测实时位置->过零,计t0、上冲峰值 -> 施加最小控制量 -> 检测实时位置 -> 过零,计t1、下冲峰值— ↓
+ ↑ <—————————————————————————————————————————————————————————————————————————————————————————————————|
+
+ 循环三次,记录系统稳态下波峰、波谷,和震荡周期Tu
+ 计算: Ku = (控制量最大值 - 控制量最小值)/ (位置波峰 - 位置波谷)
+ 查表:Kp = 0.8 * Ku
+ Ti = 0.6 * Tu
+ Td = 0.125 * Tu
+ Ki = Kp / Ti = Kp / (0.6 * Tu)
+ Kd = Kp * Td = Kp * 0.125 * Td
+
+速度控制算法:
+ s1:初始位置AD值
+ s2:单位时间位置移动后AD值
+ v1:当前速度
+ v2: 前速度
+ v: 实时速度
+a:实时加速度
+t: 速度计算周期
+v = (s2 - s1) / t
+a = (v2 - v1) / t
+
+ 整定过程,分别整定上升过程平均速度和下降过程平均速度。
+ 分别以上升和下降速度为PID 内环参考速度,计算速度控制量。
+ 速度偏差 = 当前速度 - 参考速度
+ 加速度 = 速度偏差变化(即位置的二阶导数)
+速度控制量 = Kp*速度偏差 + Ki * ∑速度偏差 + Kd * 加速度
+
+串级控制
+ 外环位置检测,进行速度控制
+ 内环速度检测,进行位置控制
+ 位置偏差 = 位置给定 - 位置反馈
+ 位置偏差变化 = 位置偏差 - 上次位置偏差
+ 速度控制量 = Kp1*位置偏差 + Ki1 * ∑位置偏差 + Kd1 * 位置偏差变化
+ 速度偏差 = 速度控制量 - 速度反馈
+ 速度偏差变化 = 速度偏差 - 上次速度偏差
+ 位置控制量 = Kp2*速度偏差 + Ki2 * ∑速度偏差 + Kd2 * 速度偏差变化
+串级速度整定:???
+
+automatic control theory
+control system
+linear and nonlinear system
+线性连续系统
+离散系统
+modelling
+analysis
+矫正
+分析 时域分析方法 微分方程 传递函数 一阶系统 二阶系统
+频域分析方法 闭环特性 低频特性 高频特性
+根轨迹
+建模 分析 矫正
+离散系统
+非线性控制理论
+L变换 Z变换
+采样控制系统 数字控制系统
+条件稳定系统
+problems
+time consuming
+行列式计算
+相对稳定性
+劳斯准则只能判断系统是否稳定,不能判断稳定程度
+伯德图
+nyquist 图
+相位裕度
+闭环特征方程的根闭,开环增益0到无穷 特征方程根的变化规律
+root locus
+单位负反馈
+G(s) = k/s(s+1)
+复角条件复值条件
+渐近线与实轴交点
+出射角p-n/n-m
+
+lambda
+大纯滞后
+积分对象
+lambda
+纯滞后 tao/t
+斯密斯预估 闭环传递函数 整定方法
+阶跃响应 鲁棒性 积分过程 输入干扰
+执行机构偏离,不确定不准确,调整速度
+PI 为主 D
+两自由度PID 比例积分先行
+鲁棒性 性能不完全微分
+负载扰
+
+makefile 工作原理:
+1、可执行文件生成过程:预处理->编译->链接
+#source object target
+SRC := *.c
+OBJ := *.o
+TARGET := mqtt_test
+
+#compile library include
+CC := cc
+LIB:= -lpthread
+LDFLAG := -L. libmosquitto.so
+CFLAG :=
+CXXFLAG :=
+#link
+$(TARGET):$(OBJ)
+ $(CC) -o $(TARGET) $(BOJ) $(LIB) $(LDFLAG)
+ $(CC) -o $@ $^ $(LIB) $(LDFLAG)
+$(OBJ):$(SRC)
+ $(CC) -c $(SRC)
+#all
+all:$(TARGET)
+ $(CC) -o $(TARGET) $(SRC) $(LIB) $(LDFLAG)
+#clean
+clean:
+ rm -rf *.o $(TARGET)
+*/
+// ————————————————————————————————————
+
+/*
+typedef struct
+{
+ int argc;
+ char **argv;
+ int sock;
+}st_app_param;
+
+const char *g_version = "V1.0.0 24.08.16";
+int child_mian_ini()
+{
+ int i_re;
+ i_re = gw_support_init();
+ if(i_re < 0)
+ {
+ printf("解析支持文件错误.\n");
+ return -1;
+ }
+
+ i_re = gw_config_init();
+ if(i_re < 0)
+ {
+ printf("解析配置文件错误.\n");
+ return -1;
+ }
+
+ i_re = gw_data_init();
+ if(i_re < 0)
+ {
+ printf("数据初始化错误.\n");
+ return -1;
+ }
+
+ i_re = gw_modol_init();
+ if(i_re < 0)
+ {
+ printf("解析模型文件错误.\n");
+ return -1;
+ }
+
+ i_re = gw_stat_init();
+ if(i_re < 0)
+ {
+ printf("数据统计初始化错误.\n");
+ return -1;
+ }
+
+ i_re = gw_process_init();
+ if(i_re < 0)
+ {
+ printf("规约初始化错误.\n");
+ return -1;
+ }
+
+ i_re = gw_manage_init();
+ if(i_re < 0)
+ {
+ printf("界面通讯初始化错误.\n");
+ return -1;
+ }
+
+
+ pthread_create(tid,thread_task1,p_param);
+
+ while(1)
+ {
+ get_sys_time();
+ sleep(1);
+ }
+}
+
+int child_main(int argc,char **argv)
+{
+
+ if((argc == 2)&&(strcasecmp(argv[1],"-version") == 0))
+ {
+ printf("version [%s]",g_version);
+ }
+
+ child_mian_ini();
+
+}
+
+static int run_child_process_thread((void *)param)
+{
+ st_app_param *p_param;
+
+ p_param = param;
+ chlid_main(p_parm->argc,p_param->argv);
+}
+
+static int run_child_process(int argc,char **argv,int sock)
+{
+ int i_re;
+ pthread_t *tid;
+ st_app_param p_param;
+
+ p_param.argc = argc;
+ p_param.argv = argv;
+ p_param.sock = sock;
+
+ pthread_creat(tid,run_child_process_thread,(void *)p_param);
+ i_re = recv(sock,..,0);//阻塞接收
+ send(sock,'q',0);
+}
+
+int main(int argc,char**argv)
+{
+ int i_re,fd,pid;
+ char lock_file[16];
+ socketpair sockpaire[2];
+
+ sprintf(lock_file,"%s.lock",argv[0]);
+
+ fd = open(lock_file,_O_WRONLY|_EXC,0777);
+ if(fd < 0)
+ {
+ printf("应用:[%s]已运行.\n",argv[0]);
+ return 0;
+ }
+
+ sockpaire[0] = -1;
+
+ while(1)
+ {
+ i_re = socketpaire(sockpaire,AN_UNIX,..);
+ if(i_re < 0)
+ {
+ printf("[%d]创建sockpaire失败.\n",getpid());
+ return 0;
+ }
+
+ pid = fork();
+
+ if(pid < 0)
+ {
+ printf("[%d]创建进程失败.\n",getpid());
+ close(sockpaire[0]);
+ sockpaire[0] = -1
+ close(sockpaire[1]);
+ return 0;
+ }
+
+ if(pid == 0)//child process
+ {
+ close(sockpair[0]);
+ return run_child_process(argc,argv,sockpair[1]);
+ }
+
+ printf("[%d]创建子进程成功.\n",getpid());
+ close(sockpair[1]);
+ while(1)//father process
+ {
+ i_re = recv(sockpaire[0],....,0);//阻塞接收
+ if(i_re <= 0)
+ {
+ //连接中断,重连
+ sockpaire[0] = -1;
+ break;
+ }
+ else
+ {
+ //正常退出
+ goto EXIT:
+ }
+ }
+
+EXIT:
+ //退出操作
+ if(sockpaire[0] == -1)
+ {
+ //有子进程,关闭子进程
+ }
+ close(fd);
+ unlink(file_lock);
+ }
+}
+*/
diff --git a/User/lib/control/custom/pid_zh1.h b/User/lib/control/custom/pid_zh1.h
new file mode 100644
index 0000000..addfbe8
--- /dev/null
+++ b/User/lib/control/custom/pid_zh1.h
@@ -0,0 +1,63 @@
+/*
+ * @Author: 张小明 zxm5337@163.com
+ * @Date: 2024-06-25 10:26:36
+ * @LastEditors: DaMingSY zxm5337@163.com
+ * @LastEditTime: 2024-09-03 09:19:23
+ * @FilePath: \controller-v2\User\lib\control\custom\cascade_pid_zh.h
+ * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+ */
+#ifndef __CASCADE_PID_ZH__
+#define __CASCADE_PID_ZH__
+
+#include "data_type_def.h"
+
+typedef enum
+{
+ TARGET_DIR_ADD,
+ TARGET_DIR_SUB,
+} target_dir_e;
+
+typedef struct
+{
+ float kp;
+ float ki;
+ float kd;
+
+ float kup;
+ float kui;
+ float kud;
+} fuzzy_pid_t;
+
+typedef struct
+{
+ BOOL iDetach, sm_open, fuzzy_open;
+ float feedBack;
+ float target, maxTarget;
+ float duty, kp, ki, kd;
+ float error, dError, lastError, errorDead;
+ float integral, iDetachCondation;
+ float output, maxOutput;
+ fuzzy_pid_t fuzzy_pid;
+} smart_pid_t;
+
+typedef struct
+{
+ smart_pid_t inner;
+ smart_pid_t outer;
+ float output;
+} cascade_pid_t;
+
+typedef struct CascadePID
+{
+ void (*smart_pid_init)(smart_pid_t *pid, float *duty, float *kp, float *ki, float *kd, float *errorDead, float *iDetachCondation, float *maxOut);
+ void (*cascade_pid_init)(cascade_pid_t *pid, smart_pid_t *pid_outer, smart_pid_t *pid_inner);
+ void (*smart_pid_calc)(smart_pid_t *pid, float *target, float *feedback);
+ void (*cascade_pid_calc)(struct CascadePID *pid, float *outerRef, float *outerFdb, float *innerFdb);
+
+ smart_pid_t smart_pid;
+ cascade_pid_t cascade_pid;
+} pid_zh1_t; // PID_t;
+
+extern void pid_zh_constructor1(struct CascadePID *pid);
+
+#endif
diff --git a/User/lib/control/inc/pid.h b/User/lib/control/inc/pid.h
index 17500ae..d5c6130 100644
--- a/User/lib/control/inc/pid.h
+++ b/User/lib/control/inc/pid.h
@@ -1,14 +1,29 @@
#ifndef __PID_H__
#define __PID_H__
#include "lib.h"
+
#include "pid_auto_tune.h"
#include "pid_c.h"
#include "pid_g.h"
#include "pid_x.h"
#include "pid_zh.h"
+#include "pid_zh1.h"
#include "pid_hd.h"
+#define INCOMPLETE_DIFFEREN 0 // 不完全微分
+
+typedef enum
+{
+ PID_SUB_TYPE_POSITION, // 位置式
+ PID_SUB_TYPE_INCREMENT, // 增量式
+} pid_sub_type_e;
+typedef enum
+{
+ DEAD_ZONE_POSITIVE = 1, // 正数
+ DEAD_ZONE_NEGATIVE = -1, // 负数
+ DEAD_ZONE_BOTH = 0 // 正负都可以
+} deadzone_e;
typedef enum
{
// PID自整定
@@ -34,42 +49,31 @@ typedef enum
PID_TYPE_CUSTOM_HANGDIAN,
} pid_type_e;
-typedef enum
-{
- // 位置式
- PID_SUB_TYPE_POSITION,
- // 增量式
- PID_SUB_TYPE_INCREMENT,
-} pid_sub_type_e;
-
-#define FUZZY_SUB_TYPE PID_SUB_TYPE_POSITION
-#define INCOMPLETE_DIFFEREN 0 // 不完全微分
-
-#pragma pack(1)
typedef struct
{
float32 ref;
- float32 feed_back;
- float32 pre_feed_back;
- float32 pre_error;
- float32 sum_iterm;
+ float32 feedback;
+ float32 pre_feedback;
+ float32 e_0; // 当前误差
+ float32 e_1; // 上一次误差
float32 kp;
float32 ki;
float32 kd;
float32 err_limit;
BOOL detach;
float32 err_dead;
-#if INCOMPLETE_DIFFEREN == 1
- dc_t alpha;
- dc_t lastdev;
-#endif
+ float32 alpha;
+ float32 lastdev;
float32 out;
float32 out_max;
float32 out_min;
float32 sv_range;
+ float32 iout; // 积分输出
BOOL sm;
BOOL ki_enable;
BOOL kd_enable;
+ float32 deviation; // 纠正系统误差造成的影响,作用于死区,大于0需要补偿,小于0需要反向补偿
+ BOOL in_dead_zone; // 是否在死区内
} pid_common_position_t; // 位置式PID
typedef struct
@@ -83,19 +87,28 @@ typedef struct
float32 e_0; // 当前误差
float32 e_1; // 上一次误差
float32 e_2; // 上上次误差
- float32 alpha;
- float32 lastdev;
float32 err_dead;
- float32 out_max; // 输出限幅
- float32 out_min; // 输出限幅
+ float32 deviation; // 纠正系统误差造成的影响,作用于死区
+ float32 out_max; // 输出限幅
+ float32 out_min; // 输出限幅
+ float32 sum_iterm;
+ float32 iout; // 积分输出
+ float32 alpha; // 不完全微分参数
+ float32 lastdev; // 不完全微分参数
+
BOOL sm;
+ BOOL ki_enable;
+ BOOL kd_enable;
float32 sv_range;
+ // 没有用的
+ float32 err_limit;
+ BOOL detach;
} pid_common_increment_t; // 增量式PID
-#pragma pack()
typedef struct PID_COMMON
{
- pid_sub_type_e type;
+ uint8_t type;
+
/* 设置PID三个参数 */
void (*set_ctrl_prm)(struct PID_COMMON *self, float32 kp, float32 ki, float32 kd);
/* 设置积分范围 */
@@ -119,7 +132,7 @@ typedef struct PID_COMMON
typedef struct PID_NEURAL
{
- pid_sub_type_e type;
+ uint8_t type;
/* 设置PID三个参数 */
void (*set_ctrl_prm)(struct PID_NEURAL *self, float32 minimum, float32 maximum);
/* 设置输出范围 */
@@ -156,47 +169,59 @@ typedef struct
float32 kup;
float32 kui;
float32 kud;
+
+ float32 maxe; // 非线性区间最大值
+ float32 mine; // 非线性区间最小值
} FUZZY_PID_t;
// 模糊PID
typedef struct PID_FUZZY
{
/* 设置PID三个参数 */
- void (*set_ctrl_prm)(struct PID_FUZZY *self, float32 kp, float32 ki, float32 kd, float32 err_dead,
- float32 out_min, float32 out_max); // 设置PID参数
+ void (*set_ctrl_prm)(struct PID_FUZZY *self, float32 kp, float32 ki, float32 kd, float32 err_dead, float32 deviation,
+ float32 out_min, float32 out_max); // 设置PID参数
+ void (*set_error_max_min)(struct PID_FUZZY *self, float32 mine, float32 maxe); // 设置非线性区间值
void (*update_ctrl_prm)(struct PID_FUZZY *self, float32 kp, float32 ki, float32 kd, float32 err_dead,
float32 out_min, float32 out_max); // 更新PID参数
void (*set_range)(struct PID_FUZZY *self, float32 out_min, float32 out_max); // 更新最大最小值
void (*set_cfg)(struct PID_FUZZY *self, float32 max_err, BOOL mode); // 配置PID模式,默认不使用积分分离
void (*set_smooth_enable)(struct PID_FUZZY *self, BOOL enable, float32 sv_range); // 设置平滑范围
-
- void (*set_err_dead)(struct PID_FUZZY *self, float32 err_dead); // 设置死区
+ void (*set_iout)(struct PID_FUZZY *self, float32 iout); // 设置积分输出
+ void (*set_err_dead)(struct PID_FUZZY *self, float32 err_dead); // 设置死区
void (*set_kp)(struct PID_FUZZY *self, float32 kp);
void (*set_ki_enable)(struct PID_FUZZY *self, BOOL enable);
void (*set_ki)(struct PID_FUZZY *self, float32 ki);
// 微分开启使能
void (*set_kd_enable)(struct PID_FUZZY *self, BOOL enable);
void (*set_kd)(struct PID_FUZZY *self, float32 kd);
- void (*restctrl)(struct PID_FUZZY *self); // 复位PID积分及微分控制数据
+ void (*set_kd_dev)(struct PID_FUZZY *self, float32 alpha);
+ void (*restctrl)(struct PID_FUZZY *self, float32 out); // 复位PID积分及微分控制数据
/* 控制接口 */
- float32 (*PID)(struct PID_FUZZY *self, float32 target, float32 feedback);
+ float32 (*execute)(struct PID_FUZZY *self, float32 target, float32 feedback);
-#if FUZZY_SUB_TYPE == PID_SUB_TYPE_POSITION
- pid_common_position_t pri;
-#else
- pid_common_increment_t pri;
-#endif
+ BOOL(*in_dead_zone)
+ (struct PID_FUZZY *self);
- BOOL open; // 是否使用模糊PID控制
+ union
+ {
+ pid_common_position_t position;
+ pid_common_increment_t increment;
+ } pri_u;
- FUZZY_PID_t fuzzy;
+ pid_sub_type_e sub_type; // 位置式PID,增量式PID
+ BOOL open; // 是否使用模糊PID控制
+ BOOL speed_integral_enable; // 变速积分,暂时没有验证成功
+ deadzone_e deadzone_dir;
+ FUZZY_PID_t pid_params;
} pid_fuzzy_t; // 模糊PID
// PID
typedef struct
{
- pid_type_e type;
+ BOOL is_init; // 是否初始化
+ pid_type_e type; // 不同的算法类型,模糊PID,神经PID,通用PID
+ pid_sub_type_e sub_type; // 位置式PID,增量式PID
union
{
pid_common_t common;
@@ -208,6 +233,7 @@ typedef struct
pid_g_t gao;
pid_x_t xu;
pid_zh_t zhang;
+ pid_zh1_t zhang1;
pid_hd_t hd;
} pid_u;
pid_auto_tune_t auto_tune;
diff --git a/User/lib/control/inc/pid_auto_tune.h b/User/lib/control/inc/pid_auto_tune.h
index 8df274a..e9e701c 100644
--- a/User/lib/control/inc/pid_auto_tune.h
+++ b/User/lib/control/inc/pid_auto_tune.h
@@ -36,15 +36,12 @@ typedef struct PID_AUTO_TUNE
int32_t sampleTime;
int32_t nLookBack;
int32_t peakType;
- // double lastInputs[101]; // 保存的历史输入值, 最多存前 100 次
int32_t lastInputs[51]; // 保存的历史输入值, 改为 50 次。 by shenghao.xu
int32_t peaks[13]; // 保存的历史峰值,最多存前 12 次,对应 6个最大、6个最小。20221124 by Embedream
int32_t peakCount; // 峰值计数
int32_t peakPeriod[7]; // 保存前 6 次的最大值间隔时间 by shenghao.xu
int32_t peakMaxCount; // 最大峰值计数 by shenghao.xu
BOOL justchanged;
- // BOOL justevaled; // 此标志没有使用
- // int32_t absMax, absMin; // 整个过程中采集的输入最大值、最小值
int32_t oStep; // 这个值是用于计算控制高低值的,以 outputStart 为中值,输出高值用 outputStart + oStep, 输出低值用 outputStart - oStep
float32 outputStart; // 输出控制的基础值,这个需要结合对象特征确定,此值也是通过第一次启动时对应的输出值带入的。
float32 Ku, Pu;
diff --git a/User/lib/control/src/pid.c b/User/lib/control/src/pid.c
index f0a1f76..64f2240 100644
--- a/User/lib/control/src/pid.c
+++ b/User/lib/control/src/pid.c
@@ -13,6 +13,7 @@ void pid_constructor(pid_t *self)
pid_neural_constructor(&self->pid_u.neural);
break;
case PID_TYPE_FUZZY:
+ self->pid_u.fuzzy.sub_type = self->sub_type;
pid_fuzzy_constructor(&self->pid_u.fuzzy);
break;
case PID_TYPE_AUTO_TUNE:
@@ -28,7 +29,8 @@ void pid_constructor(pid_t *self)
pid_x_constructor(&self->pid_u.xu);
break;
case PID_TYPE_CUSTOM_ZHANG:
- pid_zh_constructor(&self->pid_u.zhang);
+ // pid_zh_constructor(&self->pid_u.zhang);
+ pid_zh_constructor1(&self->pid_u.zhang1);
break;
case PID_TYPE_CUSTOM_HANGDIAN:
pid_hd_constructor(&self->pid_u.hd);
@@ -36,4 +38,5 @@ void pid_constructor(pid_t *self)
default:
break;
}
+ self->is_init = TRUE;
}
diff --git a/User/lib/control/src/pid_auto_tune.c b/User/lib/control/src/pid_auto_tune.c
index d3dee1b..5204421 100644
--- a/User/lib/control/src/pid_auto_tune.c
+++ b/User/lib/control/src/pid_auto_tune.c
@@ -14,7 +14,7 @@ static void set_look_backsec(pid_auto_tune_t *self, int32_t value)
if (value < 40)
{
self->pri.nLookBack = 12; // 按目前实际周期约300ms、采样周期 10ms 考虑,一个周期只有 30 点,回溯 12 点即可。
- self->pri.sampleTime = value * 10; // 改为 Value*100 ms, 20、30、40 ~ 200ms
+ self->pri.sampleTime = value * 10; // 改为 Value*10 ms, 20、30、40 ~ 200ms
}
else
{
@@ -31,7 +31,7 @@ static void _set_ctrl_prm(struct PID_AUTO_TUNE *self, float32 *input, float32 *o
self->pri.noiseBand = 1;
self->pri.running = FALSE;
self->pri.oStep = 1;
- set_look_backsec(self, 1);
+ set_look_backsec(self, 8);
self->pri.lastTime = sys_millis();
}
diff --git a/User/lib/control/src/pid_fuzzy.c b/User/lib/control/src/pid_fuzzy.c
index 3ef736e..83f1759 100644
--- a/User/lib/control/src/pid_fuzzy.c
+++ b/User/lib/control/src/pid_fuzzy.c
@@ -1,6 +1,8 @@
#include "pid.h"
#include
+// 定义死区枚举
+#define DEADZONE DEAD_ZONE_POSITIVE
// 模糊集合
#define NL -3
#define NM -2
@@ -23,7 +25,7 @@
// 定义输出量比例因子
#define KUP 3.0f // 这里只使用了模糊PID的比例增益
#define KUI 0.0f
-#define KUD 3.0f
+#define KUD 0.0f
static const float32 fuzzyRuleKp[7][7] = {
PL, PL, PM, PL, PS, PM, PL,
@@ -61,7 +63,7 @@ static void fuzzy(float32 e, float32 ec, FUZZY_PID_t *fuzzy_pid)
int eLeftIndex, ecLeftIndex; // 模糊位置标号
int eRightIndex, ecRightIndex;
- e = RANGE(e, MINE, MAXE);
+ e = RANGE(e, fuzzy_pid->mine, fuzzy_pid->maxe);
ec = RANGE(ec, MINEC, MAXEC);
e = e * KE;
ec = ec * KEC;
@@ -99,35 +101,104 @@ static void fuzzy(float32 e, float32 ec, FUZZY_PID_t *fuzzy_pid)
* @return {*}
* @note
*/
-static void smoothSetpoint(struct PID_FUZZY *self, float32 target_sv)
+static void smooth_setpoint(struct PID_FUZZY *self, float32 target_sv)
{
-#if FUZZY_SUB_TYPE == PID_SUB_TYPE_POSITION
- pid_common_position_t *pri = &self->pri;
-#else
- pid_common_increment_t *pri = &self->pri;
-#endif
- float32 stepIn = (pri->sv_range) * 0.1f;
- float32 kFactor = 0.0f;
- if (fabs(pri->ref - target_sv) <= stepIn)
+ if (self->sub_type == PID_SUB_TYPE_POSITION)
{
- pri->ref = target_sv;
- }
- else
- {
- if (pri->ref - target_sv > 0)
+ pid_common_position_t *pri = NULL;
+ pri = &self->pri_u.position;
+ float32 stepIn = (pri->sv_range) * 0.1f;
+ float32 kFactor = 0.0f;
+ if (fabs(pri->ref - target_sv) <= stepIn)
{
- kFactor = -1.0f;
- }
- else if (pri->ref - target_sv < 0)
- {
- kFactor = 1.0f;
+ pri->ref = target_sv;
}
else
{
- kFactor = 0.0f;
+ if (pri->ref - target_sv > 0)
+ {
+ kFactor = -1.0f;
+ }
+ else if (pri->ref - target_sv < 0)
+ {
+ kFactor = 1.0f;
+ }
+ else
+ {
+ kFactor = 0.0f;
+ }
+ pri->ref = pri->ref + kFactor * stepIn;
}
- pri->ref = pri->ref + kFactor * stepIn;
}
+ else
+ {
+ pid_common_increment_t *pri = NULL;
+ pri = &self->pri_u.increment;
+ float32 stepIn = (pri->sv_range) * 0.1f;
+ float32 kFactor = 0.0f;
+ if (fabs(pri->ref - target_sv) <= stepIn)
+ {
+ pri->ref = target_sv;
+ }
+ else
+ {
+ if (pri->ref - target_sv > 0)
+ {
+ kFactor = -1.0f;
+ }
+ else if (pri->ref - target_sv < 0)
+ {
+ kFactor = 1.0f;
+ }
+ else
+ {
+ kFactor = 0.0f;
+ }
+ pri->ref = pri->ref + kFactor * stepIn;
+ }
+ }
+}
+
+// 变速积分
+static float32 changing_integral_rate(struct PID_FUZZY *self)
+{
+ float32 err = 0, iout = 0;
+ float32 err_1 = 1, // 误差下限
+ err_2 = 10; // 误差上限
+ float32 index = 0;
+ if (self->sub_type == PID_SUB_TYPE_POSITION)
+ {
+ pid_common_position_t *pri = NULL;
+ pri = &self->pri_u.position;
+ err = pri->e_0;
+ iout = pri->iout;
+ }
+ else
+ {
+ pid_common_increment_t *pri = NULL;
+ pri = &self->pri_u.increment;
+ err = pri->e_0;
+ iout = pri->iout;
+ }
+
+ if (err * iout > 0) // 判断积分是否为积累趋势
+ {
+ if (ABS(err) <= err_1)
+ {
+ index = 1; // 完整积分
+ }
+ else if (ABS(err) <= (err_1 + err_2))
+ {
+ // 使用线性函数过渡
+ index = (float)(err_2 - ABS(err) + err_1) / err_2;
+ }
+ else
+ {
+ index = 0;
+ }
+ }
+
+ return index;
}
/*封装模糊接口*/
@@ -146,8 +217,20 @@ static void compensate(float32 e, float32 ec, FUZZY_PID_t *fuzzy_d)
*/
static void _set_range(struct PID_FUZZY *self, float32 out_min, float32 out_max)
{
- self->pri.out_max = out_max;
- self->pri.out_min = out_min;
+ if (self->sub_type == PID_SUB_TYPE_POSITION)
+ {
+ pid_common_position_t *pri = NULL;
+ pri = &self->pri_u.position;
+ pri->out_max = out_max;
+ pri->out_min = out_min;
+ }
+ else
+ {
+ pid_common_increment_t *pri = NULL;
+ pri = &self->pri_u.increment;
+ pri->out_max = out_max;
+ pri->out_min = out_min;
+ }
}
/**
@@ -159,12 +242,50 @@ static void _set_range(struct PID_FUZZY *self, float32 out_min, float32 out_max)
*/
static void _set_err_dead(struct PID_FUZZY *self, float32 err_dead)
{
- self->pri.err_dead = err_dead;
+ if (self->sub_type == PID_SUB_TYPE_POSITION)
+ {
+ pid_common_position_t *pri = NULL;
+ pri = &self->pri_u.position;
+ pri->err_dead = err_dead;
+ }
+ else
+ {
+ pid_common_increment_t *pri = NULL;
+ pri = &self->pri_u.increment;
+ pri->err_dead = err_dead;
+ }
+}
+
+static void _set_iout(struct PID_FUZZY *self, float32 iout)
+{
+ if (self->sub_type == PID_SUB_TYPE_POSITION)
+ {
+ pid_common_position_t *pri = NULL;
+ pri = &self->pri_u.position;
+ pri->iout = iout;
+ }
+ else
+ {
+ pid_common_increment_t *pri = NULL;
+ pri = &self->pri_u.increment;
+ pri->iout = iout;
+ }
}
static void _set_kp(struct PID_FUZZY *self, float32 kp)
{
- self->pri.kp = kp;
+ if (self->sub_type == PID_SUB_TYPE_POSITION)
+ {
+ pid_common_position_t *pri = NULL;
+ pri = &self->pri_u.position;
+ pri->kp = kp;
+ }
+ else
+ {
+ pid_common_increment_t *pri = NULL;
+ pri = &self->pri_u.increment;
+ pri->kp = kp;
+ }
}
/**
@@ -176,7 +297,7 @@ static void _set_kp(struct PID_FUZZY *self, float32 kp)
*/
// static void _set_ki_enable(struct PID_FUZZY *self, BOOL enable)
// {
-// self->pri.ki_enable = enable;
+// pri->ki_enable = enable;
// }
/**
@@ -188,22 +309,89 @@ static void _set_kp(struct PID_FUZZY *self, float32 kp)
*/
static void _set_kd_enable(struct PID_FUZZY *self, BOOL enable)
{
- self->pri.kd_enable = enable;
+ if (self->sub_type == PID_SUB_TYPE_POSITION)
+ {
+ pid_common_position_t *pri = NULL;
+ pri = &self->pri_u.position;
+ pri->kd_enable = enable;
+ }
+ else
+ {
+ pid_common_increment_t *pri = NULL;
+ pri = &self->pri_u.increment;
+ pri->kd_enable = enable;
+ }
}
static void _set_kd(struct PID_FUZZY *self, float32 kd)
{
- self->pri.kd = kd;
+ if (self->sub_type == PID_SUB_TYPE_POSITION)
+ {
+ pid_common_position_t *pri = NULL;
+ pri = &self->pri_u.position;
+ pri->kd = kd;
+ }
+ else
+ {
+ pid_common_increment_t *pri = NULL;
+ pri = &self->pri_u.increment;
+ pri->kd = kd;
+ }
+}
+
+/**
+ * @brief 配置不完全微分系数
+ * @param {PID_FUZZY} *self
+ * @param {float32} alpha
+ * @return {*}
+ * @note alpha范围0-1,系数越大,不完全微分的作用越强
+ */
+static void _set_kd_dev(struct PID_FUZZY *self, float32 alpha)
+{
+ if (self->sub_type == PID_SUB_TYPE_POSITION)
+ {
+ pid_common_position_t *pri = NULL;
+ pri = &self->pri_u.position;
+ pri->alpha = alpha;
+ }
+ else
+ {
+ pid_common_increment_t *pri = NULL;
+ pri = &self->pri_u.increment;
+ pri->alpha = alpha;
+ }
}
static void _set_ki_enable(struct PID_FUZZY *self, BOOL enable)
{
- self->pri.ki_enable = enable;
+ if (self->sub_type == PID_SUB_TYPE_POSITION)
+ {
+ pid_common_position_t *pri = NULL;
+ pri = &self->pri_u.position;
+ pri->ki_enable = enable;
+ }
+ else
+ {
+ pid_common_increment_t *pri = NULL;
+ pri = &self->pri_u.increment;
+ pri->ki_enable = enable;
+ }
}
static void _set_ki(struct PID_FUZZY *self, float32 ki)
{
- self->pri.ki = ki;
+ if (self->sub_type == PID_SUB_TYPE_POSITION)
+ {
+ pid_common_position_t *pri = NULL;
+ pri = &self->pri_u.position;
+ pri->ki = ki;
+ }
+ else
+ {
+ pid_common_increment_t *pri = NULL;
+ pri = &self->pri_u.increment;
+ pri->ki = ki;
+ }
}
/*
@@ -213,77 +401,115 @@ static void _set_ki(struct PID_FUZZY *self, float32 ki)
*/
static void _set_smooth_enable(struct PID_FUZZY *self, BOOL enable, float32 sv_range)
{
-#if FUZZY_SUB_TYPE == PID_SUB_TYPE_POSITION
- pid_common_position_t *pri = &self->pri;
-#else
- pid_common_increment_t *pri = &self->pri;
-#endif
- pri->sm = enable;
- pri->sv_range = sv_range;
+ if (self->sub_type == PID_SUB_TYPE_POSITION)
+ {
+ pid_common_position_t *pri = NULL;
+ pri = &self->pri_u.position;
+ pri->sm = enable;
+ pri->sv_range = sv_range;
+ }
+ else
+ {
+ pid_common_increment_t *pri = NULL;
+ pri = &self->pri_u.increment;
+ pri->sm = enable;
+ pri->sv_range = sv_range;
+ }
}
// 设置控制参数
-static void _set_ctrl_prm(struct PID_FUZZY *self, float32 kp, float32 ki, float32 kd, float32 err_dead,
+static void _set_ctrl_prm(struct PID_FUZZY *self, float32 kp, float32 ki, float32 kd, float32 err_dead, float32 deviation,
float32 out_min, float32 out_max)
{
self->open = TRUE;
- self->fuzzy.kup = KUP;
- self->fuzzy.kui = KUI;
- self->fuzzy.kud = KUD;
-#if FUZZY_SUB_TYPE == PID_SUB_TYPE_POSITION
- pid_common_position_t *pri = &self->pri;
- osel_memset((uint8_t *)pri, 0, sizeof(pid_common_position_t));
- pri->kp = kp;
- pri->ki = ki;
- pri->kd = kd;
- pri->err_dead = err_dead;
- pri->out_max = out_max;
- pri->out_min = out_min;
- pri->detach = FALSE;
- pri->sm = FALSE;
-#else
- pid_common_increment_t *pri = &self->pri;
- osel_memset((uint8_t *)pri, 0, sizeof(pid_common_increment_t));
- pri->kp = kp;
- pri->ki = ki;
- pri->kd = kd;
- pri->err_dead = err_dead;
- pri->out_max = out_max;
- pri->out_min = out_min;
-#endif
- pri->ki_enable = TRUE;
+ self->pid_params.kup = KUP;
+ self->pid_params.kui = KUI;
+ self->pid_params.kud = KUD;
+ self->pid_params.mine = MINE;
+ self->pid_params.maxe = MAXE;
+ if (self->sub_type == PID_SUB_TYPE_POSITION)
+ {
+ pid_common_position_t *pri = NULL;
+ pri = &self->pri_u.position;
+ osel_memset((uint8_t *)pri, 0, sizeof(pid_common_position_t));
+ pri->kp = kp;
+ pri->ki = ki;
+ pri->kd = kd;
+ pri->err_dead = err_dead;
+ pri->deviation = deviation;
+ pri->out_max = out_max;
+ pri->out_min = out_min;
+ pri->detach = FALSE;
+ pri->sm = FALSE;
+ pri->ki_enable = TRUE;
+ }
+ else
+ {
+ pid_common_increment_t *pri = NULL;
+ pri = &self->pri_u.increment;
+ osel_memset((uint8_t *)pri, 0, sizeof(pid_common_increment_t));
+ pri->kp = kp;
+ pri->ki = ki;
+ pri->kd = kd;
+ pri->err_dead = err_dead;
+ pri->deviation = deviation;
+ pri->out_max = out_max;
+ pri->out_min = out_min;
+ pri->ki_enable = TRUE;
+ }
+}
+
+static void _set_error_max_min(struct PID_FUZZY *self, float32 mine, float32 maxe)
+{
+ self->pid_params.mine = mine;
+ self->pid_params.maxe = maxe;
}
static void _update_ctrl_prm(struct PID_FUZZY *self, float32 kp, float32 ki, float32 kd, float32 err_dead,
float32 out_min, float32 out_max)
{
-#if FUZZY_SUB_TYPE == PID_SUB_TYPE_POSITION
- pid_common_position_t *pri = &self->pri;
- pri->kp = kp;
- pri->ki = ki;
- pri->kd = kd;
- pri->err_dead = err_dead;
- pri->out_max = out_max;
- pri->out_min = out_min;
- pri->detach = FALSE;
- pri->sm = FALSE;
-#else
- pid_common_increment_t *pri = &self->pri;
- pri->kp = kp;
- pri->ki = ki;
- pri->kd = kd;
- pri->err_dead = err_dead;
- pri->out_max = out_max;
- pri->out_min = out_min;
-#endif
- if (kd > 0)
+ if (self->sub_type == PID_SUB_TYPE_POSITION)
{
- pri->kd_enable = TRUE;
+ pid_common_position_t *pri = NULL;
+ pri = &self->pri_u.position;
+ pri->kp = kp;
+ pri->ki = ki;
+ pri->kd = kd;
+ pri->err_dead = err_dead;
+ pri->out_max = out_max;
+ pri->out_min = out_min;
+ pri->detach = FALSE;
+ pri->sm = FALSE;
+
+ if (kd > 0)
+ {
+ pri->kd_enable = TRUE;
+ }
+ else
+ {
+ pri->kd_enable = FALSE;
+ }
}
else
{
- pri->kd_enable = FALSE;
+ pid_common_increment_t *pri = NULL;
+ pri = &self->pri_u.increment;
+ pri->kp = kp;
+ pri->ki = ki;
+ pri->kd = kd;
+ pri->err_dead = err_dead;
+ pri->out_max = out_max;
+ pri->out_min = out_min;
+
+ if (kd > 0)
+ {
+ pri->kd_enable = TRUE;
+ }
+ else
+ {
+ pri->kd_enable = FALSE;
+ }
}
}
@@ -296,214 +522,360 @@ static void _update_ctrl_prm(struct PID_FUZZY *self, float32 kp, float32 ki, flo
*/
static void _set_cfg(struct PID_FUZZY *self, float32 max_err, BOOL mode)
{
- self->pri.err_limit = max_err;
- self->pri.detach = mode == FALSE ? FALSE : TRUE;
+
+ if (self->sub_type == PID_SUB_TYPE_POSITION)
+ {
+ pid_common_position_t *pri = NULL;
+ pri = &self->pri_u.position;
+ pri->err_limit = max_err;
+ pri->detach = mode == FALSE ? FALSE : TRUE;
+ }
+ else
+ {
+ pid_common_increment_t *pri = NULL;
+ pri = &self->pri_u.increment;
+ pri->err_limit = max_err;
+ pri->detach = mode == FALSE ? FALSE : TRUE;
+ }
}
-#if FUZZY_SUB_TYPE == PID_SUB_TYPE_POSITION
-static float32 _PID(struct PID_FUZZY *self, float32 target, float32 feedback)
+/**
+ * @brief 判断是否处于死区范围内
+ *
+ * 根据给定的 PID_FUZZY 结构体,判断当前值是否处于死区范围内。
+ *
+ * @param self PID_FUZZY 结构体指针
+ *
+ * @return 如果处于死区范围内,返回 TRUE;否则返回 FALSE
+ */
+static BOOL _in_dead_zone(struct PID_FUZZY *self)
+{
+ float32 deviation = 0.0f;
+ float32 err_dead = 0.0f;
+ float32 err = 0.0f;
+ float32 offset = 0.0f;
+ if (self->sub_type == PID_SUB_TYPE_POSITION)
+ {
+ pid_common_position_t *pri = NULL;
+ pri = &self->pri_u.position;
+ deviation = pri->deviation;
+ err_dead = pri->err_dead;
+ err = pri->feedback - pri->ref;
+ }
+ else
+ {
+ pid_common_increment_t *pri = NULL;
+ pri = &self->pri_u.increment;
+ deviation = pri->deviation;
+ err_dead = pri->err_dead;
+ err = pri->feedback - pri->ref;
+ }
+
+ offset = err + deviation;
+
+ if (self->deadzone_dir == DEAD_ZONE_POSITIVE)
+ {
+ if (offset >= 0 && offset <= ABS(err_dead))
+ {
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+ }
+ else if (self->deadzone_dir == DEAD_ZONE_NEGATIVE)
+ {
+ if (offset <= 0 && offset >= err_dead)
+ {
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+ }
+ else
+ {
+ if (ABS(offset) <= ABS(err_dead))
+ {
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+ }
+}
+
+static float32 position_pid(struct PID_FUZZY *self, float32 target, float32 feedback)
{
float32 error = 0;
- float32 insert = 0;
float32 ec = 0;
float32 kd = 0;
-#if INCOMPLETE_DIFFEREN == 1
float32 thisdev = 0;
-#else
- // float32 dinput = 0.0f;
-#endif
- // float32 fuzzy_kp = 0.0f;
- // float32 fuzzy_ki = 0.0f;
- // float32 fuzzy_kd = 0.0f;
- float32 temp_iterm = 0.0f;
- pid_common_position_t *pri = &self->pri;
+ pid_common_position_t *pri = &self->pri_u.position;
+ kd = pri->kd;
/*获取期望值与实际值,进行偏差计算*/
if (pri->sm == 1)
{
- smoothSetpoint(self, target);
+ smooth_setpoint(self, target);
}
else
{
pri->ref = target;
}
- pri->feed_back = feedback;
- error = pri->ref - pri->feed_back;
- if (fabs(error) <= pri->err_dead)
+ pri->feedback = feedback;
+ error = pri->ref - pri->feedback;
+
+ if (self->in_dead_zone(self) == TRUE)
+ {
error = 0;
-
- /* fuzzy control caculate */
- ec = error - pri->pre_error;
- if (self->open == TRUE)
- {
- compensate(error, ec, &self->fuzzy);
- }
-
- /*根据PID配置的模式,获取积分数据,进行积分累加*/
- if (pri->out >= pri->out_max)
- {
- if (fabs(error) > pri->err_limit && pri->detach)
- {
- insert = 0;
- }
- else
- {
- insert = 1;
- if (error < 0)
- {
- temp_iterm = (pri->ki + self->fuzzy.ki) * error;
- }
- }
- }
- else if (pri->out <= pri->out_min)
- {
- if (fabs(error) > pri->err_limit && pri->detach)
- {
- insert = 0;
- }
- else
- {
- insert = 1;
- if (error > 0)
- {
- temp_iterm = (pri->ki + self->fuzzy.ki) * error;
- }
- }
+ pri->in_dead_zone = TRUE;
}
else
{
- if (fabs(error) > pri->err_limit && pri->detach)
+ pri->in_dead_zone = FALSE;
+ }
+
+ pri->e_0 = error;
+
+ /* fuzzy control caculate */
+ ec = error - pri->e_1;
+ if (self->open == TRUE)
+ {
+ compensate(error, ec, &self->pid_params);
+ }
+
+ /*根据PID配置的模式,获取积分数据,进行积分累加*/
+ if (self->speed_integral_enable == TRUE)
+ {
+ pri->iout = (pri->ki + self->pid_params.ki) * error * changing_integral_rate(self);
+ }
+ else
+ {
+ float32 temp_iterm = 0.0f;
+ float32 insert = 0;
+ if (pri->out >= pri->out_max)
{
- insert = 0;
+ if (fabs(error) > pri->err_limit && pri->detach)
+ {
+ insert = 0;
+ }
+ else
+ {
+ insert = 1;
+ if (error < 0)
+ {
+ temp_iterm = (pri->ki + self->pid_params.ki) * error;
+ }
+ }
+ }
+ else if (pri->out <= pri->out_min)
+ {
+ if (fabs(error) > pri->err_limit && pri->detach)
+ {
+ insert = 0;
+ }
+ else
+ {
+ insert = 1;
+ if (error > 0)
+ {
+ temp_iterm = (pri->ki + self->pid_params.ki) * error;
+ }
+ }
}
else
{
- insert = 1;
- temp_iterm = (pri->ki + self->fuzzy.ki) * error;
+ if (fabs(error) > pri->err_limit && pri->detach)
+ {
+ insert = 0;
+ }
+ else
+ {
+ insert = 1;
+ temp_iterm = (pri->ki + self->pid_params.ki) * error;
+ }
}
- }
- pri->sum_iterm += temp_iterm;
- /* limt integral */
- if (pri->sum_iterm > pri->out_max)
- {
- pri->sum_iterm = pri->out_max;
- }
- else if (pri->sum_iterm < pri->out_min)
- {
- pri->sum_iterm = pri->out_min;
+ pri->iout += temp_iterm;
+
+ /* limt integral */
+ if (pri->iout > pri->out_max)
+ {
+ pri->iout = pri->out_max;
+ }
+ else if (pri->iout < pri->out_min)
+ {
+ pri->iout = pri->out_min;
+ }
+ pri->iout = pri->iout * insert;
}
#if INCOMPLETE_DIFFEREN == 1
/*不完全微分*/
- thisdev = (pri->kd + self->fuzzy.kd) * (1.0 - pri->alpha) * (error - pri->pre_error) + pri->alpha * pri->lastdev;
- /*caculate pid out*/
- pri->out = (pri->kp + self->fuzzy.kp) * error + pri->sum_iterm * insert + thisdev;
-
+ thisdev = kd * (1.0 - pri->alpha) * (error - pri->e_1) + pri->alpha * pri->lastdev;
/*record last dev result*/
pri->lastdev = thisdev;
#else
+ thisdev = (error - pri->e_1) * (kd);
+#endif
- if (pri->kd_enable == TRUE)
+ if (pri->kd_enable == FALSE)
{
- kd = pri->kd + self->fuzzy.kd;
- }
- else
- {
- kd = 0;
+ thisdev = 0;
}
if (pri->ki_enable == FALSE)
{
- insert = 0;
+ pri->iout = 0;
}
- pri->out = (pri->kp + self->fuzzy.kp) * error + pri->sum_iterm * insert + (error - pri->pre_error) * (kd);
-#endif
-
- pri->pre_error = error;
+ pri->out = (pri->kp + self->pid_params.kp) * error + pri->iout + thisdev;
+ pri->e_1 = error;
/*record last feedback sensor result*/
- pri->pre_feed_back = pri->feed_back;
+ pri->pre_feedback = pri->feedback;
/*limt pid output*/
pri->out = RANGE(pri->out, pri->out_min, pri->out_max);
return pri->out;
}
-/**
- * @brief 复位PID积分及微分控制数据
- * @param {PID_FUZZY} *self
- * @return {*}
- */
-static void _restctrl(struct PID_FUZZY *self)
+static float32 increment_pid(struct PID_FUZZY *self, float32 target, float32 feedback)
{
- self->pri.pre_error = 0;
- self->pri.sum_iterm = 0;
-#if INCOMPLETE_DIFFEREN == 1
- self->pri.lastdev = 0;
-#endif
-}
+ float32 ep, ei, ed;
+ float32 inc_out;
+ float32 thisdev = 0;
+ pid_common_increment_t *pri = &self->pri_u.increment;
-#elif FUZZY_SUB_TYPE == PID_SUB_TYPE_INCREMENT
-static float32 _PID(struct PID_FUZZY *self, float32 target, float32 feedback)
-{
- float fuzzy_kp = 0.0f;
- float fuzzy_ki = 0.0f;
- float fuzzy_kd = 0.0f;
-
- dc_t ep, ei, ed;
- dc_t inc_out;
- dc_t thisdev = 0;
- if (pri->sm == 1)
- {
- smoothSetpoint(self, target);
- }
- else
- {
- pri->ref = target;
- }
pri->feedback = feedback;
pri->e_0 = pri->ref - pri->feedback;
+
+ if (pri->e_0 >= MAXE)
+ {
+ return pri->out_max;
+ }
+ else if (pri->e_0 <= MINE)
+ {
+ return pri->out_min;
+ }
+
if (fabs(pri->e_0) <= pri->err_dead)
+ {
pri->e_0 = 0;
+ }
+
ep = pri->e_0 - pri->e_1;
ei = pri->e_0;
ed = pri->e_0 - 2 * pri->e_1 + pri->e_2;
if (self->open == TRUE)
{
- compensate(pri->e_0, ep, &self->fuzzy);
+ compensate(pri->e_0, ep, &self->pid_params);
}
+
+ if (pri->sm == 1)
+ {
+ smooth_setpoint(self, target);
+ }
+ else
+ {
+ pri->ref = target;
+ }
+
+#if INCOMPLETE_DIFFEREN == 1
/*不完全微分*/
- thisdev = (1.0 - pri->alpha) * (pri->kd + fuzzy_kd) * ed + pri->alpha * pri->lastdev;
- inc_out = (pri->kp + fuzzy_kp) * ep + (pri->ki + fuzzy_ki) * ei + thisdev;
+ thisdev = (1.0 - pri->alpha) * (pri->kd + self->pid_params.kd) * ed + pri->alpha * pri->lastdev;
+#else
+ ed = ed;
+#endif
+
+ if (self->speed_integral_enable == TRUE)
+ {
+
+ if (ABS(pri->e_0) > MAXE)
+ {
+ pri->iout = (pri->ki + self->pid_params.ki) * ei;
+ }
+ else
+ {
+ // 变速积分
+ pri->iout = (pri->ki + self->pid_params.ki) * ei * changing_integral_rate(self);
+ }
+ }
+ else
+ {
+ pri->iout = (pri->ki + self->pid_params.ki) * ei;
+ }
+
+ if (pri->kd_enable == FALSE)
+ {
+ thisdev = 0;
+ }
+
+ if (pri->ki_enable == FALSE)
+ {
+ pri->iout = 0;
+ }
+
+ inc_out = (pri->kp + self->pid_params.kp) * ep + pri->iout + thisdev;
pri->e_2 = pri->e_1;
pri->e_1 = pri->e_0;
pri->lastdev = thisdev;
- // pri->out = pri->out + inc_out;
- pri->out = inc_out;
+ pri->out = pri->out + inc_out;
pri->out = RANGE(pri->out, pri->out_min, pri->out_max);
return pri->out;
}
+static float32 _pid(struct PID_FUZZY *self, float32 target, float32 feedback)
+{
+ if (self->sub_type == PID_SUB_TYPE_POSITION)
+ {
+ return position_pid(self, target, feedback);
+ }
+ else
+ {
+ return increment_pid(self, target, feedback);
+ }
+}
+
/**
* @brief 复位PID积分及微分控制数据
* @param {PID_FUZZY} *self
* @return {*}
*/
-static void _restctrl(struct PID_FUZZY *self)
+static void _restctrl(struct PID_FUZZY *self, float32 out)
{
- self->e_0 = 0;
- self->e_1 = 0;
- self->e_2 = 0;
- self->lastdev = 0;
-}
-#else
-#error Please Define PID Controller Type
+ if (self->sub_type == PID_SUB_TYPE_POSITION)
+ {
+ pid_common_position_t *pri = NULL;
+ pri = &self->pri_u.position;
+ pri->e_1 = 0;
+ pri->iout = 0;
+ pri->out = out;
+ pri->iout = out;
+#if INCOMPLETE_DIFFEREN == 1
+ pri->lastdev = 0;
#endif
+ }
+ else
+ {
+ pid_common_increment_t *pri = NULL;
+ pri = &self->pri_u.increment;
+ pri->e_0 = 0;
+ pri->e_1 = 0;
+ pri->e_2 = 0;
+ pri->lastdev = 0;
+ pri->out = out;
+ pri->iout = out;
+ }
+}
void pid_fuzzy_constructor(struct PID_FUZZY *self)
{
self->set_ctrl_prm = _set_ctrl_prm;
+ self->set_error_max_min = _set_error_max_min;
self->update_ctrl_prm = _update_ctrl_prm;
self->set_cfg = _set_cfg;
self->set_smooth_enable = _set_smooth_enable;
@@ -513,7 +885,10 @@ void pid_fuzzy_constructor(struct PID_FUZZY *self)
self->set_ki = _set_ki;
self->set_kd_enable = _set_kd_enable;
self->set_kd = _set_kd;
+ self->set_kd_dev = _set_kd_dev;
self->set_range = _set_range;
self->restctrl = _restctrl;
- self->PID = _PID;
+ self->set_iout = _set_iout;
+ self->in_dead_zone = _in_dead_zone;
+ self->execute = _pid;
}
diff --git a/User/lib/control/src/pid_neural.c b/User/lib/control/src/pid_neural.c
index f7991c4..93ffc03 100644
--- a/User/lib/control/src/pid_neural.c
+++ b/User/lib/control/src/pid_neural.c
@@ -17,7 +17,7 @@ static void _set_ctrl_prm(struct PID_NEURAL *self, float32 minimum, float32 maxi
self->pri.maximum = maximum; /*输出值上限*/
self->pri.minimum = minimum; /*输出值下限*/
- self->pri.deadband = (maximum - minimum) * 0.0005; /*死区*/
+ self->pri.deadband = (maximum - minimum) * 0.0005f; /*死区*/
self->pri.wp = 0.10; /*比例加权系数*/
self->pri.wi = 0.10; /*积分加权系数*/
diff --git a/User/lib/control/模糊PID控制器设计文档.md b/User/lib/control/模糊PID控制器设计文档.md
new file mode 100644
index 0000000..c9cf8b3
--- /dev/null
+++ b/User/lib/control/模糊PID控制器设计文档.md
@@ -0,0 +1,111 @@
+# 模糊PID控制器设计文档
+
+# 模糊PID控制器详细设计文档
+
+## 1. 引言
+
+### 1.1 目的
+
+本文档旨在详细介绍模糊PID控制器的设计理念、实现方法和使用指南,为开发者提供一套完整的模糊PID控制解决方案。
+
+### 1.2 背景
+
+PID控制器因其结构简单、稳定性好、易于实现等优点,在工业控制系统中得到了广泛应用。然而,传统PID控制器在面对复杂或非线性系统时,性能表现不佳。模糊PID控制器通过引入模糊逻辑,动态调整PID参数,以适应系统在不同工作状态下的控制需求,从而提高控制性能。
+
+## 2. 设计概述
+
+### 2.1 设计目标
+
+- **适应性**:能够适应不同类型和不同工作状态的控制系统。
+- **稳定性**:保证控制系统在各种工作条件下的稳定运行。
+- **易用性**:提供简单易懂的接口,便于开发者快速实现和调试。
+
+### 2.2 功能模块
+
+模糊PID控制器主要包括以下几个功能模块:
+
+1. **模糊控制模块**:负责根据输入的误差和误差变化率,通过模糊逻辑计算出PID参数。
+2. **SV平滑给定模块**:负责平滑控制目标值,减少控制过程中的突变。
+3. **变速积分模块**:根据误差的大小调整积分速率,提高控制效率。
+4. **参数设置模块**:提供接口函数,用于设置和调整PID参数。
+
+## 3. 功能模块详细设计
+
+### 3.1 模糊控制模块
+
+#### 3.1.1 输入处理
+
+- **误差处理**:将实时误差 `e`限制在预定的范围内,并进行模糊化处理。
+- **误差变化率处理**:将误差变化率 `ec`进行相同的处理。
+
+#### 3.1.2 模糊规则库
+
+- **规则定义**:根据系统的具体需求,定义一套模糊规则,用于计算PID参数。
+- **规则应用**:根据输入的误差和误差变化率的模糊化值,通过模糊规则库计算出 `kp`、`ki`、`kd`。
+
+### 3.2 SV平滑给定模块
+
+- **平滑策略**:根据当前目标值与新目标值之间的差值,动态调整目标值变化的步长,实现平滑过渡。
+
+### 3.3 变速积分模块
+
+- **积分策略**:根据误差的大小,调整积分速率。误差较小时,使用完整积分;误差较大时,减小或停止积分。
+
+### 3.4 参数设置模块
+
+- **接口设计**:提供一系列接口函数,用于设置PID控制器的参数,如输出限制、死区误差等。
+
+## 4. 使用说明
+
+### 4.1 初始化
+
+- **控制器初始化**:根据控制对象的特性,初始化模糊PID控制器的相关参数和模糊规则库。
+
+### 4.2 实时控制
+
+- **参数调整**:在控制循环中,根据实时误差和误差变化率,动态调整PID参数。
+- **控制执行**:根据调整后的PID参数,执行PID控制算法,输出控制信号。
+
+### 4.3 参数调整
+
+- **动态调整**:根据系统运行情况,通过参数设置模块调整PID参数,优化控制效果。
+
+## 5. 结论
+
+模糊PID控制器通过动态调整PID参数,提高了控制系统的适应性和稳定性,特别适用于复杂或非线性系统的控制。本文档提供了模糊PID控制器的详细设计方案,旨在帮助开发者更好地理解和应用模糊PID控制技术
+
+## 概述
+
+本文档旨在详细介绍模糊PID控制器的设计与实现。模糊PID控制器结合了传统PID控制和模糊逻辑控制的优点,通过模糊逻辑对PID参数进行动态调整,以适应控制系统在不同工作状态下的需求。
+
+## 功能模块
+
+### 1. 模糊控制模块
+
+- **功能描述**:根据误差 `e`和误差变化率 `ec`的模糊化值,通过模糊规则库计算出模糊PID控制器的三个参数:比例系数 `kp`、积分系数 `ki`、微分系数 `kd`。
+- **实现方法**:首先将输入的误差 `e`和误差变化率 `ec`限制在预定范围内,然后通过模糊化处理得到其隶属度和模糊位置标号,最后根据模糊规则库计算出 `kp`、`ki`、`kd`的值。
+
+### 2. SV平滑给定模块
+
+- **功能描述**:平滑控制目标值(Setpoint Value, SV),以减少控制过程中的突变,提高系统的稳定性。
+- **实现方法**:根据当前目标值与新目标值之间的差值,动态调整目标值的变化步长,以实现平滑过渡。
+
+### 3. 变速积分模块
+
+- **功能描述**:根据误差的大小调整积分速率,以提高控制系统的快速性和稳定性。
+- **实现方法**:当误差较小时,使用完整积分;当误差在一定范围内变化时,通过线性函数调整积分速率;当误差较大时,减小或停止积分,以避免积分饱和。
+
+### 4. 参数设置模块
+
+- **功能描述**:提供接口函数,用于设置PID控制器的各项参数,包括输出限制范围、死区误差、积分输出值、PID参数等。
+- **实现方法**:根据控制器的子类型(位置型或增量型),分别设置相应参数的值。
+
+## 使用说明
+
+1. **初始化**:根据控制对象的具体情况,初始化模糊PID控制器的结构体,包括最大误差、最小误差、PID参数的模糊规则库等。
+2. **实时控制**:在控制循环中,根据当前的误差 `e`和误差变化率 `ec`调用模糊控制模块,计算出动态调整的PID参数,然后根据这些参数进行PID控制。
+3. **参数调整**:根据系统运行情况,通过参数设置模块调整PID控制器的参数,以优化控制效果。
+
+## 结论
+
+模糊PID控制器通过引入模糊逻辑,使得PID参数能够根据控制系统的实时状态动态调整,从而提高了控制系统的适应性和稳定性。通过本文档的设计与实现,开发者可以更好地理解和应用模糊PID控制器。
diff --git a/User/lib/examples/simple_aes.c b/User/lib/examples/simple_aes.c
deleted file mode 100644
index fb4fd5c..0000000
--- a/User/lib/examples/simple_aes.c
+++ /dev/null
@@ -1,40 +0,0 @@
-#include "../inc/data_type_def.h"
-#include "../inc/log.h"
-#include "../inc/osel_arch.h"
-#include "../inc/aes.h"
-
-// 全局变量
-static aes_context AesContext; // 密钥表
-static uint8_t aBlock[] = {0x00, 0x00, 0x00, 0xcc, 0xff, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; // 数据块
-static uint8_t sBlock[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; // 存放输出结果
-
-int32_t main(void)
-{
- uint8_t buf[16] = {0x00};
- uint8_t size = ARRAY_LEN(buf);
- uint8_t key[] = {
- 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6,
- 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C}; // 密钥
-
- // 初始化密文
- for (int i = 0; i < size; i++)
- {
- buf[i] = i;
- }
-
- // 设置预密钥
- osel_memset(AesContext.ksch, 0, ARRAY_LEN(AesContext.ksch));
- aes_set_key(key, 16, &AesContext);
-
- // 加密
- osel_memcpy(aBlock, buf, size);
- aes_encrypt(aBlock, sBlock, &AesContext);
- LOG_HEX(sBlock, ARRAY_LEN(sBlock)); // 打印加密结果:50 fe 67 cc 99 6d 32 b6 da 09 37 e9 9b af ec 60
-
- // 解密
- osel_memcpy(aBlock, sBlock, size);
- aes_decrypt(aBlock, sBlock, &AesContext);
- LOG_HEX(sBlock, ARRAY_LEN(sBlock)); // 打印解密结果:00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f
-}
diff --git a/User/lib/examples/simple_clist.c b/User/lib/examples/simple_clist.c
deleted file mode 100644
index 3254b07..0000000
--- a/User/lib/examples/simple_clist.c
+++ /dev/null
@@ -1,52 +0,0 @@
-#include "../inc/data_type_def.h"
-#include "../inc/clist.h"
-
-int32_t main(void)
-{
- clist_node_t *head = NULL; // 创建头指针,初始化为NULL
- clist_init(&head); // 初始化指针(可有可无)
-
- // 1:添加数据
- for (int32_t i = 0; i < 30; i++)
- {
- if (i > 10)
- clist_push_front(&head, (cnode)i); // 头部插入
- else
- clist_push_back(&head, (cnode)i); // 尾部插入
- }
-
- LOG_PRINT("\n 1: count:%d \n", clist_node_count(head)); // 获取链表节点数,打印
- clist_print(head); // 打印链表
-
- // 2:删除数据
- for (int32_t i = 0; i < 10; i++)
- {
- if (i > 5)
- clist_pop_back(&head); // 删除尾部
- else
- clist_pop_front(&head); // 头部删除
- }
- LOG_PRINT("\n 2: count:%d \n", clist_node_count(head));
- clist_print(head);
-
- // 3:插入数据
- clist_insert(&head, 5, (cnode)1111);
- clist_insert_for_node(&head, head->Next->Next->Next->Next->Next, (cnode)10000);
- clist_insert(&head, 1000, (cnode)2222); // 无效插入
- LOG_PRINT("\n 3: count:%d \n", clist_node_count(head));
- clist_print(head);
-
- // 4:删除指定节点
- clist_remove(&head, (cnode)5);
- clist_erase_for_node(&head, head->Next->Next);
- clist_remove(&head, (cnode)1000); // 无效删除
- clist_print(head);
- LOG_PRINT("\n 4: count:%d \n", clist_node_count(head));
- clist_print(head);
-
- // 5:删除所有节点
- clist_destroy(&head);
- LOG_PRINT("\n 5: count:%d ", clist_node_count(head));
- clist_print(head);
- return 0;
-}
diff --git a/User/lib/examples/simple_cmac.c b/User/lib/examples/simple_cmac.c
deleted file mode 100644
index a96726f..0000000
--- a/User/lib/examples/simple_cmac.c
+++ /dev/null
@@ -1,33 +0,0 @@
-#include "../inc/data_type_def.h"
-#include "../inc/log.h"
-#include "../inc/osel_arch.h"
-#include "../inc/cmac.h"
-
-static uint8_t key[] = {
- 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6,
- 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C}; // 密钥
-int32_t main(void)
-{
- uint8_t *p;
- uint8_t buffer[16] = {0x00};
- uint32_t size = ARRAY_LEN(buffer);
- // 初始化需要校验的数据
- for (int i = 0; i < size; i++)
- {
- buffer[i] = i;
- }
- uint8_t mic[16]; // 存放生成校验数据的数组
- AES_CMAC_CTX AesCmacCtx[1]; // 密钥扩展表
- AES_CMAC_Init(AesCmacCtx); // 完成密钥扩展表的初始化
-
- AES_CMAC_SetKey(AesCmacCtx, key); // 完成密钥扩展表数据
-
- AES_CMAC_Update(AesCmacCtx, buffer, size & 0xFF); // 完成数据的奇偶校验
-
- AES_CMAC_Final(mic, AesCmacCtx); // 生成16个字节的校验表
-
- uint32_t xor_vol = (uint32_t)((uint32_t)mic[3] << 24 | (uint32_t)mic[2] << 16 | (uint32_t)mic[1] << 8 | (uint32_t)mic[0]); // 取表4个字节作为校验码
-
- p = (uint8_t *)&xor_vol;
- LOG_HEX(p, 4); // 打印结果:5c 7e fb 43
-}
diff --git a/User/lib/examples/simple_cmd.c b/User/lib/examples/simple_cmd.c
deleted file mode 100644
index 563e759..0000000
--- a/User/lib/examples/simple_cmd.c
+++ /dev/null
@@ -1,26 +0,0 @@
-#include "../inc/data_type_def.h"
-#include "../inc/log.h"
-#include "../inc/cmd.h"
-
-void at_name_req(void)
-{
- LOG_PRINT("name:cmd\n");
-}
-
-void at_version_req(void)
-{
- LOG_PRINT("version:1.0\n");
-}
-
-REGISTER_CMD(NAME, at_name_req, at name);
-REGISTER_CMD(VERSION, at_version_req, at version);
-
-int32_t main(void)
-{
- cmd_init();
-
- cmd_parsing("TEST");
- cmd_parsing("NAME");
- cmd_parsing("VERSION");
- return 0;
-}
diff --git a/User/lib/examples/simple_data_analysis.c b/User/lib/examples/simple_data_analysis.c
deleted file mode 100644
index 41d38ad..0000000
--- a/User/lib/examples/simple_data_analysis.c
+++ /dev/null
@@ -1,178 +0,0 @@
-#include "../inc/data_type_def.h"
-#include "../inc/log.h"
-#include "../inc/osel_arch.h"
-#include "../inc/data_analysis.h"
-#define UART_RXSIZE (254U)
-#define UART_DATA_ANALYSIS_PORT_1 DATA_1
-#define UART_DATA_ANALYSIS_PORT_2 DATA_2
-
-static data_interupt_cb_t uart_data_analysis_cb = NULL; // 数据源中断回调函数
-
-static void data_analysis_event1(void)
-{
- uint8_t frame[UART_RXSIZE];
- uint8_t data_head[3];
- uint8_t crc[2];
- uint16_t frame_len, out_frame_len;
- data_read(UART_DATA_ANALYSIS_PORT_1, &data_head[0], 3);
- osel_memcpy((uint8_t *)&frame_len, &data_head[1], 2);
-
- frame_len = B2S_UINT16(frame_len) - 2; // 报文长度包含帧长,这里需要减2
- if (frame_len > UART_RXSIZE)
- {
- lock_data(UART_DATA_ANALYSIS_PORT_1);
- unlock_data(UART_DATA_ANALYSIS_PORT_1);
- return;
- }
-
- out_frame_len = data_read(UART_DATA_ANALYSIS_PORT_1, frame, (uint16_t)frame_len);
- if (out_frame_len != frame_len)
- {
- return;
- }
- out_frame_len = out_frame_len - 1; // 报文中包含帧尾,这里需要减1
-
- // 校验CRC_16
- uint16_t crc_16 = 0;
- uint16_t crc16 = crc16_compute(&frame[0], out_frame_len - 2);
- osel_memcpy(&crc[0], &frame[out_frame_len - 2], 2);
- crc_16 = BUILD_UINT16(crc[1], crc[0]);
- if (crc16 != crc_16)
- {
- return;
- }
- // CRC校验通过后将数据长度-2
- out_frame_len -= 2;
-
- LOG_PRINT("data_analysis_event1 ok:");
- LOG_HEX(frame, out_frame_len);
-}
-
-static void data_analysis_event2(void)
-{
- uint8_t frame[UART_RXSIZE];
- uint8_t data_head[4];
- uint8_t crc[2];
- uint16_t frame_len, out_frame_len;
- data_read(UART_DATA_ANALYSIS_PORT_2, &data_head[0], 4);
- osel_memcpy((uint8_t *)&frame_len, &data_head[2], 2);
- frame_len = B2S_UINT16(frame_len);
- if (frame_len > UART_RXSIZE)
- {
- lock_data(UART_DATA_ANALYSIS_PORT_2);
- unlock_data(UART_DATA_ANALYSIS_PORT_2);
- return;
- }
-
- out_frame_len = data_read(UART_DATA_ANALYSIS_PORT_2, frame, (uint16_t)frame_len);
- if (out_frame_len != frame_len)
- {
- return;
- }
-
- // 校验CRC_16
- uint16_t crc_16 = 0;
- uint16_t crc16 = crc16_compute(&frame[0], out_frame_len - 2);
- osel_memcpy(&crc[0], &frame[out_frame_len - 2], 2);
- crc_16 = BUILD_UINT16(crc[1], crc[0]);
- if (crc16 != crc_16)
- {
- LOG_PRINT("crc error crc16:%x, crc_16:%x\n");
- return;
- }
-
- out_frame_len -= 2; // 去掉CRC_16
-
- LOG_PRINT("data_analysis_event2 ok:");
- LOG_HEX(frame, out_frame_len);
-}
-/**
- * @brief 需要识别帧头和帧尾的数据协议
- * @return {*}
- * @note
- */
-static void data_register1(void)
-{
-/**
- * 帧头 帧长度 源地址 目标地址 报文类型 报文体 校验 帧尾
- 1 2 2 2 1 n 2 1
-*/
-#define FRAME_HEAD 0x05 // 帧头
-#define FRAME_TAIL 0x1b // 帧尾
-
- // 注册数据解析
- data_reg_t reg;
- reg.sd.valid = true; // 数据头部验证有效标志位
- reg.sd.len = 1; // 数据头部长度
- reg.sd.pos = 0; // 数据头部偏移量
- reg.sd.data[0] = FRAME_HEAD; // 数据头部数据
- reg.ld.len = 2; // 数据长度
- reg.ld.pos = 2; // 报文长度包含帧长,这里需要设置偏移2
- reg.ld.valid = true; // 数据长度有效标志位
- reg.ld.little_endian = false; // 数据长度是否小端模式
- reg.argu.len_max = UART_RXSIZE; // 数据最大长度
- reg.argu.len_min = 2; // 数据最小长度
- reg.ed.valid = true; // 数据尾部有效标志位
- reg.ed.len = 1; // 数据尾部长度
- reg.ed.data[0] = FRAME_TAIL; // 数据尾部数据
- reg.echo_en = false; // 是否回显
- reg.func_ptr = data_analysis_event1; // 数据解析回调函数 data_analysis模块处理完数据后,会调用这个函数继续数据协议的处理
- uart_data_analysis_cb = data_fsm_init(UART_DATA_ANALYSIS_PORT_1); // 注册数据处理函数 data_analysis模块会调用这个函数,将数据写入到data_analysis模块
- data_reg(UART_DATA_ANALYSIS_PORT_1, reg); // 注册数据解析
-}
-
-/**
- * @brief 需要识别帧头和没有帧尾的数据协议
- * @return {*}
- * @note
- */
-static void data_register2(void)
-{
-/**
- * 帧头 帧长度 源地址 目标地址 报文类型 报文体 校验
- 2 2 2 2 1 n 2
-*/
-#define FRAME_HEAD1 0xD5 // 帧头
-#define FRAME_HEAD2 0xC8 // 帧尾
-
- // 注册数据解析
- data_reg_t reg;
- reg.sd.valid = true; // 数据头部验证有效标志位
- reg.sd.len = 2; // 数据头部长度
- reg.sd.pos = 0; // 数据头部偏移量
- reg.sd.data[0] = FRAME_HEAD1; // 数据头部数据
- reg.sd.data[1] = FRAME_HEAD2; // 数据头部数据
- reg.ld.len = 2; // 数据长度
- reg.ld.pos = 2; // 报文长度包含帧长,这里需要设置偏移2
- reg.ld.valid = true; // 数据长度有效标志位
- reg.ld.little_endian = false; // 数据长度是否小端模式
- reg.argu.len_max = UART_RXSIZE; // 数据最大长度
- reg.argu.len_min = 2; // 数据最小长度
- reg.ed.valid = false; // 数据尾部有效标志位
- reg.echo_en = false; // 是否回显
- reg.func_ptr = data_analysis_event2; // 数据解析回调函数 data_analysis模块处理完数据后,会调用这个函数继续数据协议的处理
- uart_data_analysis_cb = data_fsm_init(UART_DATA_ANALYSIS_PORT_2); // 注册数据处理函数 data_analysis模块会调用这个函数,将数据写入到data_analysis模块
- data_reg(UART_DATA_ANALYSIS_PORT_2, reg); // 注册数据解析
-}
-
-int32_t main(void)
-{
- data_register1();
- data_register2();
-
- // 模拟串口数据
- uint8_t data1[] = {0x05, 0x00, 0x0a, 0xff, 0xff, 0x00, 0x01, 0x00, 0x55, 0x40, 0x1b};
- for (uint16_t i = 0; i < ARRAY_LEN(data1); i++)
- {
- uart_data_analysis_cb(UART_DATA_ANALYSIS_PORT_1, *(data1 + i));
- }
-
- // 模拟串口数据
- uint8_t data2[] = {0xD5, 0xC8, 0x00, 0x07, 0xff, 0xff, 0x00, 0x01, 0x00, 0x55, 0x40};
- for (uint16_t i = 0; i < ARRAY_LEN(data2); i++)
- {
- uart_data_analysis_cb(UART_DATA_ANALYSIS_PORT_2, *(data2 + i));
- }
-
- return 0;
-}
diff --git a/User/lib/examples/simple_sqqueue.c b/User/lib/examples/simple_sqqueue.c
deleted file mode 100644
index 3ed8c91..0000000
--- a/User/lib/examples/simple_sqqueue.c
+++ /dev/null
@@ -1,53 +0,0 @@
-#include "../inc/data_type_def.h"
-#include "../inc/log.h"
-#include "../inc/osel_arch.h"
-#include "../inc/sqqueue.h"
-
-typedef struct
-{
- uint8_t x;
- uint8_t y;
-} element_t;
-
-sqqueue_ctrl_t queue; // 创建队列对象
-
-void traverse_cb(const void *e)
-{
- element_t *p = (element_t *)e;
- LOG_PRINT("x = %d, y = %d", p->x, p->y);
-}
-
-int32_t main(void)
-{
- int size = 10;
- // 初始化队列
- if (FALSE == sqqueue_ctrl_init(&queue, sizeof(element_t), size))
- {
- LOG_ERR("queue init failed!");
- return -1; // 创建失败
- }
-
- // 添加测试元素
- for (int i = 1; i <= 10; i++)
- {
- element_t element;
- element.x = i * 10;
- element.y = i * 10;
- queue.enter(&queue, &element); // 将成员插入到队列中
- }
- LOG_PRINT("add queue len = %d", queue.get_len(&queue)); // 获取队列长度
-
- queue.del(&queue); // 移除首元素
- LOG_PRINT("del queue len = %d", queue.get_len(&queue)); // 获取队列长度
- queue.revoke(&queue); // 移除尾元素
- LOG_PRINT("revoke queue len = %d", queue.get_len(&queue)); // 获取队列长度
- queue.remove(&queue, 3); // 删除相对队头指定偏移位置的元素
- LOG_PRINT("remove queue len = %d", queue.get_len(&queue)); // 获取队列长度
-
- LOG_PRINT("queue traverse:");
- queue.traverse(&queue, traverse_cb); // 遍历队列
-
- queue.clear_sqq(&queue); // 清空队列
- LOG_PRINT("clear queue len = %d", queue.get_len(&queue)); // 获取队列长度
- return 0;
-}
diff --git a/User/lib/flashdb/fal/fal_cfg.h b/User/lib/flashdb/fal/fal_cfg.h
index f453e0a..aaec268 100644
--- a/User/lib/flashdb/fal/fal_cfg.h
+++ b/User/lib/flashdb/fal/fal_cfg.h
@@ -12,15 +12,16 @@
#define _FAL_CFG_H_
#include "eeprom_m95.h"
#include "eeprom_fm24.h"
+#include "flash.h"
#define FAL_PART_HAS_TABLE_CFG
-
-#define EEPROM_M95_1_BLOCK_SIZE M95_PAGE_SIZE_128 * 64
+#define FAL_ERASE_SIZE 100
+// 需要块大小为2的N次方
+#define EEPROM_M95_1_BLOCK_SIZE M95_PAGE_SIZE_256 * 32
#define EEPROM_M95_2_BLOCK_SIZE M95_PAGE_SIZE_256 * 32
+#define EEPROM_FM24_BLOCK_SIZE FM24_PAGE_SIZE * 16
-#define EEPROM_FM24_BLOCK_SIZE FM24_PAGE_SIZE * 4 // 因为块大小为2的N次方
-
-#define EEPROM_M95_1_SIZE _M95512_
+#define EEPROM_M95_1_SIZE _M95M02_
#define EEPROM_M95_2_SIZE _M95M02_
#define EEPROM_FM24_SIZE FM24_SIZE
@@ -37,19 +38,19 @@ extern struct fal_flash_dev eeprom_fm24;
#define FAL_FLASH_DEV_TABLE \
{ \
&eeprom_m95_1, \
- &eeprom_m95_2, \
- &eeprom_fm24, \
+ &eeprom_m95_2, \
+ &eeprom_fm24, \
}
/* ====================== Partition Configuration ========================== */
#ifdef FAL_PART_HAS_TABLE_CFG
/* partition table */
// issues :https://github.com/armink/FlashDB/issues/40 ;epprom的扇区太小
-#define FAL_PART_TABLE \
- { \
- {FAL_PART_MAGIC_WORD, "KVDB", EEPROM_M95_1_DEV_NAME, 0, EEPROM_M95_1_SIZE, 0}, \
- {FAL_PART_MAGIC_WORD, "TSDB", EEPROM_M95_2_DEV_NAME, 0, EEPROM_M95_2_SIZE, 0}, \
- {FAL_PART_MAGIC_WORD, "RTDB", EEPROM_FM24_DEV_NAME, 0, EEPROM_FM24_SIZE, 0}, \
+#define FAL_PART_TABLE \
+ { \
+ {FAL_PART_MAGIC_WORD, "KVDB", EEPROM_M95_1_DEV_NAME, 0, EEPROM_M95_1_SIZE, 0}, \
+ {FAL_PART_MAGIC_WORD, "TSDB", EEPROM_M95_2_DEV_NAME, 0, EEPROM_M95_2_SIZE, 0}, \
+ {FAL_PART_MAGIC_WORD, "RTDB", EEPROM_FM24_DEV_NAME, 0, EEPROM_FM24_SIZE, 0}, \
}
#endif /* FAL_PART_HAS_TABLE_CFG */
diff --git a/User/lib/flashdb/fal/fal_def.h b/User/lib/flashdb/fal/fal_def.h
index afdbc0b..de8aada 100644
--- a/User/lib/flashdb/fal/fal_def.h
+++ b/User/lib/flashdb/fal/fal_def.h
@@ -17,46 +17,39 @@
#include
#endif
-#define FAL_SW_VERSION "0.5.99"
+#define FAL_SW_VERSION "0.5.99"
#ifdef __RTTHREAD__ /* for RT-Thread platform */
#include
-#define FAL_PRINTF rt_kprintf
-#define FAL_MALLOC rt_malloc
-#define FAL_CALLOC rt_calloc
-#define FAL_REALLOC rt_realloc
-#define FAL_FREE rt_free
+#define FAL_PRINTF rt_kprintf
+#define FAL_MALLOC rt_malloc
+#define FAL_CALLOC rt_calloc
+#define FAL_REALLOC rt_realloc
+#define FAL_FREE rt_free
#endif
#ifndef FAL_MALLOC
-#define FAL_MALLOC malloc
+#define FAL_MALLOC malloc
#endif
#ifndef FAL_CALLOC
-#define FAL_CALLOC calloc
+#define FAL_CALLOC calloc
#endif
#ifndef FAL_REALLOC
-#define FAL_REALLOC realloc
+#define FAL_REALLOC realloc
#endif
#ifndef FAL_FREE
-#define FAL_FREE free
+#define FAL_FREE free
#endif
-// #ifndef FAL_PRINTF
-// #define FAL_PRINTF printf
-// #endif
-
#ifndef FAL_PRINTF
-#define FAL_PRINTF(...) \
- do \
- { \
- } while (0);
+#define FAL_PRINTF printf
#endif
#ifndef FAL_DEBUG
-#define FAL_DEBUG 0
+#define FAL_DEBUG 0
#endif
#if FAL_DEBUG
@@ -64,24 +57,20 @@
#ifdef assert
#undef assert
#endif
-#define assert(EXPR) \
- if (!(EXPR)) \
- { \
- FAL_PRINTF("(%s) has assert failed at %s.\n", #EXPR, __func__); \
- while (1) \
- ; \
- }
+#define assert(EXPR) \
+if (!(EXPR)) \
+{ \
+ FAL_PRINTF("(%s) has assert failed at %s.\n", #EXPR, __func__ ); \
+ while (1); \
+}
#endif
/* debug level log */
-#ifdef log_d
-#undef log_d
+#ifdef log_d
+#undef log_d
#endif
#include
-#define log_d(...) \
- FAL_PRINTF("[D/FAL] (%s:%" PRIdLEAST16 ") ", __func__, __LINE__); \
- FAL_PRINTF(__VA_ARGS__); \
- FAL_PRINTF("\n")
+#define log_d(...) FAL_PRINTF("[D/FAL] (%s:%" PRIdLEAST16 ") ", __func__, __LINE__); FAL_PRINTF(__VA_ARGS__);FAL_PRINTF("\n")
#else
@@ -89,33 +78,27 @@
#ifdef assert
#undef assert
#endif
-#define assert(EXPR) ((void)0);
+#define assert(EXPR) ((void)0);
#endif
/* debug level log */
-#ifdef log_d
-#undef log_d
+#ifdef log_d
+#undef log_d
#endif
#define log_d(...)
#endif /* FAL_DEBUG */
/* error level log */
-#ifdef log_e
-#undef log_e
+#ifdef log_e
+#undef log_e
#endif
-#define log_e(...) \
- FAL_PRINTF("\033[31;22m[E/FAL] (%s:%d) ", __func__, __LINE__); \
- FAL_PRINTF(__VA_ARGS__); \
- FAL_PRINTF("\033[0m\n")
+#define log_e(...) FAL_PRINTF("\033[31;22m[E/FAL] (%s:%d) ", __func__, __LINE__);FAL_PRINTF(__VA_ARGS__);FAL_PRINTF("\033[0m\n")
/* info level log */
-#ifdef log_i
-#undef log_i
+#ifdef log_i
+#undef log_i
#endif
-#define log_i(...) \
- FAL_PRINTF("\033[32;22m[I/FAL] "); \
- FAL_PRINTF(__VA_ARGS__); \
- FAL_PRINTF("\033[0m\n")
+#define log_i(...) FAL_PRINTF("\033[32;22m[I/FAL] "); FAL_PRINTF(__VA_ARGS__);FAL_PRINTF("\033[0m\n")
/* FAL flash and partition device name max length */
#ifndef FAL_DEV_NAME_MAX
@@ -140,7 +123,7 @@ struct fal_flash_dev
int (*erase)(long offset, size_t size);
} ops;
- /* write minimum granularity, unit: bit.
+ /* write minimum granularity, unit: bit.
1(nor flash)/ 8(stm32f2/f4)/ 32(stm32f1)/ 64(stm32l4)
0 will not take effect. */
size_t write_gran;
diff --git a/User/lib/flashdb/fal_eeprom24_port.c b/User/lib/flashdb/fal_eeprom24_port.c
index c9995fb..e068589 100644
--- a/User/lib/flashdb/fal_eeprom24_port.c
+++ b/User/lib/flashdb/fal_eeprom24_port.c
@@ -20,8 +20,8 @@ static int write(long offset, const uint8_t *buf, size_t size);
struct fal_flash_dev eeprom_fm24 =
{
.name = EEPROM_FM24_DEV_NAME,
- .addr = 0x000000,
- .len = EEPROM_FM24_SIZE,
+ .addr = 50 * FM24_PAGE_SIZE,
+ .len = EEPROM_FM24_SIZE - 50 * FM24_PAGE_SIZE,
.blk_size = EEPROM_FM24_BLOCK_SIZE,
.ops = {init, read, write, erase},
.write_gran = 1};
@@ -33,16 +33,25 @@ static int init(void)
static int erase(long offset, size_t size)
{
- // uint8_t buf[EEPROM_FM24_BLOCK_SIZE];
- // osel_memset(buf, 0x00, EEPROM_FM24_BLOCK_SIZE);
- // uint32_t addr = eeprom_fm24.addr + offset;
- // eeprom_fm24_write(addr, (uint8_t *)buf, size);
+ // uint8_t erase_size = size > FAL_ERASE_SIZE ? FAL_ERASE_SIZE : size;
+ // uint8_t buf[FAL_ERASE_SIZE];
+ // osel_memset(buf, 0xFF, FAL_ERASE_SIZE);
+
+ // for (uint8_t i = 0; i < (size / FM24_PAGE_SIZE); i++)
+ // {
+ // uint32_t addr = eeprom_fm24.addr + offset + i * FM24_PAGE_SIZE;
+ // eeprom_fm24_write(addr, (uint8_t *)buf, erase_size);
+ // }
return size;
}
static int read(long offset, uint8_t *buf, size_t size)
{
/* You can add your code under here. */
+ if (size == 0)
+ {
+ return 0;
+ }
uint32_t addr = eeprom_fm24.addr + offset;
BOOL res = eeprom_fm24_read(addr, buf, size);
return res == TRUE ? size : 0;
@@ -50,7 +59,11 @@ static int read(long offset, uint8_t *buf, size_t size)
static int write(long offset, const uint8_t *buf, size_t size)
{
+ if (size == 0)
+ {
+ return 0;
+ }
uint32_t addr = eeprom_fm24.addr + offset;
- eeprom_fm24_write(addr, (uint8_t *)buf, size);
- return size;
+ BOOL res = eeprom_fm24_write(addr, (uint8_t *)buf, size);
+ return res == TRUE ? (int)size : -1;
}
diff --git a/User/lib/flashdb/fal_eeprom95_port.c b/User/lib/flashdb/fal_eeprom95_port.c
index 037f810..142cf78 100644
--- a/User/lib/flashdb/fal_eeprom95_port.c
+++ b/User/lib/flashdb/fal_eeprom95_port.c
@@ -11,24 +11,22 @@
#include
static int init(void);
-static int erase1(long offset, size_t size);
-static int erase2(long offset, size_t size);
+static int erase(long offset, size_t size);
static int read1(long offset, uint8_t *buf, size_t size);
-static int write1(long offset, const uint8_t *buf, size_t size);
-
static int read2(long offset, uint8_t *buf, size_t size);
+static int write1(long offset, const uint8_t *buf, size_t size);
static int write2(long offset, const uint8_t *buf, size_t size);
// 1.定义 flash 设备
struct fal_flash_dev eeprom_m95_1 =
{
.name = EEPROM_M95_1_DEV_NAME,
- .addr = 0x000000,
- .len = EEPROM_M95_1_SIZE,
+ .addr = 10 * M95_PAGE_SIZE_256,
+ .len = EEPROM_M95_1_SIZE - 10 * M95_PAGE_SIZE_256,
.blk_size = EEPROM_M95_1_BLOCK_SIZE,
- .ops = {init, read1, write1, erase1},
- .write_gran = 8}; // 设置写粒度,单位 bit, 0 表示未生效(默认值为 0 ),该成员是 fal 版本大于 0.4.0 的新增成员。各个 flash 写入粒度不尽相同,可通过该成员进行设置,以下列举几种常见 Flash 写粒度
+ .ops = {init, read1, write1, erase},
+ .write_gran = 1}; // 设置写粒度,单位 bit,EPPROM写粒度为1bit
struct fal_flash_dev eeprom_m95_2 =
{
@@ -36,29 +34,25 @@ struct fal_flash_dev eeprom_m95_2 =
.addr = 0x000000,
.len = EEPROM_M95_2_SIZE,
.blk_size = EEPROM_M95_2_BLOCK_SIZE,
- .ops = {init, read2, write2, erase2},
- .write_gran = 8};
+ .ops = {init, read2, write2, erase},
+ .write_gran = 1};
static int init(void)
{
return 1;
}
-static int erase1(long offset, size_t size)
+static int erase(long offset, size_t size)
{
- // uint8_t buf[EEPROM_M95_1_BLOCK_SIZE];
- // osel_memset(buf, 0x00, EEPROM_M95_1_BLOCK_SIZE);
- // uint32_t addr = eeprom_m95_1.addr + offset;
- // eeprom_m95_write(M95_1, addr, (uint8_t *)buf, size);
- return size;
-}
+ // uint8_t erase_size = size > FAL_ERASE_SIZE ? FAL_ERASE_SIZE : size;
+ // uint8_t buf[FAL_ERASE_SIZE];
+ // osel_memset(buf, 0xFF, FAL_ERASE_SIZE);
-static int erase2(long offset, size_t size)
-{
- // uint8_t buf[EEPROM_M95_2_BLOCK_SIZE];
- // osel_memset(buf, 0x00, EEPROM_M95_2_BLOCK_SIZE);
- // uint32_t addr = eeprom_m95_2.addr + offset;
- // eeprom_m95_write(M95_2, addr, (uint8_t *)buf, size);
+ // for (uint8_t i = 0; i < (size / M95_PAGE_SIZE_256); i++)
+ // {
+ // uint32_t addr = eeprom_m95_1.addr + offset + i * M95_PAGE_SIZE_256;
+ // eeprom_m95_write(M95_1, addr, (uint8_t *)buf, erase_size);
+ // }
return size;
}
@@ -66,28 +60,28 @@ static int read1(long offset, uint8_t *buf, size_t size)
{
/* You can add your code under here. */
uint32_t addr = eeprom_m95_1.addr + offset;
- eeprom_m95_read(M95_1, addr, buf, size);
- return size;
+ BOOL res = eeprom_m95_read(M95_1, addr, buf, size);
+ return res == TRUE ? size : 0;
}
static int write1(long offset, const uint8_t *buf, size_t size)
{
uint32_t addr = eeprom_m95_1.addr + offset;
- eeprom_m95_write(M95_1, addr, (uint8_t *)buf, size);
- return size;
+ BOOL res = eeprom_m95_write(M95_1, addr, (uint8_t *)buf, size);
+ return res == TRUE ? (int)size : -1;
}
static int read2(long offset, uint8_t *buf, size_t size)
{
/* You can add your code under here. */
uint32_t addr = eeprom_m95_2.addr + offset;
- eeprom_m95_read(M95_2, addr, buf, size);
- return size;
+ BOOL res = eeprom_m95_read(M95_2, addr, buf, size);
+ return res == TRUE ? size : 0;
}
static int write2(long offset, const uint8_t *buf, size_t size)
{
uint32_t addr = eeprom_m95_2.addr + offset;
- eeprom_m95_write(M95_2, addr, (uint8_t *)buf, size);
- return size;
+ BOOL res = eeprom_m95_write(M95_2, addr, (uint8_t *)buf, size);
+ return res == TRUE ? (int)size : -1;
}
diff --git a/User/lib/flashdb/fdb.c b/User/lib/flashdb/fdb.c
index 021aa90..8de2b2a 100644
--- a/User/lib/flashdb/fdb.c
+++ b/User/lib/flashdb/fdb.c
@@ -74,7 +74,7 @@ fdb_err_t _fdb_init_ex(fdb_db_t db, const char *name, const char *path, fdb_db_t
} else {
/* must be aligned with block size */
if (db->sec_size % block_size != 0) {
- FDB_INFO("Error: db sector size (%" PRIu32 ") MUST align with block size (%" PRIu32 ").\n", db->sec_size, block_size);
+ FDB_INFO("Error: db sector size (%" PRIu32 ") MUST align with block size (%zu).\n", db->sec_size, block_size);
return FDB_INIT_FAILED;
}
}
diff --git a/User/lib/flashdb/fdb_cfg.h b/User/lib/flashdb/fdb_cfg.h
index e86aaa7..239d9a2 100644
--- a/User/lib/flashdb/fdb_cfg.h
+++ b/User/lib/flashdb/fdb_cfg.h
@@ -45,6 +45,6 @@
/* #define FDB_PRINT(...) my_printf(__VA_ARGS__) */
/* print debug information */
-#define FDB_DEBUG_ENABLE
+// #define FDB_DEBUG_ENABLE
#endif /* _FDB_CFG_H_ */
diff --git a/User/lib/flashdb/fdb_def.h b/User/lib/flashdb/fdb_def.h
index 7e65075..acba9e0 100644
--- a/User/lib/flashdb/fdb_def.h
+++ b/User/lib/flashdb/fdb_def.h
@@ -22,8 +22,8 @@ extern "C"
#endif
/* software version number */
-#define FDB_SW_VERSION "2.1.0"
-#define FDB_SW_VERSION_NUM 0x20100
+#define FDB_SW_VERSION "2.1.1"
+#define FDB_SW_VERSION_NUM 0x20101
/* the KV max name length must less then it */
#ifndef FDB_KV_NAME_MAX
@@ -50,7 +50,7 @@ extern "C"
/* the file cache table size, it will improve GC speed in file mode when using cache */
#ifndef FDB_FILE_CACHE_TABLE_SIZE
-#define FDB_FILE_CACHE_TABLE_SIZE 2
+#define FDB_FILE_CACHE_TABLE_SIZE 4
#endif
#ifndef FDB_WRITE_GRAN
@@ -62,12 +62,8 @@ extern "C"
// #define FDB_PRINT(...) printf(__VA_ARGS__)
// #endif
#ifndef FDB_PRINT
-#define FDB_PRINT(...) \
- do \
- { \
- } while (0);
+#define FDB_PRINT(...)
#endif
-
#define FDB_LOG_PREFIX1() FDB_PRINT("[FlashDB]" FDB_LOG_TAG)
#define FDB_LOG_PREFIX2() FDB_PRINT(" ")
#define FDB_LOG_PREFIX() \
@@ -139,7 +135,6 @@ typedef int32_t fdb_time_t;
struct fdb_default_kv_node *kvs;
size_t num;
};
- typedef struct fdb_default_kv *fdb_default_kv_t;
/* error code */
typedef enum
diff --git a/User/lib/flashdb/fdb_kvdb.c b/User/lib/flashdb/fdb_kvdb.c
index 4e737cd..2bf2375 100644
--- a/User/lib/flashdb/fdb_kvdb.c
+++ b/User/lib/flashdb/fdb_kvdb.c
@@ -8,7 +8,7 @@
* @file
* @brief KVDB feature.
*
- * @file fdb_kvdb.c
+ * Key-Value Database feature implement source file.
*/
#include
@@ -18,8 +18,8 @@
#define FDB_LOG_TAG "[kv]"
/* rewrite log prefix */
-#undef FDB_LOG_PREFIX2
-#define FDB_LOG_PREFIX2() FDB_PRINT("[%s][%s] ", db_name(db), _fdb_db_path((fdb_db_t)db))
+#undef FDB_LOG_PREFIX2
+#define FDB_LOG_PREFIX2() FDB_PRINT("[%s][%s] ", db_name(db), _fdb_db_path((fdb_db_t)db))
#if defined(FDB_USING_KVDB)
@@ -32,23 +32,25 @@
#endif
/* magic word(`F`, `D`, `B`, `1`) */
-#define SECTOR_MAGIC_WORD 0x30424446
+#define SECTOR_MAGIC_WORD 0x30424446
/* magic word(`K`, `V`, `0`, `0`) */
-#define KV_MAGIC_WORD 0x3030564B
+#define KV_MAGIC_WORD 0x3030564B
+/* GC minimum number of empty sectors. GC will using at least 1 empty sector. */
+#define GC_MIN_EMPTY_SEC_NUM 1
/* the sector remain threshold before full status */
#ifndef FDB_SEC_REMAIN_THRESHOLD
-#define FDB_SEC_REMAIN_THRESHOLD (KV_HDR_DATA_SIZE + FDB_KV_NAME_MAX)
+#define FDB_SEC_REMAIN_THRESHOLD (KV_HDR_DATA_SIZE + FDB_KV_NAME_MAX)
#endif
/* the total remain empty sector threshold before GC */
#ifndef FDB_GC_EMPTY_SEC_THRESHOLD
-#define FDB_GC_EMPTY_SEC_THRESHOLD 1 // https://github.com/armink/FlashDB/issues/156 这个值设定大了会有异常
+#define FDB_GC_EMPTY_SEC_THRESHOLD 1
#endif
/* the string KV value buffer size for legacy fdb_get_kv(db, ) function */
#ifndef FDB_STR_KV_VALUE_MAX_SIZE
-#define FDB_STR_KV_VALUE_MAX_SIZE 128
+#define FDB_STR_KV_VALUE_MAX_SIZE 128
#endif
#if FDB_KV_CACHE_TABLE_SIZE > 0xFFFF
@@ -56,97 +58,87 @@
#endif
/* the sector is not combined value */
-#if (FDB_BYTE_ERASED == 0xFF)
-#define SECTOR_NOT_COMBINED 0xFFFFFFFF
-#define SECTOR_COMBINED 0x00000000
+#if (FDB_BYTE_ERASED == 0xFF)
+#define SECTOR_NOT_COMBINED 0xFFFFFFFF
+#define SECTOR_COMBINED 0x00000000
#else
-#define SECTOR_NOT_COMBINED 0x00000000
-#define SECTOR_COMBINED 0xFFFFFFFF
+#define SECTOR_NOT_COMBINED 0x00000000
+#define SECTOR_COMBINED 0xFFFFFFFF
#endif
/* the next address is get failed */
-#define FAILED_ADDR 0xFFFFFFFF
+#define FAILED_ADDR 0xFFFFFFFF
-#define KV_STATUS_TABLE_SIZE FDB_STATUS_TABLE_SIZE(FDB_KV_STATUS_NUM)
+#define KV_STATUS_TABLE_SIZE FDB_STATUS_TABLE_SIZE(FDB_KV_STATUS_NUM)
-#define SECTOR_NUM (db_max_size(db) / db_sec_size(db))
+#define SECTOR_NUM (db_max_size(db) / db_sec_size(db))
-#define SECTOR_HDR_DATA_SIZE (FDB_WG_ALIGN(sizeof(struct sector_hdr_data)))
-#define SECTOR_STORE_OFFSET ((unsigned long)(&((struct sector_hdr_data *)0)->status_table.store))
-#define SECTOR_DIRTY_OFFSET ((unsigned long)(&((struct sector_hdr_data *)0)->status_table.dirty))
-#define SECTOR_MAGIC_OFFSET ((unsigned long)(&((struct sector_hdr_data *)0)->magic))
-#define KV_HDR_DATA_SIZE (FDB_WG_ALIGN(sizeof(struct kv_hdr_data)))
-#define KV_MAGIC_OFFSET ((unsigned long)(&((struct kv_hdr_data *)0)->magic))
-#define KV_LEN_OFFSET ((unsigned long)(&((struct kv_hdr_data *)0)->len))
-#define KV_NAME_LEN_OFFSET ((unsigned long)(&((struct kv_hdr_data *)0)->name_len))
+#define SECTOR_HDR_DATA_SIZE (FDB_WG_ALIGN(sizeof(struct sector_hdr_data)))
+#define SECTOR_STORE_OFFSET ((unsigned long)(&((struct sector_hdr_data *)0)->status_table.store))
+#define SECTOR_DIRTY_OFFSET ((unsigned long)(&((struct sector_hdr_data *)0)->status_table.dirty))
+#define SECTOR_MAGIC_OFFSET ((unsigned long)(&((struct sector_hdr_data *)0)->magic))
+#define KV_HDR_DATA_SIZE (FDB_WG_ALIGN(sizeof(struct kv_hdr_data)))
+#define KV_MAGIC_OFFSET ((unsigned long)(&((struct kv_hdr_data *)0)->magic))
+#define KV_LEN_OFFSET ((unsigned long)(&((struct kv_hdr_data *)0)->len))
+#define KV_NAME_LEN_OFFSET ((unsigned long)(&((struct kv_hdr_data *)0)->name_len))
-#define db_name(db) (((fdb_db_t)db)->name)
-#define db_init_ok(db) (((fdb_db_t)db)->init_ok)
-#define db_sec_size(db) (((fdb_db_t)db)->sec_size)
-#define db_max_size(db) (((fdb_db_t)db)->max_size)
-#define db_oldest_addr(db) (((fdb_db_t)db)->oldest_addr)
+#define db_name(db) (((fdb_db_t)db)->name)
+#define db_init_ok(db) (((fdb_db_t)db)->init_ok)
+#define db_sec_size(db) (((fdb_db_t)db)->sec_size)
+#define db_max_size(db) (((fdb_db_t)db)->max_size)
+#define db_oldest_addr(db) (((fdb_db_t)db)->oldest_addr)
-#define db_lock(db) \
- do \
- { \
- if (((fdb_db_t)db)->lock) \
- ((fdb_db_t)db)->lock((fdb_db_t)db); \
- } while (0);
+#define db_lock(db) \
+ do { \
+ if (((fdb_db_t)db)->lock) ((fdb_db_t)db)->lock((fdb_db_t)db); \
+ } while(0);
-#define db_unlock(db) \
- do \
- { \
- if (((fdb_db_t)db)->unlock) \
- ((fdb_db_t)db)->unlock((fdb_db_t)db); \
- } while (0);
+#define db_unlock(db) \
+ do { \
+ if (((fdb_db_t)db)->unlock) ((fdb_db_t)db)->unlock((fdb_db_t)db); \
+ } while(0);
-#define VER_NUM_KV_NAME "__ver_num__"
+#define VER_NUM_KV_NAME "__ver_num__"
-struct sector_hdr_data
-{
- struct
- {
- uint8_t store[FDB_STORE_STATUS_TABLE_SIZE]; /**< sector store status @see fdb_sector_store_status_t */
- uint8_t dirty[FDB_DIRTY_STATUS_TABLE_SIZE]; /**< sector dirty status @see fdb_sector_dirty_status_t */
+struct sector_hdr_data {
+ struct {
+ uint8_t store[FDB_STORE_STATUS_TABLE_SIZE]; /**< sector store status @see fdb_sector_store_status_t */
+ uint8_t dirty[FDB_DIRTY_STATUS_TABLE_SIZE]; /**< sector dirty status @see fdb_sector_dirty_status_t */
} status_table;
- uint32_t magic; /**< magic word(`E`, `F`, `4`, `0`) */
- uint32_t combined; /**< the combined next sector number, default: not combined */
+ uint32_t magic; /**< magic word(`E`, `F`, `4`, `0`) */
+ uint32_t combined; /**< the combined next sector number, default: not combined */
uint32_t reserved;
#if (FDB_WRITE_GRAN == 64) || (FDB_WRITE_GRAN == 128)
- uint8_t padding[4]; /**< align padding for 64bit and 128bit write granularity */
+ uint8_t padding[4]; /**< align padding for 64bit and 128bit write granularity */
#endif
};
typedef struct sector_hdr_data *sector_hdr_data_t;
-struct kv_hdr_data
-{
- uint8_t status_table[KV_STATUS_TABLE_SIZE]; /**< KV node status, @see fdb_kv_status_t */
- uint32_t magic; /**< magic word(`K`, `V`, `0`, `0`) */
- uint32_t len; /**< KV node total length (header + name + value), must align by FDB_WRITE_GRAN */
- uint32_t crc32; /**< KV node crc32(name_len + data_len + name + value) */
- uint8_t name_len; /**< name length */
- uint32_t value_len; /**< value length */
+struct kv_hdr_data {
+ uint8_t status_table[KV_STATUS_TABLE_SIZE]; /**< KV node status, @see fdb_kv_status_t */
+ uint32_t magic; /**< magic word(`K`, `V`, `0`, `0`) */
+ uint32_t len; /**< KV node total length (header + name + value), must align by FDB_WRITE_GRAN */
+ uint32_t crc32; /**< KV node crc32(name_len + data_len + name + value) */
+ uint8_t name_len; /**< name length */
+ uint32_t value_len; /**< value length */
#if (FDB_WRITE_GRAN == 64)
- uint8_t padding[4]; /**< align padding for 64bit write granularity */
+ uint8_t padding[4]; /**< align padding for 64bit write granularity */
#endif
#if (FDB_WRITE_GRAN == 128)
- uint8_t padding[12]; /**< align padding for 128bit write granularity */
+ uint8_t padding[12]; /**< align padding for 128bit write granularity */
#endif
};
typedef struct kv_hdr_data *kv_hdr_data_t;
-struct alloc_kv_cb_args
-{
+struct alloc_kv_cb_args {
fdb_kvdb_t db;
size_t kv_size;
uint32_t *empty_kv;
};
-struct gc_cb_args
-{
+struct gc_cb_args {
fdb_kvdb_t db;
- size_t cur_free_size;
size_t setting_free_size;
- uint32_t traversed_len;
+ size_t last_gc_sec_addr;
};
static void gc_collect(fdb_kvdb_t db);
@@ -157,29 +149,21 @@ static void update_sector_cache(fdb_kvdb_t db, kv_sec_info_t sector)
{
size_t i, empty_index = FDB_SECTOR_CACHE_TABLE_SIZE;
- for (i = 0; i < FDB_SECTOR_CACHE_TABLE_SIZE; i++)
- {
+ for (i = 0; i < FDB_SECTOR_CACHE_TABLE_SIZE; i++) {
/* update the sector empty_addr in cache */
- if (db->sector_cache_table[i].addr == sector->addr)
- {
- if (sector->check_ok)
- {
+ if (db->sector_cache_table[i].addr == sector->addr) {
+ if (sector->check_ok) {
memcpy(&db->sector_cache_table[i], sector, sizeof(struct kvdb_sec_info));
- }
- else
- {
+ } else {
db->sector_cache_table[i].addr = FDB_DATA_UNUSED;
}
return;
- }
- else if (db->sector_cache_table[i].addr == FDB_DATA_UNUSED)
- {
+ } else if (db->sector_cache_table[i].addr == FDB_DATA_UNUSED) {
empty_index = i;
}
}
/* add the sector empty_addr to cache */
- if (sector->check_ok && empty_index < FDB_SECTOR_CACHE_TABLE_SIZE)
- {
+ if (sector->check_ok && empty_index < FDB_SECTOR_CACHE_TABLE_SIZE) {
memcpy(&db->sector_cache_table[empty_index], sector, sizeof(struct kvdb_sec_info));
}
}
@@ -191,10 +175,8 @@ static kv_sec_info_t get_sector_from_cache(fdb_kvdb_t db, uint32_t sec_addr)
{
size_t i;
- for (i = 0; i < FDB_SECTOR_CACHE_TABLE_SIZE; i++)
- {
- if (db->sector_cache_table[i].addr == sec_addr)
- {
+ for (i = 0; i < FDB_SECTOR_CACHE_TABLE_SIZE; i++) {
+ if (db->sector_cache_table[i].addr == sec_addr) {
return &db->sector_cache_table[i];
}
}
@@ -205,8 +187,7 @@ static kv_sec_info_t get_sector_from_cache(fdb_kvdb_t db, uint32_t sec_addr)
static void update_sector_empty_addr_cache(fdb_kvdb_t db, uint32_t sec_addr, uint32_t empty_addr)
{
kv_sec_info_t sector = get_sector_from_cache(db, sec_addr);
- if (sector)
- {
+ if (sector) {
sector->empty_kv = empty_addr;
sector->remain = db_sec_size(db) - (sector->empty_kv - sector->addr);
}
@@ -215,8 +196,7 @@ static void update_sector_empty_addr_cache(fdb_kvdb_t db, uint32_t sec_addr, uin
static void update_sector_status_store_cache(fdb_kvdb_t db, uint32_t sec_addr, fdb_sector_store_status_t stauts)
{
kv_sec_info_t sector = get_sector_from_cache(db, sec_addr);
- if (sector)
- {
+ if (sector) {
sector->status.store = stauts;
}
}
@@ -224,37 +204,26 @@ static void update_sector_status_store_cache(fdb_kvdb_t db, uint32_t sec_addr, f
static void update_kv_cache(fdb_kvdb_t db, const char *name, size_t name_len, uint32_t addr)
{
size_t i, empty_index = FDB_KV_CACHE_TABLE_SIZE, min_activity_index = FDB_KV_CACHE_TABLE_SIZE;
- uint16_t name_crc = (uint16_t)(fdb_calc_crc32(0, name, name_len) >> 16), min_activity = 0xFFFF;
+ uint16_t name_crc = (uint16_t) (fdb_calc_crc32(0, name, name_len) >> 16), min_activity = 0xFFFF;
- for (i = 0; i < FDB_KV_CACHE_TABLE_SIZE; i++)
- {
- if (addr != FDB_DATA_UNUSED)
- {
+ for (i = 0; i < FDB_KV_CACHE_TABLE_SIZE; i++) {
+ if (addr != FDB_DATA_UNUSED) {
/* update the KV address in cache */
- if (db->kv_cache_table[i].name_crc == name_crc)
- {
+ if (db->kv_cache_table[i].name_crc == name_crc) {
db->kv_cache_table[i].addr = addr;
return;
- }
- else if ((db->kv_cache_table[i].addr == FDB_DATA_UNUSED) && (empty_index == FDB_KV_CACHE_TABLE_SIZE))
- {
+ } else if ((db->kv_cache_table[i].addr == FDB_DATA_UNUSED) && (empty_index == FDB_KV_CACHE_TABLE_SIZE)) {
empty_index = i;
- }
- else if (db->kv_cache_table[i].addr != FDB_DATA_UNUSED)
- {
- if (db->kv_cache_table[i].active > 0)
- {
+ } else if (db->kv_cache_table[i].addr != FDB_DATA_UNUSED) {
+ if (db->kv_cache_table[i].active > 0) {
db->kv_cache_table[i].active--;
}
- if (db->kv_cache_table[i].active < min_activity)
- {
+ if (db->kv_cache_table[i].active < min_activity) {
min_activity_index = i;
min_activity = db->kv_cache_table[i].active;
}
}
- }
- else if (db->kv_cache_table[i].name_crc == name_crc)
- {
+ } else if (db->kv_cache_table[i].name_crc == name_crc) {
/* delete the KV */
db->kv_cache_table[i].addr = FDB_DATA_UNUSED;
db->kv_cache_table[i].active = 0;
@@ -262,14 +231,11 @@ static void update_kv_cache(fdb_kvdb_t db, const char *name, size_t name_len, ui
}
}
/* add the KV to cache, using LRU (Least Recently Used) like algorithm */
- if (empty_index < FDB_KV_CACHE_TABLE_SIZE)
- {
+ if (empty_index < FDB_KV_CACHE_TABLE_SIZE) {
db->kv_cache_table[empty_index].addr = addr;
db->kv_cache_table[empty_index].name_crc = name_crc;
db->kv_cache_table[empty_index].active = FDB_KV_CACHE_TABLE_SIZE;
- }
- else if (min_activity_index < FDB_KV_CACHE_TABLE_SIZE)
- {
+ } else if (min_activity_index < FDB_KV_CACHE_TABLE_SIZE) {
db->kv_cache_table[min_activity_index].addr = addr;
db->kv_cache_table[min_activity_index].name_crc = name_crc;
db->kv_cache_table[min_activity_index].active = FDB_KV_CACHE_TABLE_SIZE;
@@ -282,24 +248,18 @@ static void update_kv_cache(fdb_kvdb_t db, const char *name, size_t name_len, ui
static bool get_kv_from_cache(fdb_kvdb_t db, const char *name, size_t name_len, uint32_t *addr)
{
size_t i;
- uint16_t name_crc = (uint16_t)(fdb_calc_crc32(0, name, name_len) >> 16);
+ uint16_t name_crc = (uint16_t) (fdb_calc_crc32(0, name, name_len) >> 16);
- for (i = 0; i < FDB_KV_CACHE_TABLE_SIZE; i++)
- {
- if ((db->kv_cache_table[i].addr != FDB_DATA_UNUSED) && (db->kv_cache_table[i].name_crc == name_crc))
- {
- char saved_name[FDB_KV_NAME_MAX] = {0};
+ for (i = 0; i < FDB_KV_CACHE_TABLE_SIZE; i++) {
+ if ((db->kv_cache_table[i].addr != FDB_DATA_UNUSED) && (db->kv_cache_table[i].name_crc == name_crc)) {
+ char saved_name[FDB_KV_NAME_MAX] = { 0 };
/* read the KV name in flash */
- _fdb_flash_read((fdb_db_t)db, db->kv_cache_table[i].addr + KV_HDR_DATA_SIZE, (uint32_t *)saved_name, FDB_KV_NAME_MAX);
- if (!strncmp(name, saved_name, name_len))
- {
+ _fdb_flash_read((fdb_db_t)db, db->kv_cache_table[i].addr + KV_HDR_DATA_SIZE, (uint32_t *) saved_name, FDB_KV_NAME_MAX);
+ if (!strncmp(name, saved_name, name_len)) {
*addr = db->kv_cache_table[i].addr;
- if (db->kv_cache_table[i].active >= 0xFFFF - FDB_KV_CACHE_TABLE_SIZE)
- {
+ if (db->kv_cache_table[i].active >= 0xFFFF - FDB_KV_CACHE_TABLE_SIZE) {
db->kv_cache_table[i].active = 0xFFFF;
- }
- else
- {
+ } else {
db->kv_cache_table[i].active += FDB_KV_CACHE_TABLE_SIZE;
}
return true;
@@ -323,25 +283,21 @@ static uint32_t find_next_kv_addr(fdb_kvdb_t db, uint32_t start, uint32_t end)
#ifdef FDB_KV_USING_CACHE
kv_sec_info_t sector;
sector = get_sector_from_cache(db, FDB_ALIGN_DOWN(start, db_sec_size(db)));
- if (sector && start == sector->empty_kv)
- {
+ if (sector && start == sector->empty_kv) {
return FAILED_ADDR;
}
#endif /* FDB_KV_USING_CACHE */
- for (; start < end && start + sizeof(buf) < end; start += (sizeof(buf) - sizeof(uint32_t)))
- {
- if (_fdb_flash_read((fdb_db_t)db, start, (uint32_t *)buf, sizeof(buf)) != FDB_NO_ERR)
+ for (; start < end && start + sizeof(buf) < end; start += (sizeof(buf) - sizeof(uint32_t))) {
+ if (_fdb_flash_read((fdb_db_t)db, start, (uint32_t *) buf, sizeof(buf)) != FDB_NO_ERR)
return FAILED_ADDR;
- for (i = 0; i < sizeof(buf) - sizeof(uint32_t) && start + i < end; i++)
- {
-#ifndef FDB_BIG_ENDIAN /* Little Endian Order */
- magic = buf[i] + (buf[i + 1] << 8) + (buf[i + 2] << 16) + (buf[i + 3] << 24);
-#else /* Big Endian Order */
- magic = buf[i + 3] + (buf[i + 2] << 8) + (buf[i + 1] << 16) + (buf[i] << 24);
+ for (i = 0; i < sizeof(buf) - sizeof(uint32_t) && start + i < end; i++) {
+#ifndef FDB_BIG_ENDIAN /* Little Endian Order */
+ magic = buf[i] + ((uint32_t)buf[i + 1] << 8) + ((uint32_t)buf[i + 2] << 16) + ((uint32_t)buf[i + 3] << 24);
+#else /* Big Endian Order */
+ magic = buf[i + 3] + ((uint32_t)buf[i + 2] << 8) + ((uint32_t)buf[i + 1] << 16) + ((uint32_t)buf[i] << 24);
#endif
- if (magic == KV_MAGIC_WORD && (start + i - KV_MAGIC_OFFSET) >= start_bak)
- {
+ if (magic == KV_MAGIC_WORD && (start + i - KV_MAGIC_OFFSET) >= start_bak) {
return start + i - KV_MAGIC_OFFSET;
}
}
@@ -354,26 +310,18 @@ static uint32_t get_next_kv_addr(fdb_kvdb_t db, kv_sec_info_t sector, fdb_kv_t p
{
uint32_t addr = FAILED_ADDR;
- if (sector->status.store == FDB_SECTOR_STORE_EMPTY)
- {
+ if (sector->status.store == FDB_SECTOR_STORE_EMPTY) {
return FAILED_ADDR;
}
- if (pre_kv->addr.start == FAILED_ADDR)
- {
+ if (pre_kv->addr.start == FAILED_ADDR) {
/* the first KV address */
addr = sector->addr + SECTOR_HDR_DATA_SIZE;
- }
- else
- {
- if (pre_kv->addr.start <= sector->addr + db_sec_size(db))
- {
- if (pre_kv->crc_is_ok)
- {
+ } else {
+ if (pre_kv->addr.start <= sector->addr + db_sec_size(db)) {
+ if (pre_kv->crc_is_ok) {
addr = pre_kv->addr.start + pre_kv->len;
- }
- else
- {
+ } else {
/* when pre_kv CRC check failed, maybe the flash has error data
* find_next_kv_addr after pre_kv address */
addr = pre_kv->addr.start + FDB_WG_ALIGN(1);
@@ -381,14 +329,11 @@ static uint32_t get_next_kv_addr(fdb_kvdb_t db, kv_sec_info_t sector, fdb_kv_t p
/* check and find next KV address */
addr = find_next_kv_addr(db, addr, sector->addr + db_sec_size(db) - SECTOR_HDR_DATA_SIZE);
- if (addr == FAILED_ADDR || addr > sector->addr + db_sec_size(db) || pre_kv->len == 0)
- {
- // TODO Sector continuous mode
+ if (addr == FAILED_ADDR || addr > sector->addr + db_sec_size(db) || pre_kv->len == 0) {
+ //TODO Sector continuous mode
return FAILED_ADDR;
}
- }
- else
- {
+ } else {
/* no KV */
return FAILED_ADDR;
}
@@ -406,25 +351,21 @@ static fdb_err_t read_kv(fdb_kvdb_t db, fdb_kv_t kv)
size_t len, size;
/* read KV header raw data */
_fdb_flash_read((fdb_db_t)db, kv->addr.start, (uint32_t *)&kv_hdr, sizeof(struct kv_hdr_data));
- kv->status = (fdb_kv_status_t)_fdb_get_status(kv_hdr.status_table, FDB_KV_STATUS_NUM);
+ kv->status = (fdb_kv_status_t) _fdb_get_status(kv_hdr.status_table, FDB_KV_STATUS_NUM);
kv->len = kv_hdr.len;
- if (kv->len == UINT32_MAX || kv->len > db_max_size(db) || kv->len < KV_HDR_DATA_SIZE)
- {
+ if (kv->len == UINT32_MAX || kv->len > db_max_size(db) || kv->len < KV_HDR_DATA_SIZE) {
/* the KV length was not write, so reserved the info for current KV */
kv->len = KV_HDR_DATA_SIZE;
- if (kv->status != FDB_KV_ERR_HDR)
- {
+ if (kv->status != FDB_KV_ERR_HDR) {
kv->status = FDB_KV_ERR_HDR;
FDB_INFO("Error: The KV @0x%08" PRIX32 " length has an error.\n", kv->addr.start);
_fdb_write_status((fdb_db_t)db, kv->addr.start, kv_hdr.status_table, FDB_KV_STATUS_NUM, FDB_KV_ERR_HDR, true);
}
kv->crc_is_ok = false;
return FDB_READ_ERR;
- }
- else if (kv->len > db_sec_size(db) - SECTOR_HDR_DATA_SIZE && kv->len < db_max_size(db))
- {
- // TODO Sector continuous mode, or the write length is not written completely
+ } else if (kv->len > db_sec_size(db) - SECTOR_HDR_DATA_SIZE && kv->len < db_max_size(db)) {
+ //TODO Sector continuous mode, or the write length is not written completely
}
/* CRC32 data len(header.name_len + header.value_len + name + value), using sizeof(uint32_t) for compatible V1.x */
@@ -432,23 +373,18 @@ static fdb_err_t read_kv(fdb_kvdb_t db, fdb_kv_t kv)
calc_crc32 = fdb_calc_crc32(calc_crc32, &kv_hdr.value_len, sizeof(uint32_t));
crc_data_len = kv->len - KV_HDR_DATA_SIZE;
/* calculate the CRC32 value */
- for (len = 0, size = 0; len < crc_data_len; len += size)
- {
- if (len + sizeof(buf) < crc_data_len)
- {
+ for (len = 0, size = 0; len < crc_data_len; len += size) {
+ if (len + sizeof(buf) < crc_data_len) {
size = sizeof(buf);
- }
- else
- {
+ } else {
size = crc_data_len - len;
}
- _fdb_flash_read((fdb_db_t)db, kv->addr.start + KV_HDR_DATA_SIZE + len, (uint32_t *)buf, FDB_WG_ALIGN(size));
+ _fdb_flash_read((fdb_db_t)db, kv->addr.start + KV_HDR_DATA_SIZE + len, (uint32_t *) buf, FDB_WG_ALIGN(size));
calc_crc32 = fdb_calc_crc32(calc_crc32, buf, size);
}
/* check CRC32 */
- if (calc_crc32 != kv_hdr.crc32)
- {
+ if (calc_crc32 != kv_hdr.crc32) {
size_t name_len = kv_hdr.name_len > FDB_KV_NAME_MAX ? FDB_KV_NAME_MAX : kv_hdr.name_len;
kv->crc_is_ok = false;
result = FDB_READ_ERR;
@@ -456,19 +392,16 @@ static fdb_err_t read_kv(fdb_kvdb_t db, fdb_kv_t kv)
kv_name_addr = kv->addr.start + KV_HDR_DATA_SIZE;
_fdb_flash_read((fdb_db_t)db, kv_name_addr, (uint32_t *)kv->name, FDB_WG_ALIGN(name_len));
FDB_INFO("Error: Read the KV (%.*s@0x%08" PRIX32 ") CRC32 check failed!\n", name_len, kv->name, kv->addr.start);
- }
- else
- {
+ } else {
kv->crc_is_ok = true;
/* the name is behind aligned KV header */
kv_name_addr = kv->addr.start + KV_HDR_DATA_SIZE;
- _fdb_flash_read((fdb_db_t)db, kv_name_addr, (uint32_t *)kv->name, FDB_WG_ALIGN(kv_hdr.name_len));
+ _fdb_flash_read((fdb_db_t)db, kv_name_addr, (uint32_t *) kv->name, FDB_WG_ALIGN(kv_hdr.name_len));
/* the value is behind aligned name */
kv->addr.value = kv_name_addr + FDB_WG_ALIGN(kv_hdr.name_len);
kv->value_len = kv_hdr.value_len;
kv->name_len = kv_hdr.name_len;
- if (kv_hdr.name_len >= sizeof(kv->name) / sizeof(kv->name[0]))
- {
+ if (kv_hdr.name_len >= sizeof(kv->name) / sizeof(kv->name[0])) {
kv_hdr.name_len = sizeof(kv->name) / sizeof(kv->name[0]) - 1;
}
kv->name[kv_hdr.name_len] = '\0';
@@ -480,15 +413,14 @@ static fdb_err_t read_kv(fdb_kvdb_t db, fdb_kv_t kv)
static fdb_err_t read_sector_info(fdb_kvdb_t db, uint32_t addr, kv_sec_info_t sector, bool traversal)
{
fdb_err_t result = FDB_NO_ERR;
- struct sector_hdr_data sec_hdr = {0};
+ struct sector_hdr_data sec_hdr = { 0 };
FDB_ASSERT(addr % db_sec_size(db) == 0);
FDB_ASSERT(sector);
#ifdef FDB_KV_USING_CACHE
kv_sec_info_t sector_cache = get_sector_from_cache(db, addr);
- if (sector_cache && ((!traversal) || (traversal && sector_cache->empty_kv != FAILED_ADDR)))
- {
+ if (sector_cache && ((!traversal) || (traversal && sector_cache->empty_kv != FAILED_ADDR))) {
memcpy(sector, sector_cache, sizeof(struct kvdb_sec_info));
return result;
}
@@ -502,9 +434,8 @@ static fdb_err_t read_sector_info(fdb_kvdb_t db, uint32_t addr, kv_sec_info_t se
sector->addr = addr;
sector->magic = sec_hdr.magic;
/* check magic word and combined value */
- if (sector->magic != SECTOR_MAGIC_WORD ||
- (sec_hdr.combined != SECTOR_NOT_COMBINED && sec_hdr.combined != SECTOR_COMBINED))
- {
+ if (sector->magic != SECTOR_MAGIC_WORD ||
+ (sec_hdr.combined != SECTOR_NOT_COMBINED && sec_hdr.combined != SECTOR_COMBINED)) {
sector->check_ok = false;
sector->combined = SECTOR_NOT_COMBINED;
return FDB_INIT_FAILED;
@@ -512,30 +443,24 @@ static fdb_err_t read_sector_info(fdb_kvdb_t db, uint32_t addr, kv_sec_info_t se
sector->check_ok = true;
/* get other sector info */
sector->combined = sec_hdr.combined;
- sector->status.store = (fdb_sector_store_status_t)_fdb_get_status(sec_hdr.status_table.store, FDB_SECTOR_STORE_STATUS_NUM);
- sector->status.dirty = (fdb_sector_dirty_status_t)_fdb_get_status(sec_hdr.status_table.dirty, FDB_SECTOR_DIRTY_STATUS_NUM);
+ sector->status.store = (fdb_sector_store_status_t) _fdb_get_status(sec_hdr.status_table.store, FDB_SECTOR_STORE_STATUS_NUM);
+ sector->status.dirty = (fdb_sector_dirty_status_t) _fdb_get_status(sec_hdr.status_table.dirty, FDB_SECTOR_DIRTY_STATUS_NUM);
/* traversal all KV and calculate the remain space size */
- if (traversal)
- {
+ if (traversal) {
sector->remain = 0;
sector->empty_kv = sector->addr + SECTOR_HDR_DATA_SIZE;
- if (sector->status.store == FDB_SECTOR_STORE_EMPTY)
- {
+ if (sector->status.store == FDB_SECTOR_STORE_EMPTY) {
sector->remain = db_sec_size(db) - SECTOR_HDR_DATA_SIZE;
}
- else if (sector->status.store == FDB_SECTOR_STORE_USING)
- {
+ else if (sector->status.store == FDB_SECTOR_STORE_USING) {
struct fdb_kv kv_obj;
sector->remain = db_sec_size(db) - SECTOR_HDR_DATA_SIZE;
kv_obj.addr.start = sector->addr + SECTOR_HDR_DATA_SIZE;
- do
- {
+ do {
read_kv(db, &kv_obj);
- if (!kv_obj.crc_is_ok)
- {
- if (kv_obj.status != FDB_KV_PRE_WRITE && kv_obj.status != FDB_KV_ERR_HDR)
- {
+ if (!kv_obj.crc_is_ok) {
+ if (kv_obj.status != FDB_KV_PRE_WRITE && kv_obj.status != FDB_KV_ERR_HDR) {
sector->remain = 0;
result = FDB_READ_ERR;
break;
@@ -550,22 +475,19 @@ static fdb_err_t read_sector_info(fdb_kvdb_t db, uint32_t addr, kv_sec_info_t se
ff_addr = _fdb_continue_ff_addr((fdb_db_t)db, sector->empty_kv, sector->addr + db_sec_size(db));
/* check the flash data is clean */
- if (sector->empty_kv != ff_addr)
- {
+ if (sector->empty_kv != ff_addr) {
/* update the sector information */
sector->empty_kv = ff_addr;
sector->remain = db_sec_size(db) - (ff_addr - sector->addr);
}
}
+
}
#ifdef FDB_KV_USING_CACHE
update_sector_cache(db, sector);
- }
- else
- {
- kv_sec_info_t sector_cache = get_sector_from_cache(db, sector->addr);
- if (!sector_cache)
- {
+ } else {
+ kv_sec_info_t sec_cache = get_sector_from_cache(db, sector->addr);
+ if (!sec_cache) {
sector->empty_kv = FAILED_ADDR;
sector->remain = 0;
update_sector_cache(db, sector);
@@ -580,65 +502,50 @@ static uint32_t get_next_sector_addr(fdb_kvdb_t db, kv_sec_info_t pre_sec, uint3
{
uint32_t cur_block_size;
- if (pre_sec->combined == SECTOR_NOT_COMBINED)
- {
+ if (pre_sec->combined == SECTOR_NOT_COMBINED) {
cur_block_size = db_sec_size(db);
- }
- else
- {
+ } else {
cur_block_size = pre_sec->combined * db_sec_size(db);
}
- if (traversed_len + cur_block_size <= db_max_size(db))
- {
+ if (traversed_len + cur_block_size <= db_max_size(db)) {
/* if reach to the end, roll back to the first sector */
- if (pre_sec->addr + cur_block_size < db_max_size(db))
- {
+ if (pre_sec->addr + cur_block_size < db_max_size(db)) {
return pre_sec->addr + cur_block_size;
- }
- else
- {
+ } else {
/* the next sector is on the top of the database */
return 0;
}
- }
- else
- {
+ } else {
/* finished */
return FAILED_ADDR;
}
}
static void kv_iterator(fdb_kvdb_t db, fdb_kv_t kv, void *arg1, void *arg2,
- bool (*callback)(fdb_kv_t kv, void *arg1, void *arg2))
+ bool (*callback)(fdb_kv_t kv, void *arg1, void *arg2))
{
struct kvdb_sec_info sector;
uint32_t sec_addr, traversed_len = 0;
sec_addr = db_oldest_addr(db);
/* search all sectors */
- do
- {
+ do {
traversed_len += db_sec_size(db);
- if (read_sector_info(db, sec_addr, §or, false) != FDB_NO_ERR)
- {
+ if (read_sector_info(db, sec_addr, §or, false) != FDB_NO_ERR) {
continue;
}
- if (callback == NULL)
- {
+ if (callback == NULL) {
continue;
}
/* sector has KV */
- if (sector.status.store == FDB_SECTOR_STORE_USING || sector.status.store == FDB_SECTOR_STORE_FULL)
- {
+ if (sector.status.store == FDB_SECTOR_STORE_USING || sector.status.store == FDB_SECTOR_STORE_FULL) {
kv->addr.start = sector.addr + SECTOR_HDR_DATA_SIZE;
/* search all KV */
- do
- {
+ do {
read_kv(db, kv);
/* iterator is interrupted when callback return true */
- if (callback(kv, arg1, arg2))
- {
+ if (callback(kv, arg1, arg2)) {
return;
}
} while ((kv->addr.start = get_next_kv_addr(db, §or, kv)) != FAILED_ADDR);
@@ -652,13 +559,11 @@ static bool find_kv_cb(fdb_kv_t kv, void *arg1, void *arg2)
bool *find_ok = arg2;
size_t key_len = strlen(key);
- if (key_len != kv->name_len)
- {
+ if (key_len != kv->name_len) {
return false;
}
/* check KV */
- if (kv->crc_is_ok && kv->status == FDB_KV_WRITE && !strncmp(kv->name, key, key_len))
- {
+ if (kv->crc_is_ok && kv->status == FDB_KV_WRITE && !strncmp(kv->name, key, key_len)) {
*find_ok = true;
return true;
}
@@ -681,8 +586,7 @@ static bool find_kv(fdb_kvdb_t db, const char *key, fdb_kv_t kv)
#ifdef FDB_KV_USING_CACHE
size_t key_len = strlen(key);
- if (get_kv_from_cache(db, key, key_len, &kv->addr.start))
- {
+ if (get_kv_from_cache(db, key, key_len, &kv->addr.start)) {
read_kv(db, kv);
return true;
}
@@ -691,8 +595,7 @@ static bool find_kv(fdb_kvdb_t db, const char *key, fdb_kv_t kv)
find_ok = find_kv_no_cache(db, key, kv);
#ifdef FDB_KV_USING_CACHE
- if (find_ok)
- {
+ if (find_ok) {
update_kv_cache(db, key, key_len, kv->addr.start);
}
#endif /* FDB_KV_USING_CACHE */
@@ -702,13 +605,11 @@ static bool find_kv(fdb_kvdb_t db, const char *key, fdb_kv_t kv)
static bool fdb_is_str(uint8_t *value, size_t len)
{
-#define __is_print(ch) ((unsigned int)((ch) - ' ') < 127u - ' ')
+#define __is_print(ch) ((unsigned int)((ch) - ' ') < 127u - ' ')
size_t i;
- for (i = 0; i < len; i++)
- {
- if (!__is_print(value[i]))
- {
+ for (i = 0; i < len; i++) {
+ if (!__is_print(value[i])) {
return false;
}
}
@@ -720,27 +621,19 @@ static size_t get_kv(fdb_kvdb_t db, const char *key, void *value_buf, size_t buf
struct fdb_kv kv;
size_t read_len = 0;
- if (find_kv(db, key, &kv))
- {
- if (value_len)
- {
+ if (find_kv(db, key, &kv)) {
+ if (value_len) {
*value_len = kv.value_len;
}
- if (buf_len > kv.value_len)
- {
+ if (buf_len > kv.value_len) {
read_len = kv.value_len;
- }
- else
- {
+ } else {
read_len = buf_len;
}
- if (value_buf)
- {
- _fdb_flash_read((fdb_db_t)db, kv.addr.value, (uint32_t *)value_buf, read_len);
+ if (value_buf){
+ _fdb_flash_read((fdb_db_t)db, kv.addr.value, (uint32_t *) value_buf, read_len);
}
- }
- else if (value_len)
- {
+ } else if (value_len) {
*value_len = 0;
}
@@ -760,8 +653,7 @@ fdb_kv_t fdb_kv_get_obj(fdb_kvdb_t db, const char *key, fdb_kv_t kv)
{
bool find_ok = false;
- if (!db_init_ok(db))
- {
+ if (!db_init_ok(db)) {
FDB_INFO("Error: KV (%s) isn't initialize OK.\n", db_name(db));
return 0;
}
@@ -807,8 +699,7 @@ size_t fdb_kv_get_blob(fdb_kvdb_t db, const char *key, fdb_blob_t blob)
{
size_t read_len = 0;
- if (!db_init_ok(db))
- {
+ if (!db_init_ok(db)) {
FDB_INFO("Error: KV (%s) isn't initialize OK.\n", db_name(db));
return 0;
}
@@ -841,21 +732,15 @@ char *fdb_kv_get(fdb_kvdb_t db, const char *key)
size_t get_size;
struct fdb_blob blob;
- if ((get_size = fdb_kv_get_blob(db, key, fdb_blob_make(&blob, value, FDB_STR_KV_VALUE_MAX_SIZE))) > 0)
- {
+ if ((get_size = fdb_kv_get_blob(db, key, fdb_blob_make(&blob, value, FDB_STR_KV_VALUE_MAX_SIZE))) > 0) {
/* the return value must be string */
- if (fdb_is_str((uint8_t *)value, get_size))
- {
+ if (fdb_is_str((uint8_t *)value, get_size)) {
value[get_size] = '\0';
return value;
- }
- else if (blob.saved.len > FDB_STR_KV_VALUE_MAX_SIZE)
- {
+ } else if (blob.saved.len > FDB_STR_KV_VALUE_MAX_SIZE) {
FDB_INFO("Warning: The default string KV value buffer length (%" PRIdLEAST16 ") is too less (%" PRIu32 ").\n", FDB_STR_KV_VALUE_MAX_SIZE,
- (uint32_t)blob.saved.len);
- }
- else
- {
+ (uint32_t)blob.saved.len);
+ } else {
FDB_INFO("Warning: The KV value isn't string. Could not be returned\n");
return NULL;
}
@@ -869,8 +754,7 @@ static fdb_err_t write_kv_hdr(fdb_kvdb_t db, uint32_t addr, kv_hdr_data_t kv_hdr
fdb_err_t result = FDB_NO_ERR;
/* write the status will by write granularity */
result = _fdb_write_status((fdb_db_t)db, addr, kv_hdr->status_table, FDB_KV_STATUS_NUM, FDB_KV_PRE_WRITE, false);
- if (result != FDB_NO_ERR)
- {
+ if (result != FDB_NO_ERR) {
return result;
}
/* write other header data */
@@ -882,13 +766,12 @@ static fdb_err_t write_kv_hdr(fdb_kvdb_t db, uint32_t addr, kv_hdr_data_t kv_hdr
static fdb_err_t format_sector(fdb_kvdb_t db, uint32_t addr, uint32_t combined_value)
{
fdb_err_t result = FDB_NO_ERR;
- struct sector_hdr_data sec_hdr = {0};
+ struct sector_hdr_data sec_hdr = { 0 };
FDB_ASSERT(addr % db_sec_size(db) == 0);
result = _fdb_flash_erase((fdb_db_t)db, addr, db_sec_size(db));
- if (result == FDB_NO_ERR)
- {
+ if (result == FDB_NO_ERR) {
/* initialize the header data */
memset(&sec_hdr, FDB_BYTE_ERASED, sizeof(struct sector_hdr_data));
#if (FDB_WRITE_GRAN == 1)
@@ -899,8 +782,8 @@ static fdb_err_t format_sector(fdb_kvdb_t db, uint32_t addr, uint32_t combined_v
sec_hdr.reserved = FDB_DATA_UNUSED;
/* save the header */
result = _fdb_flash_write((fdb_db_t)db, addr, (uint32_t *)&sec_hdr, SECTOR_HDR_DATA_SIZE, true);
-#else // seperate the whole "sec_hdr" program to serval sinle program operation to prevent re-program issue on STM32L4xx or
- // other MCU internal flash
+#else // seperate the whole "sec_hdr" program to serval sinle program operation to prevent re-program issue on STM32L4xx or
+ // other MCU internal flash
/* write the sector store status */
_fdb_write_status((fdb_db_t)db,
addr + SECTOR_STORE_OFFSET,
@@ -930,7 +813,7 @@ static fdb_err_t format_sector(fdb_kvdb_t db, uint32_t addr, uint32_t combined_v
#ifdef FDB_KV_USING_CACHE
{
- struct kvdb_sec_info sector = {.addr = addr, .check_ok = false, .empty_kv = FAILED_ADDR};
+ struct kvdb_sec_info sector = {.addr = addr, .check_ok = false, .empty_kv = FAILED_ADDR };
/* delete the sector cache */
update_sector_cache(db, §or);
}
@@ -945,20 +828,17 @@ static fdb_err_t update_sec_status(fdb_kvdb_t db, kv_sec_info_t sector, size_t n
uint8_t status_table[FDB_STORE_STATUS_TABLE_SIZE];
fdb_err_t result = FDB_NO_ERR;
/* change the current sector status */
- if (sector->status.store == FDB_SECTOR_STORE_EMPTY)
- {
+ if (sector->status.store == FDB_SECTOR_STORE_EMPTY) {
/* change the sector status to using */
result = _fdb_write_status((fdb_db_t)db, sector->addr, status_table, FDB_SECTOR_STORE_STATUS_NUM, FDB_SECTOR_STORE_USING, true);
#ifdef FDB_KV_USING_CACHE
update_sector_status_store_cache(db, sector->addr, FDB_SECTOR_STORE_USING);
#endif /* FDB_KV_USING_CACHE */
- }
- else if (sector->status.store == FDB_SECTOR_STORE_USING)
- {
+
+ } else if (sector->status.store == FDB_SECTOR_STORE_USING) {
/* check remain size */
- if (sector->remain < FDB_SEC_REMAIN_THRESHOLD || sector->remain - new_kv_len < FDB_SEC_REMAIN_THRESHOLD)
- {
+ if (sector->remain < FDB_SEC_REMAIN_THRESHOLD || sector->remain - new_kv_len < FDB_SEC_REMAIN_THRESHOLD) {
/* change the sector status to full */
result = _fdb_write_status((fdb_db_t)db, sector->addr, status_table, FDB_SECTOR_STORE_STATUS_NUM, FDB_SECTOR_STORE_FULL, true);
@@ -966,13 +846,10 @@ static fdb_err_t update_sec_status(fdb_kvdb_t db, kv_sec_info_t sector, size_t n
update_sector_status_store_cache(db, sector->addr, FDB_SECTOR_STORE_FULL);
#endif /* FDB_KV_USING_CACHE */
- if (is_full)
- {
+ if (is_full) {
*is_full = true;
}
- }
- else if (is_full)
- {
+ } else if (is_full) {
*is_full = false;
}
}
@@ -981,25 +858,21 @@ static fdb_err_t update_sec_status(fdb_kvdb_t db, kv_sec_info_t sector, size_t n
}
static void sector_iterator(fdb_kvdb_t db, kv_sec_info_t sector, fdb_sector_store_status_t status, void *arg1, void *arg2,
- bool (*callback)(kv_sec_info_t sector, void *arg1, void *arg2), bool traversal_kv)
+ bool (*callback)(kv_sec_info_t sector, void *arg1, void *arg2), bool traversal_kv)
{
uint32_t sec_addr, traversed_len = 0;
/* search all sectors */
sec_addr = db_oldest_addr(db);
- do
- {
+ do {
traversed_len += db_sec_size(db);
read_sector_info(db, sec_addr, sector, false);
- if (status == FDB_SECTOR_STORE_UNUSED || status == sector->status.store)
- {
- if (traversal_kv)
- {
+ if (status == FDB_SECTOR_STORE_UNUSED || status == sector->status.store) {
+ if (traversal_kv) {
read_sector_info(db, sec_addr, sector, true);
}
/* iterator is interrupted when callback return true */
- if (callback && callback(sector, arg1, arg2))
- {
+ if (callback && callback(sector, arg1, arg2)) {
return;
}
}
@@ -1010,12 +883,9 @@ static bool sector_statistics_cb(kv_sec_info_t sector, void *arg1, void *arg2)
{
size_t *empty_sector = arg1, *using_sector = arg2;
- if (sector->check_ok && sector->status.store == FDB_SECTOR_STORE_EMPTY)
- {
+ if (sector->check_ok && sector->status.store == FDB_SECTOR_STORE_EMPTY) {
(*empty_sector)++;
- }
- else if (sector->check_ok && sector->status.store == FDB_SECTOR_STORE_USING)
- {
+ } else if (sector->check_ok && sector->status.store == FDB_SECTOR_STORE_USING) {
(*using_sector)++;
}
@@ -1029,8 +899,9 @@ static bool alloc_kv_cb(kv_sec_info_t sector, void *arg1, void *arg2)
/* 1. sector has space
* 2. the NO dirty sector
* 3. the dirty sector only when the gc_request is false */
- if (sector->check_ok && sector->remain > arg->kv_size + FDB_SEC_REMAIN_THRESHOLD && ((sector->status.dirty == FDB_SECTOR_DIRTY_FALSE) || (sector->status.dirty == FDB_SECTOR_DIRTY_TRUE && !arg->db->gc_request)))
- {
+ if (sector->check_ok && sector->remain > arg->kv_size + FDB_SEC_REMAIN_THRESHOLD
+ && ((sector->status.dirty == FDB_SECTOR_DIRTY_FALSE)
+ || (sector->status.dirty == FDB_SECTOR_DIRTY_TRUE && !arg->db->gc_request))) {
*(arg->empty_kv) = sector->empty_kv;
return true;
}
@@ -1046,19 +917,14 @@ static uint32_t alloc_kv(fdb_kvdb_t db, kv_sec_info_t sector, size_t kv_size)
/* sector status statistics */
sector_iterator(db, sector, FDB_SECTOR_STORE_UNUSED, &empty_sector, &using_sector, sector_statistics_cb, false);
- if (using_sector > 0)
- {
+ if (using_sector > 0) {
/* alloc the KV from the using status sector first */
sector_iterator(db, sector, FDB_SECTOR_STORE_USING, &arg, NULL, alloc_kv_cb, true);
}
- if (empty_sector > 0 && empty_kv == FAILED_ADDR)
- {
- if (empty_sector > FDB_GC_EMPTY_SEC_THRESHOLD || db->gc_request)
- {
+ if (empty_sector > 0 && empty_kv == FAILED_ADDR) {
+ if (empty_sector > FDB_GC_EMPTY_SEC_THRESHOLD || db->gc_request) {
sector_iterator(db, sector, FDB_SECTOR_STORE_EMPTY, &arg, NULL, alloc_kv_cb, true);
- }
- else
- {
+ } else {
/* no space for new KV now will GC and retry */
FDB_DEBUG("Trigger a GC check after alloc KV failed.\n");
db->gc_request = true;
@@ -1072,7 +938,7 @@ static fdb_err_t del_kv(fdb_kvdb_t db, const char *key, fdb_kv_t old_kv, bool co
{
fdb_err_t result = FDB_NO_ERR;
uint32_t dirty_status_addr;
- struct fdb_kv kv = {.status = FDB_KV_UNUSED};
+ struct fdb_kv kv = { .status = FDB_KV_UNUSED };
#if (KV_STATUS_TABLE_SIZE >= FDB_DIRTY_STATUS_TABLE_SIZE)
uint8_t status_table[KV_STATUS_TABLE_SIZE];
@@ -1081,40 +947,29 @@ static fdb_err_t del_kv(fdb_kvdb_t db, const char *key, fdb_kv_t old_kv, bool co
#endif
/* need find KV */
- if (!old_kv)
- {
+ if (!old_kv) {
/* find KV */
- if (find_kv(db, key, &kv))
- {
+ if (find_kv(db, key, &kv)) {
old_kv = &kv;
- }
- else
- {
+ } else {
FDB_DEBUG("Not found '%s' in KV.\n", key);
return FDB_KV_NAME_ERR;
}
}
/* change and save the new status */
- if (!complete_del)
- {
+ if (!complete_del) {
result = _fdb_write_status((fdb_db_t)db, old_kv->addr.start, status_table, FDB_KV_STATUS_NUM, FDB_KV_PRE_DELETE, false);
db->last_is_complete_del = true;
- }
- else
- {
+ } else {
result = _fdb_write_status((fdb_db_t)db, old_kv->addr.start, status_table, FDB_KV_STATUS_NUM, FDB_KV_DELETED, true);
- if (!db->last_is_complete_del && result == FDB_NO_ERR)
- {
+ if (!db->last_is_complete_del && result == FDB_NO_ERR) {
#ifdef FDB_KV_USING_CACHE
/* delete the KV in flash and cache */
- if (key != NULL)
- {
+ if (key != NULL) {
/* when using del_kv(db, key, NULL, true) or del_kv(db, key, kv, true) in fdb_del_kv(db, ) and set_kv(db, ) */
update_kv_cache(db, key, strlen(key), FDB_DATA_UNUSED);
- }
- else if (old_kv != NULL)
- {
+ } else if (old_kv != NULL) {
/* when using del_kv(db, NULL, kv, true) in move_kv(db, ) */
update_kv_cache(db, old_kv->name, old_kv->name_len, FDB_DATA_UNUSED);
}
@@ -1126,14 +981,13 @@ static fdb_err_t del_kv(fdb_kvdb_t db, const char *key, fdb_kv_t old_kv, bool co
dirty_status_addr = FDB_ALIGN_DOWN(old_kv->addr.start, db_sec_size(db)) + SECTOR_DIRTY_OFFSET;
/* read and change the sector dirty status */
- if (result == FDB_NO_ERR && _fdb_read_status((fdb_db_t)db, dirty_status_addr, status_table, FDB_SECTOR_DIRTY_STATUS_NUM) == FDB_SECTOR_DIRTY_FALSE)
- {
+ if (result == FDB_NO_ERR
+ && _fdb_read_status((fdb_db_t)db, dirty_status_addr, status_table, FDB_SECTOR_DIRTY_STATUS_NUM) == FDB_SECTOR_DIRTY_FALSE) {
result = _fdb_write_status((fdb_db_t)db, dirty_status_addr, status_table, FDB_SECTOR_DIRTY_STATUS_NUM, FDB_SECTOR_DIRTY_TRUE, true);
#ifdef FDB_KV_USING_CACHE
{
kv_sec_info_t sector_cache = get_sector_from_cache(db, FDB_ALIGN_DOWN(old_kv->addr.start, db_sec_size(db)));
- if (sector_cache)
- {
+ if (sector_cache) {
sector_cache->status.dirty = FDB_SECTOR_DIRTY_TRUE;
}
}
@@ -1154,29 +1008,23 @@ static fdb_err_t move_kv(fdb_kvdb_t db, fdb_kv_t kv)
struct kvdb_sec_info sector;
/* prepare to delete the current KV */
- if (kv->status == FDB_KV_WRITE)
- {
+ if (kv->status == FDB_KV_WRITE) {
del_kv(db, NULL, kv, false);
}
- if ((kv_addr = alloc_kv(db, §or, kv->len)) != FAILED_ADDR)
- {
- if (db->in_recovery_check && kv->status == FDB_KV_PRE_DELETE)
- {
+ if ((kv_addr = alloc_kv(db, §or, kv->len)) != FAILED_ADDR) {
+ if (db->in_recovery_check && kv->status == FDB_KV_PRE_DELETE) {
struct fdb_kv kv_bak;
- char name[FDB_KV_NAME_MAX + 1] = {0};
+ char name[FDB_KV_NAME_MAX + 1] = { 0 };
strncpy(name, kv->name, kv->name_len);
/* check the KV in flash is already create success */
- if (find_kv_no_cache(db, name, &kv_bak))
- {
+ if (find_kv_no_cache(db, name, &kv_bak)) {
/* already create success, don't need to duplicate */
result = FDB_NO_ERR;
goto __exit;
}
}
- }
- else
- {
+ } else {
return FDB_SAVED_FULL;
}
/* start move the KV */
@@ -1189,24 +1037,20 @@ static fdb_err_t move_kv(fdb_kvdb_t db, fdb_kv_t kv)
_fdb_write_status((fdb_db_t)db, kv_addr, status_table, FDB_KV_STATUS_NUM, FDB_KV_PRE_WRITE, false);
kv_len -= KV_MAGIC_OFFSET;
- for (len = 0, size = 0; len < kv_len; len += size)
- {
- if (len + sizeof(buf) < kv_len)
- {
+ for (len = 0, size = 0; len < kv_len; len += size) {
+ if (len + sizeof(buf) < kv_len) {
size = sizeof(buf);
- }
- else
- {
+ } else {
size = kv_len - len;
}
- _fdb_flash_read((fdb_db_t)db, kv->addr.start + KV_MAGIC_OFFSET + len, (uint32_t *)buf, FDB_WG_ALIGN(size));
- result = _fdb_flash_write((fdb_db_t)db, kv_addr + KV_MAGIC_OFFSET + len, (uint32_t *)buf, size, true);
+ _fdb_flash_read((fdb_db_t)db, kv->addr.start + KV_MAGIC_OFFSET + len, (uint32_t *) buf, FDB_WG_ALIGN(size));
+ result = _fdb_flash_write((fdb_db_t)db, kv_addr + KV_MAGIC_OFFSET + len, (uint32_t *) buf, size, true);
}
_fdb_write_status((fdb_db_t)db, kv_addr, status_table, FDB_KV_STATUS_NUM, FDB_KV_WRITE, true);
#ifdef FDB_KV_USING_CACHE
update_sector_empty_addr_cache(db, FDB_ALIGN_DOWN(kv_addr, db_sec_size(db)),
- kv_addr + KV_HDR_DATA_SIZE + FDB_WG_ALIGN(kv->name_len) + FDB_WG_ALIGN(kv->value_len));
+ kv_addr + KV_HDR_DATA_SIZE + FDB_WG_ALIGN(kv->name_len) + FDB_WG_ALIGN(kv->value_len));
update_kv_cache(db, kv->name, kv->name_len, kv_addr);
#endif /* FDB_KV_USING_CACHE */
}
@@ -1226,17 +1070,13 @@ static uint32_t new_kv(fdb_kvdb_t db, kv_sec_info_t sector, size_t kv_size)
__retry:
- if ((empty_kv = alloc_kv(db, sector, kv_size)) == FAILED_ADDR)
- {
- if (db->gc_request && !already_gc)
- {
- FDB_INFO("Warning: Alloc an KV (size %" PRIu32 ") failed when new KV. Now will GC then retry.\n", (uint32_t)kv_size);
+ if ((empty_kv = alloc_kv(db, sector, kv_size)) == FAILED_ADDR) {
+ if (db->gc_request && !already_gc) {
+ FDB_DEBUG("Alloc an KV (size %" PRIu32 ") failed when new KV. Now will GC then retry.\n", (uint32_t)kv_size);
gc_collect_by_free_size(db, kv_size);
already_gc = true;
goto __retry;
- }
- else if (already_gc)
- {
+ } else if (already_gc) {
FDB_INFO("Error: Alloc an KV (size %" PRIuLEAST16 ") failed after GC. KV full.\n", kv_size);
db->gc_request = false;
}
@@ -1254,14 +1094,16 @@ static uint32_t new_kv_ex(fdb_kvdb_t db, kv_sec_info_t sector, size_t key_len, s
static bool gc_check_cb(kv_sec_info_t sector, void *arg1, void *arg2)
{
- size_t *empty_sec = arg1;
+ size_t *empty_sec_num = arg1;
+ uint32_t *empty_sec_addr = arg2;
- if (sector->check_ok)
- {
- *empty_sec = *empty_sec + 1;
+ if (sector->check_ok) {
+ *empty_sec_num = *empty_sec_num + 1;
+ *empty_sec_addr = sector->addr;
}
return false;
+
}
static bool do_gc(kv_sec_info_t sector, void *arg1, void *arg2)
@@ -1269,33 +1111,37 @@ static bool do_gc(kv_sec_info_t sector, void *arg1, void *arg2)
struct fdb_kv kv;
struct gc_cb_args *gc = (struct gc_cb_args *)arg1;
fdb_kvdb_t db = gc->db;
+ uint32_t last_gc_sec_addr = 0;
- if (sector->check_ok && (sector->status.dirty == FDB_SECTOR_DIRTY_TRUE || sector->status.dirty == FDB_SECTOR_DIRTY_GC))
- {
+ if (sector->check_ok && (sector->status.dirty == FDB_SECTOR_DIRTY_TRUE || sector->status.dirty == FDB_SECTOR_DIRTY_GC)) {
uint8_t status_table[FDB_DIRTY_STATUS_TABLE_SIZE];
/* change the sector status to GC */
_fdb_write_status((fdb_db_t)db, sector->addr + SECTOR_DIRTY_OFFSET, status_table, FDB_SECTOR_DIRTY_STATUS_NUM, FDB_SECTOR_DIRTY_GC, true);
/* search all KV */
kv.addr.start = sector->addr + SECTOR_HDR_DATA_SIZE;
- do
- {
+ do {
read_kv(db, &kv);
- if (kv.crc_is_ok && (kv.status == FDB_KV_WRITE || kv.status == FDB_KV_PRE_DELETE))
- {
+ if (kv.crc_is_ok && (kv.status == FDB_KV_WRITE || kv.status == FDB_KV_PRE_DELETE)) {
/* move the KV to new space */
- if (move_kv(db, &kv) != FDB_NO_ERR)
- {
+ if (move_kv(db, &kv) != FDB_NO_ERR) {
FDB_INFO("Error: Moved the KV (%.*s) for GC failed.\n", kv.name_len, kv.name);
}
+ } else {
+ FDB_DEBUG("KV (%.*s) is garbage NOT need move, collect it.\n", kv.name_len, kv.name);
}
} while ((kv.addr.start = get_next_kv_addr(db, sector, &kv)) != FAILED_ADDR);
format_sector(db, sector->addr, SECTOR_NOT_COMBINED);
- gc->cur_free_size += db_sec_size(db) - SECTOR_HDR_DATA_SIZE;
- FDB_DEBUG("Collect a sector @0x%08" PRIX32 "\n", sector->addr);
+ last_gc_sec_addr = gc->last_gc_sec_addr;
+ gc->last_gc_sec_addr = sector->addr;
/* update oldest_addr for next GC sector format */
db_oldest_addr(db) = get_next_sector_addr(db, sector, 0);
- if (gc->cur_free_size >= gc->setting_free_size)
- return true;
+ FDB_DEBUG("Collect a sector @0x%08" PRIX32 "\n", sector->addr);
+ /* the collect new space is in last GC sector */
+ struct kvdb_sec_info last_gc_sector;
+ if (read_sector_info(db, last_gc_sec_addr, &last_gc_sector, true) == FDB_NO_ERR) {
+ if (last_gc_sector.remain > gc->setting_free_size)
+ return true;
+ }
}
return false;
@@ -1304,16 +1150,17 @@ static bool do_gc(kv_sec_info_t sector, void *arg1, void *arg2)
static void gc_collect_by_free_size(fdb_kvdb_t db, size_t free_size)
{
struct kvdb_sec_info sector;
- size_t empty_sec = 0;
- struct gc_cb_args arg = {db, 0, free_size, 0};
+ size_t empty_sec_num = 0;
+ /* an empty sector address */
+ uint32_t empty_sec_addr = 0;
/* GC check the empty sector number */
- sector_iterator(db, §or, FDB_SECTOR_STORE_EMPTY, &empty_sec, NULL, gc_check_cb, false);
+ sector_iterator(db, §or, FDB_SECTOR_STORE_EMPTY, &empty_sec_num, &empty_sec_addr, gc_check_cb, false);
/* do GC collect */
- FDB_DEBUG("The remain empty sector is %" PRIu32 ", GC threshold is %" PRIdLEAST16 ".\n", (uint32_t)empty_sec, FDB_GC_EMPTY_SEC_THRESHOLD);
- if (empty_sec <= FDB_GC_EMPTY_SEC_THRESHOLD)
- {
+ FDB_DEBUG("The remain empty sector is %" PRIu32 ", GC threshold is %" PRIdLEAST16 ".\n", (uint32_t)empty_sec_num, FDB_GC_EMPTY_SEC_THRESHOLD);
+ if (empty_sec_num <= FDB_GC_EMPTY_SEC_THRESHOLD) {
+ struct gc_cb_args arg = { db, free_size, empty_sec_addr };
sector_iterator(db, §or, FDB_SECTOR_STORE_UNUSED, &arg, NULL, do_gc, false);
}
@@ -1345,14 +1192,13 @@ static fdb_err_t align_write(fdb_kvdb_t db, uint32_t addr, const uint32_t *buf,
#endif
memset(align_data, FDB_BYTE_ERASED, align_data_size);
- result = _fdb_flash_write((fdb_db_t)db, addr, buf, FDB_WG_ALIGN_DOWN(size), false);
+ result = _fdb_flash_write((fdb_db_t) db, addr, buf, FDB_WG_ALIGN_DOWN(size), false);
align_remain = size - FDB_WG_ALIGN_DOWN(size);
- if (result == FDB_NO_ERR && align_remain)
- {
- memcpy(align_data, (uint8_t *)buf + FDB_WG_ALIGN_DOWN(size), align_remain);
- result = _fdb_flash_write((fdb_db_t)db, addr + FDB_WG_ALIGN_DOWN(size), (uint32_t *)align_data,
- align_data_size, false);
+ if (result == FDB_NO_ERR && align_remain) {
+ memcpy(align_data, (uint8_t *) buf + FDB_WG_ALIGN_DOWN(size), align_remain);
+ result = _fdb_flash_write((fdb_db_t) db, addr + FDB_WG_ALIGN_DOWN(size), (uint32_t *) align_data,
+ align_data_size, false);
}
return result;
@@ -1365,8 +1211,7 @@ static fdb_err_t create_kv_blob(fdb_kvdb_t db, kv_sec_info_t sector, const char
bool is_full = false;
uint32_t kv_addr = sector->empty_kv;
- if (strlen(key) > FDB_KV_NAME_MAX)
- {
+ if (strlen(key) > FDB_KV_NAME_MAX) {
FDB_INFO("Error: The KV name length is more than %d\n", FDB_KV_NAME_MAX);
return FDB_KV_NAME_ERR;
}
@@ -1377,22 +1222,18 @@ static fdb_err_t create_kv_blob(fdb_kvdb_t db, kv_sec_info_t sector, const char
kv_hdr.value_len = len;
kv_hdr.len = KV_HDR_DATA_SIZE + FDB_WG_ALIGN(kv_hdr.name_len) + FDB_WG_ALIGN(kv_hdr.value_len);
- if (kv_hdr.len > db_sec_size(db) - SECTOR_HDR_DATA_SIZE)
- {
+ if (kv_hdr.len > db_sec_size(db) - SECTOR_HDR_DATA_SIZE) {
FDB_INFO("Error: The KV size is too big\n");
return FDB_SAVED_FULL;
}
- if (kv_addr != FAILED_ADDR || (kv_addr = new_kv(db, sector, kv_hdr.len)) != FAILED_ADDR)
- {
+ if (kv_addr != FAILED_ADDR || (kv_addr = new_kv(db, sector, kv_hdr.len)) != FAILED_ADDR) {
size_t align_remain;
/* update the sector status */
- if (result == FDB_NO_ERR)
- {
+ if (result == FDB_NO_ERR) {
result = update_sec_status(db, sector, kv_hdr.len, &is_full);
}
- if (result == FDB_NO_ERR)
- {
+ if (result == FDB_NO_ERR) {
uint8_t ff = FDB_BYTE_ERASED;
/* start calculate CRC32 */
kv_hdr.crc32 = 0;
@@ -1401,54 +1242,45 @@ static fdb_err_t create_kv_blob(fdb_kvdb_t db, kv_sec_info_t sector, const char
kv_hdr.crc32 = fdb_calc_crc32(kv_hdr.crc32, &kv_hdr.value_len, sizeof(uint32_t));
kv_hdr.crc32 = fdb_calc_crc32(kv_hdr.crc32, key, kv_hdr.name_len);
align_remain = FDB_WG_ALIGN(kv_hdr.name_len) - kv_hdr.name_len;
- while (align_remain--)
- {
+ while (align_remain--) {
kv_hdr.crc32 = fdb_calc_crc32(kv_hdr.crc32, &ff, 1);
}
kv_hdr.crc32 = fdb_calc_crc32(kv_hdr.crc32, value, kv_hdr.value_len);
align_remain = FDB_WG_ALIGN(kv_hdr.value_len) - kv_hdr.value_len;
- while (align_remain--)
- {
+ while (align_remain--) {
kv_hdr.crc32 = fdb_calc_crc32(kv_hdr.crc32, &ff, 1);
}
/* write KV header data */
result = write_kv_hdr(db, kv_addr, &kv_hdr);
}
/* write key name */
- if (result == FDB_NO_ERR)
- {
- result = align_write(db, kv_addr + KV_HDR_DATA_SIZE, (uint32_t *)key, kv_hdr.name_len);
+ if (result == FDB_NO_ERR) {
+ result = align_write(db, kv_addr + KV_HDR_DATA_SIZE, (uint32_t *) key, kv_hdr.name_len);
#ifdef FDB_KV_USING_CACHE
- if (!is_full)
- {
+ if (!is_full) {
update_sector_empty_addr_cache(db, sector->addr,
- kv_addr + KV_HDR_DATA_SIZE + FDB_WG_ALIGN(kv_hdr.name_len) + FDB_WG_ALIGN(kv_hdr.value_len));
+ kv_addr + KV_HDR_DATA_SIZE + FDB_WG_ALIGN(kv_hdr.name_len) + FDB_WG_ALIGN(kv_hdr.value_len));
}
update_kv_cache(db, key, kv_hdr.name_len, kv_addr);
#endif /* FDB_KV_USING_CACHE */
}
/* write value */
- if (result == FDB_NO_ERR)
- {
+ if (result == FDB_NO_ERR) {
result = align_write(db, kv_addr + KV_HDR_DATA_SIZE + FDB_WG_ALIGN(kv_hdr.name_len), value,
- kv_hdr.value_len);
+ kv_hdr.value_len);
}
/* change the KV status to KV_WRITE */
- if (result == FDB_NO_ERR)
- {
- result = _fdb_write_status((fdb_db_t)db, kv_addr, kv_hdr.status_table, FDB_KV_STATUS_NUM, FDB_KV_WRITE,
- true);
+ if (result == FDB_NO_ERR) {
+ result = _fdb_write_status((fdb_db_t) db, kv_addr, kv_hdr.status_table, FDB_KV_STATUS_NUM, FDB_KV_WRITE,
+ true);
}
/* trigger GC collect when current sector is full */
- if (result == FDB_NO_ERR && is_full)
- {
+ if (result == FDB_NO_ERR && is_full) {
FDB_DEBUG("Trigger a GC check after created KV.\n");
db->gc_request = true;
}
- }
- else
- {
+ } else {
result = FDB_SAVED_FULL;
}
@@ -1467,8 +1299,7 @@ fdb_err_t fdb_kv_del(fdb_kvdb_t db, const char *key)
{
fdb_err_t result = FDB_NO_ERR;
- if (!db_init_ok(db))
- {
+ if (!db_init_ok(db)) {
FDB_INFO("Error: KV (%s) isn't initialize OK.\n", db_name(db));
return FDB_INIT_FAILED;
}
@@ -1489,36 +1320,28 @@ static fdb_err_t set_kv(fdb_kvdb_t db, const char *key, const void *value_buf, s
fdb_err_t result = FDB_NO_ERR;
bool kv_is_found = false;
- if (value_buf == NULL)
- {
+ if (value_buf == NULL) {
result = del_kv(db, key, NULL, true);
- }
- else
- {
+ } else {
/* make sure the flash has enough space */
- if (new_kv_ex(db, &db->cur_sector, strlen(key), buf_len) == FAILED_ADDR)
- {
+ if (new_kv_ex(db, &db->cur_sector, strlen(key), buf_len) == FAILED_ADDR) {
return FDB_SAVED_FULL;
}
kv_is_found = find_kv(db, key, &db->cur_kv);
/* prepare to delete the old KV */
- if (kv_is_found)
- {
+ if (kv_is_found) {
result = del_kv(db, key, &db->cur_kv, false);
}
/* create the new KV */
- if (result == FDB_NO_ERR)
- {
+ if (result == FDB_NO_ERR) {
result = create_kv_blob(db, &db->cur_sector, key, value_buf, buf_len);
}
/* delete the old KV */
- if (kv_is_found && result == FDB_NO_ERR)
- {
+ if (kv_is_found && result == FDB_NO_ERR) {
result = del_kv(db, key, &db->cur_kv, true);
}
/* process the GC after set KV */
- if (db->gc_request)
- {
+ if (db->gc_request) {
gc_collect_by_free_size(db, KV_HDR_DATA_SIZE + FDB_WG_ALIGN(strlen(key)) + FDB_WG_ALIGN(buf_len));
}
}
@@ -1540,8 +1363,7 @@ fdb_err_t fdb_kv_set_blob(fdb_kvdb_t db, const char *key, fdb_blob_t blob)
{
fdb_err_t result = FDB_NO_ERR;
- if (!db_init_ok(db))
- {
+ if (!db_init_ok(db)) {
FDB_INFO("Error: KV (%s) isn't initialize OK.\n", db_name(db));
return FDB_INIT_FAILED;
}
@@ -1571,7 +1393,11 @@ fdb_err_t fdb_kv_set(fdb_kvdb_t db, const char *key, const char *value)
{
struct fdb_blob blob;
- return fdb_kv_set_blob(db, key, fdb_blob_make(&blob, value, strlen(value)));
+ if (value) {
+ return fdb_kv_set_blob(db, key, fdb_blob_make(&blob, value, strlen(value)));
+ } else {
+ return fdb_kv_del(db, key);
+ }
}
/**
@@ -1588,32 +1414,32 @@ fdb_err_t fdb_kv_set_default(fdb_kvdb_t db)
/* lock the KV cache */
db_lock(db);
+
+#ifdef FDB_KV_USING_CACHE
+ for (i = 0; i < FDB_KV_CACHE_TABLE_SIZE; i++) {
+ db->kv_cache_table[i].addr = FDB_DATA_UNUSED;
+ }
+#endif /* FDB_KV_USING_CACHE */
+
/* format all sectors */
- for (addr = 0; addr < db_max_size(db); addr += db_sec_size(db))
- {
+ for (addr = 0; addr < db_max_size(db); addr += db_sec_size(db)) {
result = format_sector(db, addr, SECTOR_NOT_COMBINED);
- if (result != FDB_NO_ERR)
- {
+ if (result != FDB_NO_ERR) {
goto __exit;
}
}
/* create default KV */
- for (i = 0; i < db->default_kvs.num; i++)
- {
+ for (i = 0; i < db->default_kvs.num; i++) {
/* It seems to be a string when value length is 0.
* This mechanism is for compatibility with older versions (less then V4.0). */
- if (db->default_kvs.kvs[i].value_len == 0)
- {
+ if (db->default_kvs.kvs[i].value_len == 0) {
value_len = strlen(db->default_kvs.kvs[i].value);
- }
- else
- {
+ } else {
value_len = db->default_kvs.kvs[i].value_len;
}
sector.empty_kv = FAILED_ADDR;
create_kv_blob(db, §or, db->default_kvs.kvs[i].key, db->default_kvs.kvs[i].value, value_len);
- if (result != FDB_NO_ERR)
- {
+ if (result != FDB_NO_ERR) {
goto __exit;
}
}
@@ -1632,54 +1458,39 @@ static bool print_kv_cb(fdb_kv_t kv, void *arg1, void *arg2)
size_t *using_size = arg1;
fdb_kvdb_t db = arg2;
- if (kv->crc_is_ok)
- {
+ if (kv->crc_is_ok) {
/* calculate the total using flash size */
*using_size += kv->len;
/* check KV */
- if (kv->status == FDB_KV_WRITE)
- {
+ if (kv->status == FDB_KV_WRITE) {
FDB_PRINT("%.*s=", kv->name_len, kv->name);
- if (kv->value_len < FDB_STR_KV_VALUE_MAX_SIZE)
- {
+ if (kv->value_len < FDB_STR_KV_VALUE_MAX_SIZE ) {
uint8_t buf[32];
size_t len, size;
- __reload:
+__reload:
/* check the value is string */
- for (len = 0, size = 0; len < kv->value_len; len += size)
- {
- if (len + sizeof(buf) < kv->value_len)
- {
+ for (len = 0, size = 0; len < kv->value_len; len += size) {
+ if (len + sizeof(buf) < kv->value_len) {
size = sizeof(buf);
- }
- else
- {
+ } else {
size = kv->value_len - len;
}
- _fdb_flash_read((fdb_db_t)db, kv->addr.value + len, (uint32_t *)buf, FDB_WG_ALIGN(size));
- if (print_value)
- {
+ _fdb_flash_read((fdb_db_t)db, kv->addr.value + len, (uint32_t *) buf, FDB_WG_ALIGN(size));
+ if (print_value) {
FDB_PRINT("%.*s", (int)size, buf);
- }
- else if (!fdb_is_str(buf, size))
- {
+ } else if (!fdb_is_str(buf, size)) {
value_is_str = false;
break;
}
}
- }
- else
- {
+ } else {
value_is_str = false;
}
- if (value_is_str && !print_value)
- {
+ if (value_is_str && !print_value) {
print_value = true;
goto __reload;
- }
- else if (!value_is_str)
- {
+ } else if (!value_is_str) {
FDB_PRINT("blob @0x%08" PRIX32 " %" PRIu32 "bytes", kv->addr.value, kv->value_len);
}
FDB_PRINT("\n");
@@ -1689,6 +1500,7 @@ static bool print_kv_cb(fdb_kv_t kv, void *arg1, void *arg2)
return false;
}
+
/**
* Print all KV.
*
@@ -1699,8 +1511,7 @@ void fdb_kv_print(fdb_kvdb_t db)
struct fdb_kv kv;
size_t using_size = 0;
- if (!db_init_ok(db))
- {
+ if (!db_init_ok(db)) {
FDB_INFO("Error: KV (%s) isn't initialize OK.\n", db_name(db));
return;
}
@@ -1712,7 +1523,7 @@ void fdb_kv_print(fdb_kvdb_t db)
FDB_PRINT("\nmode: next generation\n");
FDB_PRINT("size: %" PRIu32 "/%" PRIu32 " bytes.\n", (uint32_t)using_size + ((SECTOR_NUM - FDB_GC_EMPTY_SEC_THRESHOLD) * SECTOR_HDR_DATA_SIZE),
- db_max_size(db) - db_sec_size(db) * FDB_GC_EMPTY_SEC_THRESHOLD);
+ db_max_size(db) - db_sec_size(db) * FDB_GC_EMPTY_SEC_THRESHOLD);
/* unlock the KV cache */
db_unlock(db);
@@ -1726,35 +1537,26 @@ static void kv_auto_update(fdb_kvdb_t db)
{
size_t saved_ver_num, setting_ver_num = db->ver_num;
- if (get_kv(db, VER_NUM_KV_NAME, &saved_ver_num, sizeof(size_t), NULL) > 0)
- {
+ if (get_kv(db, VER_NUM_KV_NAME, &saved_ver_num, sizeof(size_t), NULL) > 0) {
/* check version number */
- if (saved_ver_num != setting_ver_num)
- {
+ if (saved_ver_num != setting_ver_num) {
size_t i, value_len;
FDB_DEBUG("Update the KV from version %zu to %zu.\n", saved_ver_num, setting_ver_num);
- for (i = 0; i < db->default_kvs.num; i++)
- {
+ for (i = 0; i < db->default_kvs.num; i++) {
/* add a new KV when it's not found */
- if (!find_kv(db, db->default_kvs.kvs[i].key, &db->cur_kv))
- {
+ if (!find_kv(db, db->default_kvs.kvs[i].key, &db->cur_kv)) {
/* It seems to be a string when value length is 0.
* This mechanism is for compatibility with older versions (less then V4.0). */
- if (db->default_kvs.kvs[i].value_len == 0)
- {
+ if (db->default_kvs.kvs[i].value_len == 0) {
value_len = strlen(db->default_kvs.kvs[i].value);
- }
- else
- {
+ } else {
value_len = db->default_kvs.kvs[i].value_len;
}
db->cur_sector.empty_kv = FAILED_ADDR;
create_kv_blob(db, &db->cur_sector, db->default_kvs.kvs[i].key, db->default_kvs.kvs[i].value, value_len);
}
}
- }
- else
- {
+ } else {
/* version number not changed now return */
return;
}
@@ -1766,14 +1568,14 @@ static void kv_auto_update(fdb_kvdb_t db)
static bool check_oldest_addr_cb(kv_sec_info_t sector, void *arg1, void *arg2)
{
- uint32_t *sector_oldest_addr = (uint32_t *)arg1;
+ uint32_t *sector_oldest_addr = (uint32_t *) arg1;
fdb_sector_store_status_t *last_sector_status = (fdb_sector_store_status_t *)arg2;
/* The oldest address is 0 by default.
* The new oldest sector is found when sector status change from empty to full or using.
*/
- if (*last_sector_status == FDB_SECTOR_STORE_EMPTY && (sector->status.store == FDB_SECTOR_STORE_FULL || sector->status.store == FDB_SECTOR_STORE_USING))
- {
+ if (*last_sector_status == FDB_SECTOR_STORE_EMPTY
+ && (sector->status.store == FDB_SECTOR_STORE_FULL || sector->status.store == FDB_SECTOR_STORE_USING)) {
*sector_oldest_addr = sector->addr;
}
@@ -1783,19 +1585,15 @@ static bool check_oldest_addr_cb(kv_sec_info_t sector, void *arg1, void *arg2)
static bool check_sec_hdr_cb(kv_sec_info_t sector, void *arg1, void *arg2)
{
- if (!sector->check_ok)
- {
+ if (!sector->check_ok) {
size_t *failed_count = arg1;
fdb_kvdb_t db = arg2;
- (*failed_count)++;
- if (db->parent.not_formatable)
- {
+ (*failed_count) ++;
+ if (db->parent.not_formatable) {
return true;
- }
- else
- {
- FDB_INFO("Sector header info is incorrect. Auto format this sector (0x%08" PRIX32 ").\n", sector->addr);
+ } else {
+ FDB_DEBUG("Sector header info is incorrect. Auto format this sector (0x%08" PRIX32 ").\n", sector->addr);
format_sector(db, sector->addr, SECTOR_NOT_COMBINED);
}
}
@@ -1807,8 +1605,7 @@ static bool check_and_recovery_gc_cb(kv_sec_info_t sector, void *arg1, void *arg
{
fdb_kvdb_t db = arg1;
- if (sector->check_ok && sector->status.dirty == FDB_SECTOR_DIRTY_GC)
- {
+ if (sector->check_ok && sector->status.dirty == FDB_SECTOR_DIRTY_GC) {
/* make sure the GC request flag to true */
db->gc_request = true;
/* resume the GC operate */
@@ -1823,30 +1620,22 @@ static bool check_and_recovery_kv_cb(fdb_kv_t kv, void *arg1, void *arg2)
fdb_kvdb_t db = arg1;
/* recovery the prepare deleted KV */
- if (kv->crc_is_ok && kv->status == FDB_KV_PRE_DELETE)
- {
+ if (kv->crc_is_ok && kv->status == FDB_KV_PRE_DELETE) {
FDB_INFO("Found an KV (%.*s) which has changed value failed. Now will recovery it.\n", kv->name_len, kv->name);
/* recovery the old KV */
- if (move_kv(db, kv) == FDB_NO_ERR)
- {
+ if (move_kv(db, kv) == FDB_NO_ERR) {
FDB_DEBUG("Recovery the KV successful.\n");
- }
- else
- {
+ } else {
FDB_DEBUG("Warning: Moved an KV (size %" PRIu32 ") failed when recovery. Now will GC then retry.\n", kv->len);
return true;
}
- }
- else if (kv->status == FDB_KV_PRE_WRITE)
- {
+ } else if (kv->status == FDB_KV_PRE_WRITE) {
uint8_t status_table[KV_STATUS_TABLE_SIZE];
/* the KV has not write finish, change the status to error */
- // TODO Draw the state replacement diagram of exception handling
+ //TODO Draw the state replacement diagram of exception handling
_fdb_write_status((fdb_db_t)db, kv->addr.start, status_table, FDB_KV_STATUS_NUM, FDB_KV_ERR_HDR, true);
return true;
- }
- else if (kv->crc_is_ok && kv->status == FDB_KV_WRITE)
- {
+ } else if (kv->crc_is_ok && kv->status == FDB_KV_WRITE) {
#ifdef FDB_KV_USING_CACHE
/* update the cache when first load. If caching is disabled, this step is not performed */
update_kv_cache(db, kv->name, kv->name_len, kv->addr.start);
@@ -1871,13 +1660,11 @@ static fdb_err_t _fdb_kv_load(fdb_kvdb_t db)
db->in_recovery_check = true;
/* check all sector header */
sector_iterator(db, §or, FDB_SECTOR_STORE_UNUSED, &check_failed_count, db, check_sec_hdr_cb, false);
- if (db->parent.not_formatable && check_failed_count > 0)
- {
+ if (db->parent.not_formatable && check_failed_count > 0) {
return FDB_READ_ERR;
}
/* all sector header check failed */
- if (check_failed_count == SECTOR_NUM)
- {
+ if (check_failed_count == SECTOR_NUM) {
FDB_INFO("All sector header is incorrect. Set it to default.\n");
fdb_kv_set_default(db);
}
@@ -1888,8 +1675,7 @@ static fdb_err_t _fdb_kv_load(fdb_kvdb_t db)
__retry:
/* check all KV for recovery */
kv_iterator(db, &kv, db, NULL, check_and_recovery_kv_cb);
- if (db->gc_request)
- {
+ if (db->gc_request) {
gc_collect(db);
goto __retry;
}
@@ -1910,22 +1696,21 @@ void fdb_kvdb_control(fdb_kvdb_t db, int cmd, void *arg)
{
FDB_ASSERT(db);
- switch (cmd)
- {
+ switch (cmd) {
case FDB_KVDB_CTRL_SET_SEC_SIZE:
/* this change MUST before database initialization */
FDB_ASSERT(db->parent.init_ok == false);
- db->parent.sec_size = *(uint32_t *)arg;
+ db->parent.sec_size = *(uint32_t *) arg;
break;
case FDB_KVDB_CTRL_GET_SEC_SIZE:
- *(uint32_t *)arg = db->parent.sec_size;
+ *(uint32_t *) arg = db->parent.sec_size;
break;
case FDB_KVDB_CTRL_SET_LOCK:
#if !defined(__ARMCC_VERSION) && defined(__GNUC__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpedantic"
#endif
- db->parent.lock = (void (*)(fdb_db_t db))arg;
+ db->parent.lock = (void (*)(fdb_db_t db)) arg;
#if !defined(__ARMCC_VERSION) && defined(__GNUC__)
#pragma GCC diagnostic pop
#endif
@@ -1935,7 +1720,7 @@ void fdb_kvdb_control(fdb_kvdb_t db, int cmd, void *arg)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpedantic"
#endif
- db->parent.unlock = (void (*)(fdb_db_t db))arg;
+ db->parent.unlock = (void (*)(fdb_db_t db)) arg;
#if !defined(__ARMCC_VERSION) && defined(__GNUC__)
#pragma GCC diagnostic pop
#endif
@@ -1944,7 +1729,7 @@ void fdb_kvdb_control(fdb_kvdb_t db, int cmd, void *arg)
#ifdef FDB_USING_FILE_MODE
/* this change MUST before database initialization */
FDB_ASSERT(db->parent.init_ok == false);
- db->parent.file_mode = *(bool *)arg;
+ db->parent.file_mode = *(bool *) arg;
#else
FDB_INFO("Error: set file mode Failed. Please defined the FDB_USING_FILE_MODE macro.");
#endif
@@ -1976,7 +1761,7 @@ void fdb_kvdb_control(fdb_kvdb_t db, int cmd, void *arg)
* @return result
*/
fdb_err_t fdb_kvdb_init(fdb_kvdb_t db, const char *name, const char *path, struct fdb_default_kv *default_kv,
- void *user_data)
+ void *user_data)
{
fdb_err_t result = FDB_NO_ERR;
struct kvdb_sec_info sector;
@@ -1988,9 +1773,8 @@ fdb_err_t fdb_kvdb_init(fdb_kvdb_t db, const char *name, const char *path, struc
/* must be aligned with write granularity */
FDB_ASSERT((FDB_STR_KV_VALUE_MAX_SIZE * 8) % FDB_WRITE_GRAN == 0);
- result = _fdb_init_ex((fdb_db_t)db, name, path, FDB_DB_TYPE_KV, user_data);
- if (result != FDB_NO_ERR)
- {
+ result = _fdb_init_ex((fdb_db_t) db, name, path, FDB_DB_TYPE_KV, user_data);
+ if (result != FDB_NO_ERR) {
goto __exit;
}
@@ -1999,12 +1783,9 @@ fdb_err_t fdb_kvdb_init(fdb_kvdb_t db, const char *name, const char *path, struc
db->gc_request = false;
db->in_recovery_check = false;
- if (default_kv)
- {
+ if (default_kv) {
db->default_kvs = *default_kv;
- }
- else
- {
+ } else {
db->default_kvs.num = 0;
db->default_kvs.kvs = NULL;
}
@@ -2015,7 +1796,7 @@ fdb_err_t fdb_kvdb_init(fdb_kvdb_t db, const char *name, const char *path, struc
db_oldest_addr(db) = 0;
sector_iterator(db, §or, FDB_SECTOR_STORE_UNUSED, §or_oldest_addr, &last_sector_status,
- check_oldest_addr_cb, false);
+ check_oldest_addr_cb, false);
db_oldest_addr(db) = sector_oldest_addr;
FDB_DEBUG("The oldest addr is @0x%08" PRIX32 "\n", db_oldest_addr(db));
}
@@ -2023,25 +1804,24 @@ fdb_err_t fdb_kvdb_init(fdb_kvdb_t db, const char *name, const char *path, struc
FDB_ASSERT((FDB_GC_EMPTY_SEC_THRESHOLD > 0 && FDB_GC_EMPTY_SEC_THRESHOLD < SECTOR_NUM))
#ifdef FDB_KV_USING_CACHE
- for (i = 0; i < FDB_SECTOR_CACHE_TABLE_SIZE; i++)
- {
+ for (i = 0; i < FDB_SECTOR_CACHE_TABLE_SIZE; i++) {
db->sector_cache_table[i].check_ok = false;
db->sector_cache_table[i].empty_kv = FAILED_ADDR;
db->sector_cache_table[i].addr = FDB_DATA_UNUSED;
}
- for (i = 0; i < FDB_KV_CACHE_TABLE_SIZE; i++)
- {
+ for (i = 0; i < FDB_KV_CACHE_TABLE_SIZE; i++) {
db->kv_cache_table[i].addr = FDB_DATA_UNUSED;
}
#endif /* FDB_KV_USING_CACHE */
FDB_DEBUG("KVDB size is %" PRIu32 " bytes.\n", db_max_size(db));
-
+ db_unlock(db);
+
result = _fdb_kv_load(db);
-
+
+ db_lock(db);
#ifdef FDB_KV_AUTO_UPDATE
- if (result == FDB_NO_ERR)
- {
+ if (result == FDB_NO_ERR) {
kv_auto_update(db);
}
#endif
@@ -2065,7 +1845,7 @@ __exit:
*/
fdb_err_t fdb_kvdb_deinit(fdb_kvdb_t db)
{
- _fdb_deinit((fdb_db_t)db);
+ _fdb_deinit((fdb_db_t) db);
return FDB_NO_ERR;
}
@@ -2105,27 +1885,19 @@ bool fdb_kv_iterate(fdb_kvdb_t db, fdb_kv_iterator_t itr)
struct kvdb_sec_info sector;
fdb_kv_t kv = &(itr->curr_kv);
- do
- {
- if (read_sector_info(db, itr->sector_addr, §or, false) == FDB_NO_ERR)
- {
- if (sector.status.store == FDB_SECTOR_STORE_USING || sector.status.store == FDB_SECTOR_STORE_FULL)
- {
- if (kv->addr.start == 0)
- {
+ do {
+ if (read_sector_info(db, itr->sector_addr, §or, false) == FDB_NO_ERR) {
+ if (sector.status.store == FDB_SECTOR_STORE_USING || sector.status.store == FDB_SECTOR_STORE_FULL) {
+ if (kv->addr.start == 0) {
kv->addr.start = sector.addr + SECTOR_HDR_DATA_SIZE;
- }
- else if ((kv->addr.start = get_next_kv_addr(db, §or, kv)) == FAILED_ADDR)
- {
+ } else if ((kv->addr.start = get_next_kv_addr(db, §or, kv)) == FAILED_ADDR) {
kv->addr.start = 0;
itr->traversed_len += db_sec_size(db);
continue;
}
- do
- {
+ do {
read_kv(db, kv);
- if (kv->status == FDB_KV_WRITE && kv->crc_is_ok == true)
- {
+ if (kv->status == FDB_KV_WRITE && kv->crc_is_ok == true) {
/* We got a valid kv here. */
/* If iterator statistics is needed */
itr->iterated_cnt++;
@@ -2160,8 +1932,7 @@ fdb_err_t fdb_kvdb_check(fdb_kvdb_t db)
struct kvdb_sec_info sector;
struct fdb_kv kv;
- if (!db_init_ok(db))
- {
+ if (!db_init_ok(db)) {
FDB_INFO("Error: KV (%s) isn't initialize OK.\n", db_name(db));
return FDB_INIT_FAILED;
}
@@ -2171,19 +1942,16 @@ fdb_err_t fdb_kvdb_check(fdb_kvdb_t db)
sec_addr = db_oldest_addr(db);
/* search all sectors */
- do
- {
+ do {
traversed_len += db_sec_size(db);
result = read_sector_info(db, sec_addr, §or, false);
if (result == FDB_NO_ERR)
{
/* sector has KV */
- if (sector.status.store == FDB_SECTOR_STORE_USING || sector.status.store == FDB_SECTOR_STORE_FULL)
- {
+ if (sector.status.store == FDB_SECTOR_STORE_USING || sector.status.store == FDB_SECTOR_STORE_FULL) {
kv.addr.start = sector.addr + SECTOR_HDR_DATA_SIZE;
/* search all KV */
- do
- {
+ do {
result = read_kv(db, &kv);
} while ((kv.addr.start = get_next_kv_addr(db, §or, &kv)) != FAILED_ADDR && result == FDB_NO_ERR);
}
diff --git a/User/lib/flashdb/fdb_tsdb.c b/User/lib/flashdb/fdb_tsdb.c
index d019476..2d66c92 100644
--- a/User/lib/flashdb/fdb_tsdb.c
+++ b/User/lib/flashdb/fdb_tsdb.c
@@ -241,7 +241,9 @@ static fdb_err_t read_sector_info(fdb_tsdb_t db, uint32_t addr, tsdb_sec_info_t
if (tsl.status == FDB_TSL_UNUSED) {
break;
}
- sector->end_time = tsl.time;
+ if (tsl.status != FDB_TSL_PRE_WRITE) {
+ sector->end_time = tsl.time;
+ }
sector->end_idx = tsl.addr.index;
sector->empty_idx += LOG_IDX_DATA_SIZE;
sector->empty_data -= FDB_WG_ALIGN(tsl.log_len);
diff --git a/User/lib/flashdb/fdb_utils.c b/User/lib/flashdb/fdb_utils.c
index 2e2b99c..0776f13 100644
--- a/User/lib/flashdb/fdb_utils.c
+++ b/User/lib/flashdb/fdb_utils.c
@@ -304,7 +304,7 @@ fdb_err_t _fdb_flash_write(fdb_db_t db, uint32_t addr, const void *buf, size_t s
#ifdef FDB_USING_FILE_MODE
return _fdb_file_write(db, addr, buf, size, sync);
#else
- return FDB_READ_ERR;
+ return FDB_WRITE_ERR;
#endif /* FDB_USING_FILE_MODE */
} else {
#ifdef FDB_USING_FAL_MODE
diff --git a/User/lib/flashdb/flashdb.h b/User/lib/flashdb/flashdb.h
index 92816b2..61634fd 100644
--- a/User/lib/flashdb/flashdb.h
+++ b/User/lib/flashdb/flashdb.h
@@ -25,62 +25,52 @@
#include
+
#ifdef __cplusplus
-extern "C"
-{
+extern "C" {
#endif
- /* FlashDB database API */
- fdb_err_t fdb_kvdb_init(fdb_kvdb_t db, const char *name, const char *path, struct fdb_default_kv *default_kv,
- void *user_data);
- void fdb_kvdb_control(fdb_kvdb_t db, int cmd, void *arg);
- fdb_err_t fdb_kvdb_check(fdb_kvdb_t db);
- fdb_err_t fdb_kvdb_deinit(fdb_kvdb_t db);
- fdb_err_t fdb_tsdb_init(fdb_tsdb_t db, const char *name, const char *path, fdb_get_time get_time, size_t max_len,
- void *user_data);
- void fdb_tsdb_control(fdb_tsdb_t db, int cmd, void *arg);
- fdb_err_t fdb_tsdb_deinit(fdb_tsdb_t db);
+/* FlashDB database API */
+fdb_err_t fdb_kvdb_init (fdb_kvdb_t db, const char *name, const char *path, struct fdb_default_kv *default_kv,
+ void *user_data);
+void fdb_kvdb_control(fdb_kvdb_t db, int cmd, void *arg);
+fdb_err_t fdb_kvdb_check(fdb_kvdb_t db);
+fdb_err_t fdb_kvdb_deinit(fdb_kvdb_t db);
+fdb_err_t fdb_tsdb_init (fdb_tsdb_t db, const char *name, const char *path, fdb_get_time get_time, size_t max_len,
+ void *user_data);
+void fdb_tsdb_control(fdb_tsdb_t db, int cmd, void *arg);
+fdb_err_t fdb_tsdb_deinit(fdb_tsdb_t db);
- /* blob API */
- fdb_blob_t fdb_blob_make(fdb_blob_t blob, const void *value_buf, size_t buf_len);
- size_t fdb_blob_read(fdb_db_t db, fdb_blob_t blob);
+/* blob API */
+fdb_blob_t fdb_blob_make (fdb_blob_t blob, const void *value_buf, size_t buf_len);
+size_t fdb_blob_read (fdb_db_t db, fdb_blob_t blob);
- /* Key-Value API like a KV DB */
- fdb_err_t fdb_kv_set(fdb_kvdb_t db, const char *key, const char *value);
- char *fdb_kv_get(fdb_kvdb_t db, const char *key);
- fdb_err_t fdb_kv_set_blob(fdb_kvdb_t db, const char *key, fdb_blob_t blob);
- size_t fdb_kv_get_blob(fdb_kvdb_t db, const char *key, fdb_blob_t blob);
- fdb_err_t fdb_kv_del(fdb_kvdb_t db, const char *key);
- fdb_kv_t fdb_kv_get_obj(fdb_kvdb_t db, const char *key, fdb_kv_t kv);
- fdb_blob_t fdb_kv_to_blob(fdb_kv_t kv, fdb_blob_t blob);
- fdb_err_t fdb_kv_set_default(fdb_kvdb_t db);
- void fdb_kv_print(fdb_kvdb_t db);
- fdb_kv_iterator_t fdb_kv_iterator_init(fdb_kvdb_t db, fdb_kv_iterator_t itr);
- bool fdb_kv_iterate(fdb_kvdb_t db, fdb_kv_iterator_t itr);
+/* Key-Value API like a KV DB */
+fdb_err_t fdb_kv_set (fdb_kvdb_t db, const char *key, const char *value);
+char *fdb_kv_get (fdb_kvdb_t db, const char *key);
+fdb_err_t fdb_kv_set_blob (fdb_kvdb_t db, const char *key, fdb_blob_t blob);
+size_t fdb_kv_get_blob (fdb_kvdb_t db, const char *key, fdb_blob_t blob);
+fdb_err_t fdb_kv_del (fdb_kvdb_t db, const char *key);
+fdb_kv_t fdb_kv_get_obj (fdb_kvdb_t db, const char *key, fdb_kv_t kv);
+fdb_blob_t fdb_kv_to_blob (fdb_kv_t kv, fdb_blob_t blob);
+fdb_err_t fdb_kv_set_default (fdb_kvdb_t db);
+void fdb_kv_print (fdb_kvdb_t db);
+fdb_kv_iterator_t fdb_kv_iterator_init(fdb_kvdb_t db, fdb_kv_iterator_t itr);
+bool fdb_kv_iterate (fdb_kvdb_t db, fdb_kv_iterator_t itr);
- /* Time series log API like a TSDB */
- fdb_err_t fdb_tsl_append(fdb_tsdb_t db, fdb_blob_t blob);
- fdb_err_t fdb_tsl_append_with_ts(fdb_tsdb_t db, fdb_blob_t blob, fdb_time_t timestamp);
- void fdb_tsl_iter(fdb_tsdb_t db, fdb_tsl_cb cb, void *cb_arg);
- void fdb_tsl_iter_reverse(fdb_tsdb_t db, fdb_tsl_cb cb, void *cb_arg);
- void fdb_tsl_iter_by_time(fdb_tsdb_t db, fdb_time_t from, fdb_time_t to, fdb_tsl_cb cb, void *cb_arg);
- size_t fdb_tsl_query_count(fdb_tsdb_t db, fdb_time_t from, fdb_time_t to, fdb_tsl_status_t status);
- fdb_err_t fdb_tsl_set_status(fdb_tsdb_t db, fdb_tsl_t tsl, fdb_tsl_status_t status);
- void fdb_tsl_clean(fdb_tsdb_t db);
- fdb_blob_t fdb_tsl_to_blob(fdb_tsl_t tsl, fdb_blob_t blob);
+/* Time series log API like a TSDB */
+fdb_err_t fdb_tsl_append (fdb_tsdb_t db, fdb_blob_t blob);
+fdb_err_t fdb_tsl_append_with_ts(fdb_tsdb_t db, fdb_blob_t blob, fdb_time_t timestamp);
+void fdb_tsl_iter (fdb_tsdb_t db, fdb_tsl_cb cb, void *cb_arg);
+void fdb_tsl_iter_reverse(fdb_tsdb_t db, fdb_tsl_cb cb, void *cb_arg);
+void fdb_tsl_iter_by_time(fdb_tsdb_t db, fdb_time_t from, fdb_time_t to, fdb_tsl_cb cb, void *cb_arg);
+size_t fdb_tsl_query_count (fdb_tsdb_t db, fdb_time_t from, fdb_time_t to, fdb_tsl_status_t status);
+fdb_err_t fdb_tsl_set_status (fdb_tsdb_t db, fdb_tsl_t tsl, fdb_tsl_status_t status);
+void fdb_tsl_clean (fdb_tsdb_t db);
+fdb_blob_t fdb_tsl_to_blob (fdb_tsl_t tsl, fdb_blob_t blob);
- /* fdb_utils.c */
- uint32_t fdb_calc_crc32(uint32_t crc, const void *buf, size_t size);
-
- static inline void fdb_lock(fdb_db_t db)
- {
- __disable_irq();
- }
-
- static inline void fdb_unlock(fdb_db_t db)
- {
- __enable_irq();
- }
+/* fdb_utils.c */
+uint32_t fdb_calc_crc32(uint32_t crc, const void *buf, size_t size);
#ifdef __cplusplus
}
diff --git a/User/lib/flashdb/readme.md b/User/lib/flashdb/readme.md
new file mode 100644
index 0000000..2f5acd3
--- /dev/null
+++ b/User/lib/flashdb/readme.md
@@ -0,0 +1,38 @@
+# 移植说明
+
+## 简介
+
+[FlashDB](http://armink.gitee.io/flashdb/#/zh-cn/) 是一款超轻量级的嵌入式数据库,专注于提供嵌入式产品的数据存储方案。FlashDB 不仅支持传统的基于文件系统的数据库模式,而且结合了 Flash 的特性,具有较强的性能及可靠性。并在保证极低的资源占用前提下,尽可能延长 Flash 使用寿命。
+
+
+## 使用场景
+
+如今,物联网产品种类越来越多,运行时产生的数据种类及总量及也在不断变大。FlashDB 提供了多样化的数据存储方案,不仅资源占用小,并且存储容量大,非常适合用于物联网产品。下面是主要应用场景:
+
+* **键值数据库** :
+ * 产品参数存储
+ * 用户配置信息存储
+ * 小文件管理
+* **时序数据库** :
+ * 存储动态产生的结构化数据:如 温湿度传感器采集的环境监测信息,智能手环实时记录的人体健康信息等
+ * 记录运行日志:存储产品历史的运行日志,异常告警的记录等
+
+本项目使用3块EPPROM
+
+
+## 文件移植
+
+项目地址 https://github.com/armink/FlashDB
+
+引入目录中的文件
+
+.\FlashDB\src
+
+.\FlashDB\inc
+
+.\FlashDB\port\fal\src
+
+.\FlashDB\port\fal\inc
+
+
+> fal_cfg.h 这个文件为用户自定义升级的时候不要覆盖
diff --git a/User/lib/inc/data_type_def.h b/User/lib/inc/data_type_def.h
index 94694ca..90de350 100644
--- a/User/lib/inc/data_type_def.h
+++ b/User/lib/inc/data_type_def.h
@@ -128,11 +128,22 @@ typedef uint16_t nwk_id_t;
#define BIT20 (0x00100000u)
#define BIT21 (0x00200000u)
#define BIT22 (0x00400000u)
+#define BIT23 (0x00800000u)
+#define BIT24 (0x01000000u)
+#define BIT25 (0x02000000u)
+#define BIT26 (0x04000000u)
+#define BIT27 (0x08000000u)
+#define BIT28 (0x10000000u)
+#define BIT29 (0x20000000u)
+#define BIT30 (0x40000000u)
+#define BIT31 (0x80000000u)
-#define BIT_SET(x, b) x |= b // 置位
-#define BIT_CLR(x, b) x &= ~b // 清零
-#define BIT_IS_SET(x, b) ((x) & (b)) // 判断某一位是否为1
-#define BIT_IS_CLR(x, b) (!((x) & (b))) // 判断某一位是否为0
+#define BIT_SET(x, b) x |= b // 置位
+#define BIT_CLR(x, b) x &= ~b // 清零
+#define BIT_GET(x, y) ((x) >> (y) & 1) // 获取某一位
+#define BIT_REVERSE(x, y) (x) ^= (1 << y) // 某位取反
+#define BIT_IS_SET(x, b) ((x) & (b)) // 判断某一位是否为1
+#define BIT_IS_CLR(x, b) (!((x) & (b))) // 判断某一位是否为0
#endif
@@ -273,4 +284,7 @@ static inline float32 S2B_FLOAT32(float fv)
// 数字转换为ASSIC码
#define NUM_TO_ASCII(x) ((x) < 10 ? (x) + '0' : (x) - 10 + 'A')
-#endif /* __DATA_TYPE_DEF_H_ */
+
+#define FLOAT_TO_UINT16(x) (x * 8192 / 100 + 2048) ///> 浮点压缩uint16_t
+#define UINT16_TO_FLOAT(x) (100 * (x - 2048) / 8192) ///> uint16转浮点
+#endif /* __DATA_TYPE_DEF_H_ */
diff --git a/User/lib/inc/filter.h b/User/lib/inc/filter.h
index 54d0a6c..de165d9 100644
--- a/User/lib/inc/filter.h
+++ b/User/lib/inc/filter.h
@@ -12,18 +12,16 @@
typedef struct
{
- float32 Last_P; // 上次估算协方差 不可以为0 ! ! ! ! !
- float32 Now_P; // 当前估算协方差
- float32 out; // 卡尔曼滤波器输出
- float32 Kg; // 卡尔曼增益
- float32 Q; // 过程噪声协方差
- float32 R; // 观测噪声协方差
+ float32 x; // 卡尔曼滤波器的估计值
+ float32 a; // 状态转移矩阵(1,表示没有动态变化)
+ float32 h; // 观测矩阵(1,表示直接观测)
+ float32 q; // 过程噪声协方差
+ float32 r; // 观测噪声协方差
+ float32 p; // 估计误差协方差
+ float32 gain; // 卡尔曼增益
- uint8_t filter_count;
- uint8_t default_filter_count;
- float32 filter_limit;
- BOOL change;
-} kalman_t; // 卡尔曼滤波器
+ float32 change_max; // 允许的最大变化量,用于判断观测值是否异常
+} kalman_t; // 卡尔曼滤波器结构
typedef struct
{
@@ -41,15 +39,14 @@ typedef struct
uint16_t index; // 滑动窗口索引
} lpf_window_t; // 滑动窗口滤波器
-void kalman_init(kalman_t *cfg);
-void kalman_reset(kalman_t *cfg);
+void kalman_init(kalman_t *cfg, float32 change_max);
float32 kalman_update(kalman_t *cfg, float32 input);
void lpf_init(lpf_t *cfg);
float32 lpf_update(lpf_t *cfg, float32 input);
void lpf_reset(lpf_t *cfg);
-lpf_window_t *lpf_window_init(uint16_t size);
+void lpf_window_init(lpf_window_t *cfg, uint16_t size);
void lpf_window_dinit(lpf_window_t *cfg);
float32 lpf_window_update(lpf_window_t *cfg, float32 input);
void lpf_window_reset(lpf_window_t *cfg);
diff --git a/User/lib/inc/lib.h b/User/lib/inc/lib.h
index 4fac283..aba352a 100644
--- a/User/lib/inc/lib.h
+++ b/User/lib/inc/lib.h
@@ -10,7 +10,9 @@
#ifndef __LIB_H
#define __LIB_H
+#include
#include
+#include
#include "data_type_def.h"
#include "malloc.h"
#include "data_analysis.h"
@@ -36,11 +38,33 @@
do \
{ \
} while (0);
+
#endif
+#define EXIT(x) \
+ do \
+ { \
+ DBG_ASSERT(FALSE, __DBG_LINE); \
+ } while (0);
+
+////< 时间结构
+typedef union
+{
+ uint8_t data[6];
+ struct
+ {
+ uint8_t year;
+ uint8_t month;
+ uint8_t day;
+ uint8_t hour;
+ uint8_t minute;
+ uint8_t second;
+ } date;
+} date_time_t;
+
typedef struct
{
- uint8_t year;
+ uint16_t year;
uint8_t month;
uint8_t day;
} rtc_date_t;
@@ -52,29 +76,52 @@ typedef struct
uint8_t second;
} rtc_time_t;
-extern void assic_to_str(uint8_t *assic, uint8_t len, uint8_t *str); // ASCII码转字符串
-extern uint32_t cpu_encrypt(void); // CPU加密
-extern BOOL cpu_judge_encrypt(uint32_t cupid_encrypt); // CPU判断加密
-extern void version_split(uint8_t *version, uint8_t *hi, uint8_t *lo); // 版本号1.0拆解成1和0
-extern void reverse(uint8_t *buf, uint16_t len); // 反序数组
-extern BOOL is_in_array(uint16_t *arr, uint16_t len, uint16_t val); // 判断val是否在数组arr中
-extern BOOL is_same_value(uint8_t *buf, uint16_t len, uint8_t value); // 判断数组中的值是否都相等
-extern uint16_t crc16_compute(const uint8_t *const data, uint16_t length); // CRC16校验
-extern uint32_t crc32_compute(const uint8_t *const data, uint16_t length); // CRC32校验
-extern uint8_t xor_compute(const uint8_t *const data, uint16_t length); // 异或校验
-extern uint8_t get_bit_num(uint8_t bit); // 获取bit位的值
-extern BOOL is_bit_set(int x, int k); // 判断x的第k位是否为1
-extern uint8_t is_leap(uint16_t year); // 检查是否是闰年
-extern uint16_t dayOfyear(uint16_t year, uint8_t month, uint8_t day); // 计算一年中的第几天
-extern uint16_t weekOfyear(uint16_t year, uint8_t month, uint8_t day); // 计算一年中的第几周
-extern uint8_t get_weekday(uint16_t year, uint8_t month, uint8_t day); // 获取今天星期几
-extern uint8_t hex_format_dec(uint8_t hex); // 十六进制转十进制
-extern uint8_t dec_format_hex(uint8_t dec); // 十进制转十六进制
-extern void quicksort(uint16_t arr[], int low, int high); // 快速排序
-extern void insertion_sort(uint16_t arr[], uint8_t n); // 插入排序
+typedef struct
+{
+ float32 x;
+ float32 y;
+} point_t;
-extern uint32_t time2stamp(rtc_date_t *date, rtc_time_t *time); // 北京时间转时间戳
-extern void stamp2time(uint32_t stamp, rtc_date_t *date, rtc_time_t *time); // 时间戳转北京时间
-extern void convert_seconds(uint32_t total_seconds, char *date); // 秒数转换成时分秒
-extern void add_commas(uint32_t num, char *result); // 数字添加逗号
-#endif //__LIB_H
+typedef struct
+{
+ float32 a;
+ float32 b;
+} linear_func_param_t;
+
+extern void assic_to_str(uint8_t *assic, uint8_t len, uint8_t *str); // ASCII码转字符串
+extern void get_cpu_id(uint32_t *id); // 获取CPU ID
+extern uint32_t cpu_encrypt(void); // CPU加密
+extern BOOL cpu_judge_encrypt(uint32_t cupid_encrypt); // CPU判断加密
+extern void version_split(uint8_t *version, uint8_t *hi, uint8_t *lo); // 版本号1.0拆解成1和0
+extern void reverse(uint8_t *buf, uint16_t len); // 反序数组
+extern BOOL is_in_array(uint16_t *arr, uint16_t len, uint16_t val); // 判断val是否在数组arr中
+extern BOOL is_same_value(uint8_t *buf, uint16_t len, uint8_t value); // 判断数组中的值是否都相等
+extern uint16_t crc16_compute(const uint8_t *const data, uint16_t length); // CRC16校验
+extern uint32_t crc32_compute(const uint8_t *const data, uint16_t length); // CRC32校验
+extern uint64_t crc64_compute(const uint8_t *const data, const uint16_t length); // CRC64校验
+extern uint8_t xor_compute(const uint8_t *const data, uint16_t length); // 异或校验
+extern uint8_t get_bit_num(uint8_t bit); // 获取bit位的值
+extern BOOL is_bit_set(int x, int k); // 判断x的第k位是否为1
+extern uint8_t is_leap_year(uint16_t year); // 检查是否是闰年
+extern BOOL is_valid_date(uint8_t year, uint8_t month, uint8_t day); // 检查日期是否有效
+extern BOOL is_valid_time(uint8_t hour, uint8_t minute, uint8_t second); // 检查时间是否有效
+extern BOOL is_valid_datetime(uint8_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t minute, uint8_t second); // 检查日期和时间是否有效
+extern uint32_t days_since_1970(uint16_t year, uint8_t month, uint8_t day); // 计算从1970年1月1日到给定年月日的天数
+extern uint32_t date_to_seconds(uint16_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t minute, uint8_t second); // 将日期转换为秒数
+extern void seconds_to_date(uint32_t total_seconds, rtc_date_t *date, rtc_time_t *time); // 将秒数转换为日期
+extern uint16_t dayOfyear(uint16_t year, uint8_t month, uint8_t day); // 计算一年中的第几天
+extern uint16_t weekOfyear(uint16_t year, uint8_t month, uint8_t day); // 计算一年中的第几周
+extern uint8_t get_weekday(uint16_t year, uint8_t month, uint8_t day); // 获取今天星期几
+extern uint8_t hex_format_dec(uint8_t hex); // 十六进制转十进制
+extern uint8_t dec_format_hex(uint8_t dec); // 十进制转十六进制
+extern void quicksort(uint16_t arr[], int low, int high); // 快速排序
+extern void insertion_sort(uint16_t arr[], uint16_t n); // 插入排序
+
+extern uint32_t time2stamp(const rtc_date_t *const date, const rtc_time_t *const time); // 日期时间转时间戳
+extern void stamp2time(uint32_t stamp, rtc_date_t *date, rtc_time_t *time); // 时间戳转北京时间
+extern void convert_seconds(uint32_t total_seconds, char *date); // 秒数转换成时分秒
+extern void add_commas(uint32_t num, char *result); // 数字添加逗号
+
+extern linear_func_param_t calculate_linear_regression(const point_t *points, int32_t count); // 计算线性回归
+extern float32 get_linearity_value(const point_t *points, int32_t count, linear_func_param_t param); // 获取线性度
+#endif //__LIB_H
diff --git a/User/lib/inc/malloc.h b/User/lib/inc/malloc.h
index 65b6586..9c81a98 100644
--- a/User/lib/inc/malloc.h
+++ b/User/lib/inc/malloc.h
@@ -15,12 +15,12 @@
// mem1内存参数设定.mem1完全处于内部SRAM里面.(设置内部SARM的内存池和内存表的参数)
#define MEM1_BLOCK_SIZE 32 // 一个内存块大小为32字节
-#define MEM1_MAX_SIZE 24 * 1024 // 最大管理内存 1K (我们这个内存管理系统的内部SRAM可控制的内存大小)
+#define MEM1_MAX_SIZE 20 * 1024 // 最大管理内存 1K (我们这个内存管理系统的内部SRAM可控制的内存大小)
#define MEM1_ALLOC_TABLE_SIZE MEM1_MAX_SIZE / MEM1_BLOCK_SIZE // 内存表大小(有多少块内存块)
// mem2内存参数设定.mem2的内存池处于外部SRAM里面
#define MEM2_BLOCK_SIZE 32 // 一个内存块大小为32字节
-#define MEM2_MAX_SIZE 1 * 1024 // 因为精英版没有外扩内存,故这里设置一个最小值
+#define MEM2_MAX_SIZE 20 * 1024 // 因为精英版没有外扩内存,故这里设置一个最小值
#define MEM2_ALLOC_TABLE_SIZE MEM2_MAX_SIZE / MEM2_BLOCK_SIZE // 内存表大小
// 内存管理控制器结构体
diff --git a/User/lib/inc/sqqueue.h b/User/lib/inc/sqqueue.h
index e6e92c7..aac846c 100644
--- a/User/lib/inc/sqqueue.h
+++ b/User/lib/inc/sqqueue.h
@@ -8,7 +8,6 @@
#ifndef __SQQUEUE_H
#define __SQQUEUE_H
-#include
#include "data_type_def.h"
typedef struct _sqqueue_t
@@ -28,21 +27,25 @@ typedef struct _sqqueue_t
typedef struct _sqqueue_ctrl_t
{
sqqueue_t sqq;
- bool (*enter)(struct _sqqueue_ctrl_t *const p_this, const void *const e); // 单元素入队列
- bool (*string_enter)(struct _sqqueue_ctrl_t *const p_this, const void *const string, uint16_t len); // 多元素入队列
- void *(*del)(struct _sqqueue_ctrl_t *const p_this); // 出队列
- void *(*revoke)(struct _sqqueue_ctrl_t *const p_this); // 撤销入队列
- uint16_t (*get_len)(const struct _sqqueue_ctrl_t *const p_this); // 取队列长度
- bool (*full)(const struct _sqqueue_ctrl_t *const p_this); // 判满
- void (*clear_sqq)(struct _sqqueue_ctrl_t *const p_this); // 清空队列
- void (*traverse)(struct _sqqueue_ctrl_t *const p_this, void (*vi)(const void *e)); // 遍历
- void (*remove)(struct _sqqueue_ctrl_t *const p_this, uint16_t location); // 删除指定位置
+ BOOL(*enter)
+ (struct _sqqueue_ctrl_t *const p_this, const void *const e); // 单元素入队列
+ BOOL(*string_enter)
+ (struct _sqqueue_ctrl_t *const p_this, const void *const string, uint16_t len); // 多元素入队列
+ void *(*del)(struct _sqqueue_ctrl_t *const p_this); // 出队列
+ void *(*revoke)(struct _sqqueue_ctrl_t *const p_this); // 撤销入队列
+ uint16_t (*get_len)(const struct _sqqueue_ctrl_t *const p_this); // 取队列长度
+ BOOL(*full)
+ (const struct _sqqueue_ctrl_t *const p_this); // 判满
+ void (*clear_sqq)(struct _sqqueue_ctrl_t *const p_this); // 清空队列
+ void (*traverse)(struct _sqqueue_ctrl_t *const p_this, void (*vi)(const void *e)); // 遍历
+ void (*remove)(struct _sqqueue_ctrl_t *const p_this, uint16_t location); // 删除指定位置
} sqqueue_ctrl_t;
-bool sqqueue_ctrl_init(sqqueue_ctrl_t *const p_this,
+BOOL sqqueue_ctrl_init(sqqueue_ctrl_t *const p_this,
uint8_t entry_size,
uint16_t sqq_len); ///< 初始化
+void sqqueue_ctrl_dinit(sqqueue_ctrl_t *const p_this); ///< 销毁
#endif
/**
* @}
diff --git a/User/lib/inc/storage.h b/User/lib/inc/storage.h
new file mode 100644
index 0000000..ca50d28
--- /dev/null
+++ b/User/lib/inc/storage.h
@@ -0,0 +1,52 @@
+/**
+ * @file storage.h
+ * @author xushenghao
+ * @date 2024-11-15 15:57:02
+ * @brief 一个存储库,不支持平衡擦写
+ * @copyright Copyright (c) 2024 by xxx, All Rights Reserved.
+ */
+#ifndef __STORAGE_H__
+#define __STORAGE_H__
+
+#include "lib.h"
+
+typedef struct
+{
+ uint16_t index;
+ uint16_t size;
+ uint32_t address;
+} storage_node_t;
+
+typedef struct
+{
+ clist_node_t *head;
+ struct
+ {
+ uint32_t base_addr; ///< 存储器基地址
+ uint16_t page_size; ///< 存储器页大小
+ uint16_t variable_count; ///< 存储器变量数量
+ uint16_t variable_size; ///< 存储器变量占用大小,如果变量大小不够一页剩余部分则写入下一页,上一页剩余字节计入变量占用大小
+ uint16_t page_count; ///< 变量占用存储器页数
+ } params;
+
+ struct
+ {
+ BOOL(*read)
+ (uint32_t addr, uint8_t *buf, uint16_t size);
+ BOOL(*write)
+ (uint32_t addr, uint8_t * buf, uint16_t size);
+ BOOL(*erase_page)
+ (uint32_t page);
+ } ops;
+} storage_t;
+
+storage_t *storage_init(uint32_t base_addr, uint16_t page_size); ///< 初始化存储器
+void storage_destroy(storage_t *storage); ///< 销毁存储器
+void storage_add_node(storage_t *storage, uint16_t index, uint16_t size); ///< 添加存储节点
+BOOL storage_write(storage_t *storage, uint16_t index, const uint8_t *buf); ///< 存储数据
+BOOL storage_read(storage_t *storage, uint16_t index, uint8_t *buf); ///< 读取数据
+BOOL storage_write_all(storage_t *storage, const uint8_t *buf); ///< 存储所有数据
+BOOL storage_read_all(storage_t *storage, uint8_t *buf); ///< 读取所有数据
+BOOL storage_check(storage_t *storage, uint16_t index, uint8_t *buf); ///< 检查存储数据
+BOOL storage_check_all(storage_t *storage, uint8_t *buf); ///< 检查所有存储数据
+#endif // __STORAGE_H__
diff --git a/User/lib/inc/wl_flash.h b/User/lib/inc/wl_flash.h
new file mode 100644
index 0000000..694fac9
--- /dev/null
+++ b/User/lib/inc/wl_flash.h
@@ -0,0 +1,108 @@
+/**
+ * @file wl_flash.h
+ * @author xushenghao
+ * @date 2024-07-22 13:57:02
+ * @brief
+ * @copyright Copyright (c) 2024 by xxx, All Rights Reserved.
+ */
+/**
+ * @brief 磨损平衡算法
+ *
+ * 1. 初始化block_page大小和当前写入地址
+ * 2. 写入数据前,检查剩余空间是否足够
+ * a. 如果足够,直接写入数据
+ * b. 如果不足够,执行以下步骤:
+ * i. 检查是否有已擦除但未使用的block_page,如果有,移动到该block_page继续写入
+ * ii. 如果没有已擦除的block_page,检查当前block_page是否已满
+ * - 如果已满,移动到下一个block_page
+ * - 在移动前,检查该block_page是否有有效数据需要迁移,如果有,则先迁移数据
+ * 3. 在决定擦除新的block_page前,采用Wear Leveling算法选择最佳的block_page进行擦除
+ * 4. 数据写入后,更新剩余空间大小和当前写入地址
+ */
+
+/**
+ * 使用方法
+ *
+ #define LL_FLASH_PAGE_SIZE (2 * 1024)
+ #define PVD_RESET_STORAGE_START_ADDRESS (256 * LL_FLASH_PAGE_SIZE)
+ static void test_wl_flash(void)
+ {
+ uint32_t address = 0;
+ wl_flash_t wf = {
+ .wl_flag = TRUE,
+ .addr = PVD_RESET_STORAGE_START_ADDRESS,
+ .len = 2 * LL_FLASH_PAGE_SIZE,
+ .page_size = LL_FLASH_PAGE_SIZE,
+ .data_size = sizeof(device_reset_t),
+ .write_gran = 8,
+
+ .ops.srand = board_srand,
+ .ops.read = flash_read,
+ .ops.write = flash_write,
+ .ops.erase_page = flash_erase_page,
+ };
+ wl_flash_init(&wf);
+ wl_flash_erase(&wf);
+ address = wl_flash_get_current_address(&wf);
+
+ device_reset_t power_on;
+ power_on.flag = PVD_RESET_FLAG;
+
+ // 一页2048/16 = 128个数据,2页 = 256个数据,i=255时数据从头开始
+ for (uint16_t i = 0; i < 1000; i++)
+ {
+ wl_flash_write(&wf, (uint8_t *)&power_on, sizeof(device_reset_t));
+ wl_flash_set_next_address(&wf);
+ address = wl_flash_get_current_address(&wf);
+ if (address == wf.addr)
+ {
+ __NOP();
+ }
+ }
+ }
+ */
+
+#ifndef __WL_FLASH_H__
+#define __WL_FLASH_H__
+#include "lib.h"
+
+typedef struct
+{
+ BOOL wl_flag; // 开启平衡擦写标志
+ uint32_t addr; // Flash 起始地址
+ uint32_t len; // Flash 长度
+ uint16_t page_size; // Flash 页大小 2^N
+ uint16_t data_size; // 数据大小
+ /* write minimum granularity, unit: byte.
+ 1(stm32f2/f4)/ 4(stm32f1)/ 8(stm32l4)
+ 0 will not take effect. */
+ uint8_t write_gran;
+ struct
+ {
+ void (*srand)(void); // 随机数种子
+ BOOL(*read)
+ (uint32_t addr, uint8_t *buf, uint16_t size);
+ BOOL(*write)
+ (uint32_t addr, const uint8_t *buf, uint16_t size);
+ BOOL(*erase_page)
+ (uint32_t page);
+ } ops;
+
+ struct
+ {
+ uint32_t current_address; // 当前准备写入的地址
+ uint16_t residue_size; // 剩余可写大小
+ uint16_t start_page; // 起始页
+ uint16_t page_total; // 总页数
+ uint16_t block_page; // 擦除块大小
+ } private;
+} wl_flash_t;
+
+extern void wl_flash_init(wl_flash_t *cfg); ///< 初始化 Flash 磨损平衡算法
+extern uint32_t wl_flash_get_current_address(wl_flash_t *cfg); ///< 获取当前写入地址
+extern void wl_flash_set_next_address(wl_flash_t *cfg); ///< 设置下一个写入地址,下一个写入区域会被擦除
+extern void wl_flash_set_current_address(wl_flash_t *cfg, uint32_t address); ///< 设置当前写入地址
+extern void wl_flash_erase(wl_flash_t *cfg); ///< 擦除 Flash, 如果开启了平衡擦写标志, 则会随机分配写入地址
+extern BOOL wl_flash_write(wl_flash_t *cfg, const uint8_t *buf, uint16_t size); ///< 写入 Flash
+extern BOOL wl_flash_read(wl_flash_t *cfg, uint8_t *buf, uint16_t size); ///< 读取 Flash
+#endif // __WL_FLASH_H__
diff --git a/User/lib/lcd/font/HZ16x16.c b/User/lib/lcd/font/HZ16x16.c
new file mode 100644
index 0000000..5949899
--- /dev/null
+++ b/User/lib/lcd/font/HZ16x16.c
@@ -0,0 +1,9511 @@
+/*
+**********************************************************************
+* UcGUI Font
+* Chinese GB2312 library
+* (c) Copyright 19xx-20xx, company name
+*
+*
+* 注:本字体文件由 ucGUI字体生成器v9.0 生成,作者:馋嘴猫(qq:602426967)
+* 字体:宋体,字形:粗体,大小:11,宽:16,高:16,水平偏移:0,垂直偏移:0
+*
+**********************************************************************
+*/
+
+#include "GUI.H"
+
+
+/* char: code:0x0020 */
+static GUI_CONST_STORAGE unsigned char ac0020[32] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: ! code:0x0021 */
+static GUI_CONST_STORAGE unsigned char ac0021[32] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ___XX___,________,
+ ___XX___,________,
+ ___XX___,________,
+ ___XX___,________,
+ ___XX___,________,
+ ___XX___,________,
+ ___XX___,________,
+ ________,________,
+ ___XX___,________,
+ ___XX___,________,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: " code:0x0022 */
+static GUI_CONST_STORAGE unsigned char ac0022[32] = {
+ ________,________,
+ ___XXXX_,________,
+ __XXXX__,________,
+ __XXXX__,________,
+ _XXXX___,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: # code:0x0023 */
+static GUI_CONST_STORAGE unsigned char ac0023[32] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ___XX_XX,________,
+ ___XX_XX,________,
+ _XXXXXXX,________,
+ __XX_XX_,________,
+ __XX_XX_,________,
+ __XX_XX_,________,
+ _XXXXXXX,________,
+ __XX_XX_,________,
+ __XX_XX_,________,
+ __XX_XX_,________,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: $ code:0x0024 */
+static GUI_CONST_STORAGE unsigned char ac0024[32] = {
+ ________,________,
+ ________,________,
+ ____XX__,________,
+ __XXXXX_,________,
+ _XX_XXXX,________,
+ _XX_XXXX,________,
+ __XXXX__,________,
+ ___XXX__,________,
+ ____XXX_,________,
+ ____XXXX,________,
+ _XX_XXXX,________,
+ _XX_XXXX,________,
+ __XXXXX_,________,
+ ____XX__,________,
+ ____XX__,________,
+ ________,________
+};
+
+/* char: % code:0x0025 */
+static GUI_CONST_STORAGE unsigned char ac0025[32] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ _XX__XX_,________,
+ XXXX_XX_,________,
+ XXXXXX__,________,
+ XXXXXX__,________,
+ XXXXXXX_,________,
+ _XXXXXXX,________,
+ __XXXXXX,________,
+ __XXXXXX,________,
+ _XX_XXXX,________,
+ _XX__XX_,________,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: & code:0x0026 */
+static GUI_CONST_STORAGE unsigned char ac0026[32] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ __XXX___,________,
+ _XX_XX__,________,
+ _XX_XX__,________,
+ _XXXX___,________,
+ _XXX_XXX,________,
+ XXXX_XX_,________,
+ XXXX_XX_,________,
+ XX_XXXX_,________,
+ XX__XX_X,X_______,
+ _XXXXXXX,________,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: ' code:0x0027 */
+static GUI_CONST_STORAGE unsigned char ac0027[32] = {
+ ________,________,
+ _XXX____,________,
+ __XX____,________,
+ __XX____,________,
+ _XX_____,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: ( code:0x0028 */
+static GUI_CONST_STORAGE unsigned char ac0028[32] = {
+ ________,________,
+ ______XX,________,
+ _____XX_,________,
+ ____XX__,________,
+ ____XX__,________,
+ ___XX___,________,
+ ___XX___,________,
+ ___XX___,________,
+ ___XX___,________,
+ ___XX___,________,
+ ____XX__,________,
+ ____XX__,________,
+ _____XX_,________,
+ ______XX,________,
+ ________,________,
+ ________,________
+};
+
+/* char: ) code:0x0029 */
+static GUI_CONST_STORAGE unsigned char ac0029[32] = {
+ ________,________,
+ XX______,________,
+ _XX_____,________,
+ __XX____,________,
+ __XX____,________,
+ ___XX___,________,
+ ___XX___,________,
+ ___XX___,________,
+ ___XX___,________,
+ ___XX___,________,
+ __XX____,________,
+ __XX____,________,
+ _XX_____,________,
+ XX______,________,
+ ________,________,
+ ________,________
+};
+
+/* char: * code:0x002A */
+static GUI_CONST_STORAGE unsigned char ac002A[32] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ___XX___,________,
+ ___XX___,________,
+ XXXXXXXX,________,
+ __XXXX__,________,
+ __XXXX__,________,
+ XXXXXXXX,________,
+ ___XX___,________,
+ ___XX___,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: + code:0x002B */
+static GUI_CONST_STORAGE unsigned char ac002B[32] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ____XX__,________,
+ ____XX__,________,
+ ____XX__,________,
+ _XXXXXXX,X_______,
+ ____XX__,________,
+ ____XX__,________,
+ ____XX__,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: , code:0x002C */
+static GUI_CONST_STORAGE unsigned char ac002C[32] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ _XXX____,________,
+ __XX____,________,
+ __XX____,________,
+ _XX_____,________,
+ ________,________
+};
+
+/* char: - code:0x002D */
+static GUI_CONST_STORAGE unsigned char ac002D[32] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ XXXXXXXX,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: . code:0x002E */
+static GUI_CONST_STORAGE unsigned char ac002E[32] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ _XXX____,________,
+ _XXX____,________,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: / code:0x002F */
+static GUI_CONST_STORAGE unsigned char ac002F[32] = {
+ ________,________,
+ ______XX,________,
+ _____XX_,________,
+ _____XX_,________,
+ _____XX_,________,
+ ____XX__,________,
+ ____XX__,________,
+ ___XX___,________,
+ ___XX___,________,
+ ___XX___,________,
+ __XX____,________,
+ __XX____,________,
+ _XX_____,________,
+ _XX_____,________,
+ ________,________,
+ ________,________
+};
+
+/* char: 0 code:0x0030 */
+static GUI_CONST_STORAGE unsigned char ac0030[32] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ___XXX__,________,
+ __XX_XX_,________,
+ _XX___XX,________,
+ _XX___XX,________,
+ _XX___XX,________,
+ _XX___XX,________,
+ _XX___XX,________,
+ _XX___XX,________,
+ __XX_XX_,________,
+ ___XXX__,________,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: 1 code:0x0031 */
+static GUI_CONST_STORAGE unsigned char ac0031[32] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ___XX___,________,
+ _XXXX___,________,
+ ___XX___,________,
+ ___XX___,________,
+ ___XX___,________,
+ ___XX___,________,
+ ___XX___,________,
+ ___XX___,________,
+ ___XX___,________,
+ _XXXXXX_,________,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: 2 code:0x0032 */
+static GUI_CONST_STORAGE unsigned char ac0032[32] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ __XXXXX_,________,
+ _XX___XX,________,
+ _XX___XX,________,
+ ______XX,________,
+ _____XX_,________,
+ ____XX__,________,
+ ___XX___,________,
+ __XX____,________,
+ _XX___XX,________,
+ _XXXXXXX,________,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: 3 code:0x0033 */
+static GUI_CONST_STORAGE unsigned char ac0033[32] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ __XXXXX_,________,
+ _XX___XX,________,
+ _XX___XX,________,
+ _____XX_,________,
+ ___XXX__,________,
+ _____XX_,________,
+ ______XX,________,
+ _XX___XX,________,
+ _XX___XX,________,
+ __XXXXX_,________,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: 4 code:0x0034 */
+static GUI_CONST_STORAGE unsigned char ac0034[32] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ _____XX_,________,
+ ____XXX_,________,
+ ____XXX_,________,
+ ___XXXX_,________,
+ __XX_XX_,________,
+ _XX__XX_,________,
+ _XXXXXXX,X_______,
+ _____XX_,________,
+ _____XX_,________,
+ ___XXXXX,________,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: 5 code:0x0035 */
+static GUI_CONST_STORAGE unsigned char ac0035[32] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ _XXXXXXX,________,
+ _XX_____,________,
+ _XX_____,________,
+ _XXXXXX_,________,
+ _XX___XX,________,
+ ______XX,________,
+ ______XX,________,
+ _XX___XX,________,
+ _XX___XX,________,
+ __XXXXX_,________,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: 6 code:0x0036 */
+static GUI_CONST_STORAGE unsigned char ac0036[32] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ___XXX__,________,
+ __XX_XX_,________,
+ _XX_____,________,
+ _XXXXXX_,________,
+ _XXX__XX,________,
+ _XX___XX,________,
+ _XX___XX,________,
+ _XX___XX,________,
+ __XX__XX,________,
+ ___XXXX_,________,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: 7 code:0x0037 */
+static GUI_CONST_STORAGE unsigned char ac0037[32] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ _XXXXXXX,________,
+ _XX___XX,________,
+ _____XX_,________,
+ ____XX__,________,
+ ____XX__,________,
+ ____XX__,________,
+ ___XX___,________,
+ ___XX___,________,
+ ___XX___,________,
+ ___XX___,________,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: 8 code:0x0038 */
+static GUI_CONST_STORAGE unsigned char ac0038[32] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ __XXXXX_,________,
+ _XX___XX,________,
+ _XX___XX,________,
+ _XX___XX,________,
+ __XXXXX_,________,
+ __XX_XX_,________,
+ _XX___XX,________,
+ _XX___XX,________,
+ _XX___XX,________,
+ __XXXXX_,________,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: 9 code:0x0039 */
+static GUI_CONST_STORAGE unsigned char ac0039[32] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ __XXXX__,________,
+ _XX__XX_,________,
+ _XX___XX,________,
+ _XX___XX,________,
+ _XX__XXX,________,
+ __XXXXXX,________,
+ ______XX,________,
+ ______XX,________,
+ __XX_XX_,________,
+ ___XXX__,________,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: : code:0x003A */
+static GUI_CONST_STORAGE unsigned char ac003A[32] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ___XXX__,________,
+ ___XXX__,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ___XXX__,________,
+ ___XXX__,________,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: ; code:0x003B */
+static GUI_CONST_STORAGE unsigned char ac003B[32] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ___XX___,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ___XX___,________,
+ ___XX___,________,
+ ___XX___,________,
+ ________,________
+};
+
+/* char: < code:0x003C */
+static GUI_CONST_STORAGE unsigned char ac003C[32] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ _____XX_,________,
+ ____XX__,________,
+ ___XX___,________,
+ __XX____,________,
+ _XX_____,________,
+ _XX_____,________,
+ __XX____,________,
+ ___XX___,________,
+ ____XX__,________,
+ _____XX_,________,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: = code:0x003D */
+static GUI_CONST_STORAGE unsigned char ac003D[32] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ XXXXXXXX,________,
+ ________,________,
+ ________,________,
+ XXXXXXXX,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: > code:0x003E */
+static GUI_CONST_STORAGE unsigned char ac003E[32] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ __XX____,________,
+ ___XX___,________,
+ ____XX__,________,
+ _____XX_,________,
+ ______XX,________,
+ ______XX,________,
+ _____XX_,________,
+ ____XX__,________,
+ ___XX___,________,
+ __XX____,________,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: ? code:0x003F */
+static GUI_CONST_STORAGE unsigned char ac003F[32] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ __XXXXX_,________,
+ _XX___XX,________,
+ _XX___XX,________,
+ _XX___XX,________,
+ _____XX_,________,
+ ____XX__,________,
+ ____XX__,________,
+ ________,________,
+ ___XXX__,________,
+ ___XXX__,________,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: @ code:0x0040 */
+static GUI_CONST_STORAGE unsigned char ac0040[32] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ __XXXX__,________,
+ _XX__XX_,________,
+ XX_XXXXX,________,
+ XXXXXXXX,________,
+ XXXXXXXX,________,
+ XXXXXXXX,________,
+ XXXXXXXX,________,
+ XX_XXXX_,________,
+ _XX___XX,________,
+ __XXXXX_,________,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: A code:0x0041 */
+static GUI_CONST_STORAGE unsigned char ac0041[32] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ___XX___,________,
+ ___XX___,________,
+ __XXXX__,________,
+ __XXXX__,________,
+ __XXXX__,________,
+ __XXXX__,________,
+ _XXXXXX_,________,
+ _XX__XX_,________,
+ _XX__XX_,________,
+ XXXXXXXX,________,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: B code:0x0042 */
+static GUI_CONST_STORAGE unsigned char ac0042[32] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ XXXXXXX_,________,
+ _XX___XX,________,
+ _XX___XX,________,
+ _XX__XX_,________,
+ _XXXXX__,________,
+ _XX__XX_,________,
+ _XX___XX,________,
+ _XX___XX,________,
+ _XX___XX,________,
+ XXXXXXX_,________,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: C code:0x0043 */
+static GUI_CONST_STORAGE unsigned char ac0043[32] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ __XXXXXX,________,
+ _XX___XX,________,
+ XX____XX,________,
+ XX______,________,
+ XX______,________,
+ XX______,________,
+ XX______,________,
+ XX____XX,________,
+ _XX__XX_,________,
+ __XXXX__,________,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: D code:0x0044 */
+static GUI_CONST_STORAGE unsigned char ac0044[32] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ XXXXXX__,________,
+ _XX__XX_,________,
+ _XX___XX,________,
+ _XX___XX,________,
+ _XX___XX,________,
+ _XX___XX,________,
+ _XX___XX,________,
+ _XX___XX,________,
+ _XX__XX_,________,
+ XXXXXX__,________,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: E code:0x0045 */
+static GUI_CONST_STORAGE unsigned char ac0045[32] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ XXXXXXX_,________,
+ _XX___XX,________,
+ _XX_XX__,________,
+ _XX_XX__,________,
+ _XXXXX__,________,
+ _XX_XX__,________,
+ _XX_XX__,________,
+ _XX_____,________,
+ _XX___XX,________,
+ XXXXXXX_,________,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: F code:0x0046 */
+static GUI_CONST_STORAGE unsigned char ac0046[32] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ XXXXXXX_,________,
+ _XX___XX,________,
+ _XX_XX__,________,
+ _XX_XX__,________,
+ _XXXXX__,________,
+ _XX_XX__,________,
+ _XX_XX__,________,
+ _XX_____,________,
+ _XX_____,________,
+ XXXX____,________,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: G code:0x0047 */
+static GUI_CONST_STORAGE unsigned char ac0047[32] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ __XXXXX_,________,
+ _XX__XX_,________,
+ XX___XX_,________,
+ XX______,________,
+ XX______,________,
+ XX______,________,
+ XX__XXXX,________,
+ XX___XX_,________,
+ _XX__XX_,________,
+ __XXXX__,________,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: H code:0x0048 */
+static GUI_CONST_STORAGE unsigned char ac0048[32] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ XXXXXXXX,________,
+ _XX__XX_,________,
+ _XX__XX_,________,
+ _XX__XX_,________,
+ _XXXXXX_,________,
+ _XX__XX_,________,
+ _XX__XX_,________,
+ _XX__XX_,________,
+ _XX__XX_,________,
+ XXXXXXXX,________,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: I code:0x0049 */
+static GUI_CONST_STORAGE unsigned char ac0049[32] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ _XXXXXX_,________,
+ ___XX___,________,
+ ___XX___,________,
+ ___XX___,________,
+ ___XX___,________,
+ ___XX___,________,
+ ___XX___,________,
+ ___XX___,________,
+ ___XX___,________,
+ _XXXXXX_,________,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: J code:0x004A */
+static GUI_CONST_STORAGE unsigned char ac004A[32] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ __XXXXXX,________,
+ ____XX__,________,
+ ____XX__,________,
+ ____XX__,________,
+ ____XX__,________,
+ ____XX__,________,
+ ____XX__,________,
+ ____XX__,________,
+ ____XX__,________,
+ ____XX__,________,
+ XX__XX__,________,
+ XXXXX___,________,
+ ________,________
+};
+
+/* char: K code:0x004B */
+static GUI_CONST_STORAGE unsigned char ac004B[32] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ XXXXXXXX,________,
+ _XX__XX_,________,
+ _XX_XX__,________,
+ _XXXX___,________,
+ _XXXX___,________,
+ _XXXX___,________,
+ _XX_XX__,________,
+ _XX_XX__,________,
+ _XX__XX_,________,
+ XXXXXXXX,________,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: L code:0x004C */
+static GUI_CONST_STORAGE unsigned char ac004C[32] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ XXXX____,________,
+ _XX_____,________,
+ _XX_____,________,
+ _XX_____,________,
+ _XX_____,________,
+ _XX_____,________,
+ _XX_____,________,
+ _XX_____,________,
+ _XX___XX,________,
+ XXXXXXXX,________,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: M code:0x004D */
+static GUI_CONST_STORAGE unsigned char ac004D[32] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ XXXXXXXX,________,
+ _XXXXXX_,________,
+ _XXXXXX_,________,
+ _XXXXXX_,________,
+ _XXXXXX_,________,
+ _XXXXXX_,________,
+ _XXXXXX_,________,
+ _XXXXXX_,________,
+ _XXXXXX_,________,
+ XXXXXXXX,________,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: N code:0x004E */
+static GUI_CONST_STORAGE unsigned char ac004E[32] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ XXXXXXXX,________,
+ _XXX_XX_,________,
+ _XXX_XX_,________,
+ _XXXXXX_,________,
+ _XXXXXX_,________,
+ _XXXXXX_,________,
+ _XX_XXX_,________,
+ _XX_XXX_,________,
+ _XX_XXX_,________,
+ XXXX_XX_,________,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: O code:0x004F */
+static GUI_CONST_STORAGE unsigned char ac004F[32] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ __XXXX__,________,
+ _XX__XX_,________,
+ XX____XX,________,
+ XX____XX,________,
+ XX____XX,________,
+ XX____XX,________,
+ XX____XX,________,
+ XX____XX,________,
+ _XX__XX_,________,
+ __XXXX__,________,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: P code:0x0050 */
+static GUI_CONST_STORAGE unsigned char ac0050[32] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ XXXXXXX_,________,
+ _XX___XX,________,
+ _XX___XX,________,
+ _XX___XX,________,
+ _XXXXXX_,________,
+ _XX_____,________,
+ _XX_____,________,
+ _XX_____,________,
+ _XX_____,________,
+ XXXX____,________,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: Q code:0x0051 */
+static GUI_CONST_STORAGE unsigned char ac0051[32] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ __XXXX__,________,
+ _XX__XX_,________,
+ XX____XX,________,
+ XX____XX,________,
+ XX____XX,________,
+ XX____XX,________,
+ XX____XX,________,
+ XXXXX_XX,________,
+ _XX_XXX_,________,
+ __XXXX__,________,
+ _____XXX,________,
+ ________,________,
+ ________,________
+};
+
+/* char: R code:0x0052 */
+static GUI_CONST_STORAGE unsigned char ac0052[32] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ XXXXXX__,________,
+ _XX__XX_,________,
+ _XX__XX_,________,
+ _XX__XX_,________,
+ _XXXXX__,________,
+ _XXXX___,________,
+ _XX_XX__,________,
+ _XX_XX__,________,
+ _XX__XX_,________,
+ XXXX_XXX,________,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: S code:0x0053 */
+static GUI_CONST_STORAGE unsigned char ac0053[32] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ __XXXXXX,________,
+ _XX___XX,________,
+ _XX___XX,________,
+ _XX_____,________,
+ __XXX___,________,
+ ____XXX_,________,
+ ______XX,________,
+ _XX___XX,________,
+ _XX___XX,________,
+ _XXXXXX_,________,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: T code:0x0054 */
+static GUI_CONST_STORAGE unsigned char ac0054[32] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ XXXXXXXX,________,
+ XX_XX_XX,________,
+ ___XX___,________,
+ ___XX___,________,
+ ___XX___,________,
+ ___XX___,________,
+ ___XX___,________,
+ ___XX___,________,
+ ___XX___,________,
+ __XXXX__,________,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: U code:0x0055 */
+static GUI_CONST_STORAGE unsigned char ac0055[32] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ XXXXXXXX,________,
+ _XX__XX_,________,
+ _XX__XX_,________,
+ _XX__XX_,________,
+ _XX__XX_,________,
+ _XX__XX_,________,
+ _XX__XX_,________,
+ _XX__XX_,________,
+ _XX__XX_,________,
+ __XXXX__,________,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: V code:0x0056 */
+static GUI_CONST_STORAGE unsigned char ac0056[32] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ XXXXXXXX,________,
+ _XX__XX_,________,
+ _XX__XX_,________,
+ _XX__XX_,________,
+ __XXXX__,________,
+ __XXXX__,________,
+ __XXXX__,________,
+ __XXXX__,________,
+ ___XX___,________,
+ ___XX___,________,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: W code:0x0057 */
+static GUI_CONST_STORAGE unsigned char ac0057[32] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ XXXXXXXX,________,
+ _XXXXXX_,________,
+ _XXXXXX_,________,
+ _XXXXXX_,________,
+ _XXXXXX_,________,
+ _XXXXXX_,________,
+ __XXXX__,________,
+ __XXXX__,________,
+ __XXXX__,________,
+ __XXXX__,________,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: X code:0x0058 */
+static GUI_CONST_STORAGE unsigned char ac0058[32] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ XXXXXXXX,________,
+ _XX__XX_,________,
+ __XXXX__,________,
+ __XXXX__,________,
+ ___XX___,________,
+ ___XX___,________,
+ __XXXX__,________,
+ __XXXX__,________,
+ _XX__XX_,________,
+ XXXXXXXX,________,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: Y code:0x0059 */
+static GUI_CONST_STORAGE unsigned char ac0059[32] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ XXXXXXXX,________,
+ _XX__XX_,________,
+ _XX__XX_,________,
+ __XXXX__,________,
+ __XXXX__,________,
+ ___XX___,________,
+ ___XX___,________,
+ ___XX___,________,
+ ___XX___,________,
+ __XXXX__,________,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: Z code:0x005A */
+static GUI_CONST_STORAGE unsigned char ac005A[32] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ __XXXXXX,________,
+ _XX__XX_,________,
+ _____XX_,________,
+ ____XX__,________,
+ ____XX__,________,
+ ___XX___,________,
+ ___XX___,________,
+ __XX____,________,
+ __XX__XX,________,
+ _XXXXXXX,________,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: [ code:0x005B */
+static GUI_CONST_STORAGE unsigned char ac005B[32] = {
+ ________,________,
+ ___XXXX_,________,
+ ___XX___,________,
+ ___XX___,________,
+ ___XX___,________,
+ ___XX___,________,
+ ___XX___,________,
+ ___XX___,________,
+ ___XX___,________,
+ ___XX___,________,
+ ___XX___,________,
+ ___XX___,________,
+ ___XX___,________,
+ ___XXXX_,________,
+ ________,________,
+ ________,________
+};
+
+/* char: \ code:0x005C */
+static GUI_CONST_STORAGE unsigned char ac005C[32] = {
+ ________,________,
+ ________,________,
+ _XX_____,________,
+ _XX_____,________,
+ __XX____,________,
+ __XX____,________,
+ ___XX___,________,
+ ___XX___,________,
+ ___XX___,________,
+ ____XX__,________,
+ ____XX__,________,
+ _____XX_,________,
+ _____XX_,________,
+ _____XX_,________,
+ ______XX,________,
+ ________,________
+};
+
+/* char: ] code:0x005D */
+static GUI_CONST_STORAGE unsigned char ac005D[32] = {
+ ________,________,
+ _XXXXX__,________,
+ ____XX__,________,
+ ____XX__,________,
+ ____XX__,________,
+ ____XX__,________,
+ ____XX__,________,
+ ____XX__,________,
+ ____XX__,________,
+ ____XX__,________,
+ ____XX__,________,
+ ____XX__,________,
+ ____XX__,________,
+ _XXXXX__,________,
+ ________,________,
+ ________,________
+};
+
+/* char: ^ code:0x005E */
+static GUI_CONST_STORAGE unsigned char ac005E[32] = {
+ ________,________,
+ ___XXX__,________,
+ __XX_XX_,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: _ code:0x005F */
+static GUI_CONST_STORAGE unsigned char ac005F[32] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ XXXXXXXX,________,
+ ________,________
+};
+
+/* char: ` code:0x0060 */
+static GUI_CONST_STORAGE unsigned char ac0060[32] = {
+ _XXX____,________,
+ ___XX___,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: a code:0x0061 */
+static GUI_CONST_STORAGE unsigned char ac0061[32] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ __XXXX__,________,
+ _XX__XX_,________,
+ ____XXX_,________,
+ __XXXXX_,________,
+ _XX__XX_,________,
+ _XX_XXX_,________,
+ __XXXXXX,________,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: b code:0x0062 */
+static GUI_CONST_STORAGE unsigned char ac0062[32] = {
+ ________,________,
+ ________,________,
+ XXX_____,________,
+ _XX_____,________,
+ _XX_____,________,
+ _XX_____,________,
+ _XXXXXX_,________,
+ _XXX__XX,________,
+ _XX___XX,________,
+ _XX___XX,________,
+ _XX___XX,________,
+ _XX___XX,________,
+ _XXXXXX_,________,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: c code:0x0063 */
+static GUI_CONST_STORAGE unsigned char ac0063[32] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ___XXXX_,________,
+ __XX__XX,________,
+ _XX_____,________,
+ _XX_____,________,
+ _XX_____,________,
+ __XX__XX,________,
+ ___XXXX_,________,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: d code:0x0064 */
+static GUI_CONST_STORAGE unsigned char ac0064[32] = {
+ ________,________,
+ ________,________,
+ _____XXX,________,
+ ______XX,________,
+ ______XX,________,
+ ______XX,________,
+ __XXXXXX,________,
+ _XX___XX,________,
+ _XX___XX,________,
+ _XX___XX,________,
+ _XX___XX,________,
+ _XX__XXX,________,
+ __XXXXXX,X_______,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: e code:0x0065 */
+static GUI_CONST_STORAGE unsigned char ac0065[32] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ __XXXXX_,________,
+ _XX___XX,________,
+ _XX___XX,________,
+ _XXXXXXX,________,
+ _XX_____,________,
+ _XX___XX,________,
+ __XXXXX_,________,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: f code:0x0066 */
+static GUI_CONST_STORAGE unsigned char ac0066[32] = {
+ ________,________,
+ ________,________,
+ ____XXX_,________,
+ ___XX_XX,________,
+ ___XX___,________,
+ ___XX___,________,
+ _XXXXXX_,________,
+ ___XX___,________,
+ ___XX___,________,
+ ___XX___,________,
+ ___XX___,________,
+ ___XX___,________,
+ _XXXXXX_,________,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: g code:0x0067 */
+static GUI_CONST_STORAGE unsigned char ac0067[32] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ __XXXXXX,________,
+ _XX__XX_,________,
+ _XX__XX_,________,
+ __XXXX__,________,
+ _XX_____,________,
+ __XXXXX_,________,
+ _XX___XX,________,
+ _XX___XX,________,
+ __XXXXX_,________,
+ ________,________
+};
+
+/* char: h code:0x0068 */
+static GUI_CONST_STORAGE unsigned char ac0068[32] = {
+ ________,________,
+ ________,________,
+ XXX_____,________,
+ _XX_____,________,
+ _XX_____,________,
+ _XX_____,________,
+ _XXXXXX_,________,
+ _XXX__XX,________,
+ _XX___XX,________,
+ _XX___XX,________,
+ _XX___XX,________,
+ _XX___XX,________,
+ XXXX_XXX,X_______,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: i code:0x0069 */
+static GUI_CONST_STORAGE unsigned char ac0069[32] = {
+ ________,________,
+ ________,________,
+ __XXX___,________,
+ __XXX___,________,
+ ________,________,
+ ________,________,
+ _XXXX___,________,
+ ___XX___,________,
+ ___XX___,________,
+ ___XX___,________,
+ ___XX___,________,
+ ___XX___,________,
+ _XXXXXX_,________,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: j code:0x006A */
+static GUI_CONST_STORAGE unsigned char ac006A[32] = {
+ ________,________,
+ ________,________,
+ ____XXX_,________,
+ ____XXX_,________,
+ ________,________,
+ ________,________,
+ ___XXXX_,________,
+ _____XX_,________,
+ _____XX_,________,
+ _____XX_,________,
+ _____XX_,________,
+ _____XX_,________,
+ _____XX_,________,
+ _XX__XX_,________,
+ _XXXXX__,________,
+ ________,________
+};
+
+/* char: k code:0x006B */
+static GUI_CONST_STORAGE unsigned char ac006B[32] = {
+ ________,________,
+ ________,________,
+ XXX_____,________,
+ _XX_____,________,
+ _XX_____,________,
+ _XX_____,________,
+ _XX_XXXX,________,
+ _XX_XX__,________,
+ _XXXX___,________,
+ _XXXXX__,________,
+ _XX_XX__,________,
+ _XX__XX_,________,
+ XXXXXXXX,________,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: l code:0x006C */
+static GUI_CONST_STORAGE unsigned char ac006C[32] = {
+ ________,________,
+ ________,________,
+ _XXXX___,________,
+ ___XX___,________,
+ ___XX___,________,
+ ___XX___,________,
+ ___XX___,________,
+ ___XX___,________,
+ ___XX___,________,
+ ___XX___,________,
+ ___XX___,________,
+ ___XX___,________,
+ _XXXXXX_,________,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: m code:0x006D */
+static GUI_CONST_STORAGE unsigned char ac006D[32] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ XXXXXX__,________,
+ _XXXXXX_,________,
+ _XXXXXX_,________,
+ _XXXXXX_,________,
+ _XXXXXX_,________,
+ _XXXXXX_,________,
+ XXXXXXXX,________,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: n code:0x006E */
+static GUI_CONST_STORAGE unsigned char ac006E[32] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ XXXXXXX_,________,
+ _XXX__XX,________,
+ _XX___XX,________,
+ _XX___XX,________,
+ _XX___XX,________,
+ _XX___XX,________,
+ XXXX_XXX,X_______,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: o code:0x006F */
+static GUI_CONST_STORAGE unsigned char ac006F[32] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ___XXX__,________,
+ __XX_XX_,________,
+ _XX___XX,________,
+ _XX___XX,________,
+ _XX___XX,________,
+ __XX_XX_,________,
+ ___XXX__,________,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: p code:0x0070 */
+static GUI_CONST_STORAGE unsigned char ac0070[32] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ XXXXXXX_,________,
+ _XXX__XX,________,
+ _XX___XX,________,
+ _XX___XX,________,
+ _XX___XX,________,
+ _XXX__XX,________,
+ _XXXXXX_,________,
+ _XX_____,________,
+ XXXX____,________,
+ ________,________
+};
+
+/* char: q code:0x0071 */
+static GUI_CONST_STORAGE unsigned char ac0071[32] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ __XXXXXX,________,
+ _XX__XXX,________,
+ _XX___XX,________,
+ _XX___XX,________,
+ _XX___XX,________,
+ _XX__XXX,________,
+ __XXXXXX,________,
+ ______XX,________,
+ _____XXX,X_______,
+ ________,________
+};
+
+/* char: r code:0x0072 */
+static GUI_CONST_STORAGE unsigned char ac0072[32] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ XXXXXXXX,________,
+ __XXX_XX,________,
+ __XX____,________,
+ __XX____,________,
+ __XX____,________,
+ __XX____,________,
+ XXXXXX__,________,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: s code:0x0073 */
+static GUI_CONST_STORAGE unsigned char ac0073[32] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ __XXXXX_,________,
+ _XX__XX_,________,
+ _XX_____,________,
+ __XXXX__,________,
+ _____XX_,________,
+ _XX__XX_,________,
+ _XXXXX__,________,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: t code:0x0074 */
+static GUI_CONST_STORAGE unsigned char ac0074[32] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ___XX___,________,
+ ___XX___,________,
+ _XXXXXX_,________,
+ ___XX___,________,
+ ___XX___,________,
+ ___XX___,________,
+ ___XX___,________,
+ ___XX_XX,________,
+ ____XXX_,________,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: u code:0x0075 */
+static GUI_CONST_STORAGE unsigned char ac0075[32] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ XXX__XXX,________,
+ _XX___XX,________,
+ _XX___XX,________,
+ _XX___XX,________,
+ _XX___XX,________,
+ _XX__XXX,________,
+ __XXXXXX,X_______,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: v code:0x0076 */
+static GUI_CONST_STORAGE unsigned char ac0076[32] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ XXXXXXXX,________,
+ _XX__XX_,________,
+ _XX__XX_,________,
+ __XXXX__,________,
+ __XXXX__,________,
+ ___XX___,________,
+ ___XX___,________,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: w code:0x0077 */
+static GUI_CONST_STORAGE unsigned char ac0077[32] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ XXXXXXXX,________,
+ _XXXXXX_,________,
+ _XXXXXX_,________,
+ _XXXXXX_,________,
+ __XXXX__,________,
+ __XXXX__,________,
+ __XXXX__,________,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: x code:0x0078 */
+static GUI_CONST_STORAGE unsigned char ac0078[32] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ _XXXXXXX,________,
+ __XX_XX_,________,
+ ___XXX__,________,
+ ___XXX__,________,
+ ___XXX__,________,
+ __XX_XX_,________,
+ _XXXXXXX,________,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: y code:0x0079 */
+static GUI_CONST_STORAGE unsigned char ac0079[32] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ XXXX_XXX,X_______,
+ _XX___XX,________,
+ __XX_XX_,________,
+ __XX_XX_,________,
+ ___XXX__,________,
+ ___XXX__,________,
+ ___XX___,________,
+ ___XX___,________,
+ _XXX____,________,
+ ________,________
+};
+
+/* char: z code:0x007A */
+static GUI_CONST_STORAGE unsigned char ac007A[32] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ _XXXXXXX,________,
+ _XX__XX_,________,
+ ____XX__,________,
+ ___XX___,________,
+ ___XX___,________,
+ __XX__XX,________,
+ _XXXXXXX,________,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: { code:0x007B */
+static GUI_CONST_STORAGE unsigned char ac007B[32] = {
+ ________,________,
+ _____XXX,________,
+ _____XX_,________,
+ _____XX_,________,
+ _____XX_,________,
+ _____XX_,________,
+ _____XX_,________,
+ ____XX__,________,
+ _____XX_,________,
+ _____XX_,________,
+ _____XX_,________,
+ _____XX_,________,
+ _____XX_,________,
+ _____XXX,________,
+ ________,________,
+ ________,________
+};
+
+/* char: | code:0x007C */
+static GUI_CONST_STORAGE unsigned char ac007C[32] = {
+ ____XX__,________,
+ ____XX__,________,
+ ____XX__,________,
+ ____XX__,________,
+ ____XX__,________,
+ ____XX__,________,
+ ____XX__,________,
+ ____XX__,________,
+ ____XX__,________,
+ ____XX__,________,
+ ____XX__,________,
+ ____XX__,________,
+ ____XX__,________,
+ ____XX__,________,
+ ____XX__,________,
+ ________,________
+};
+
+/* char: } code:0x007D */
+static GUI_CONST_STORAGE unsigned char ac007D[32] = {
+ ________,________,
+ _XXX____,________,
+ __XX____,________,
+ __XX____,________,
+ __XX____,________,
+ __XX____,________,
+ __XX____,________,
+ ___XX___,________,
+ __XX____,________,
+ __XX____,________,
+ __XX____,________,
+ __XX____,________,
+ __XX____,________,
+ _XXX____,________,
+ ________,________,
+ ________,________
+};
+
+/* char: ~ code:0x007E */
+static GUI_CONST_STORAGE unsigned char ac007E[32] = {
+ __XX____,________,
+ _XXXXXXX,________,
+ _____XX_,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: code:0x007F */
+static GUI_CONST_STORAGE unsigned char ac007F[32] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: ~ code:0xA1AB */
+static GUI_CONST_STORAGE unsigned char acA1AB[32] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ___XXXX_,_____XX_,
+ __XX__XX,XX__XX__,
+ _XX_____,_XXXX___,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+};
+
+/* char: × code:0xA1C1 */
+static GUI_CONST_STORAGE unsigned char acA1C1[32] = {
+ ________,________,
+ ________,________,
+ ___XX___,___XX___,
+ ____XX__,__XX____,
+ _____XX_,_XX_____,
+ ______XX,XX______,
+ _______X,X_______,
+ ______XX,XX______,
+ _____XX_,_XX_____,
+ ____XX__,__XX____,
+ ___XX___,___XX___,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+};
+
+/* char: √ code:0xA1CC */
+static GUI_CONST_STORAGE unsigned char acA1CC[32] = {
+ ________,_____XX_,
+ ________,_____XX_,
+ ________,____XX__,
+ ________,____XX__,
+ ________,___XX___,
+ ________,___XX___,
+ ________,__XX____,
+ ________,_XX_____,
+ ________,_XX_____,
+ ___XX___,XX______,
+ __XXXX_X,X_______,
+ _XX__XXX,X_______,
+ ______XX,________,
+ ________,________,
+ ________,________,
+ ________,________,
+};
+
+/* char: ° code:0xA1E3 */
+static GUI_CONST_STORAGE unsigned char acA1E3[32] = {
+ ________,________,
+ ____XXX_,________,
+ ___XX_XX,________,
+ ___XX_XX,________,
+ ____XXX_,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+};
+
+/* char: ℃ code:0xA1E6 */
+static GUI_CONST_STORAGE unsigned char acA1E6[32] = {
+ __XXX___,________,
+ _XX_XX__,________,
+ _XX_XXXX,XXXXXXX_,
+ __XXXXX_,____XXX_,
+ ____XX__,_____XX_,
+ ____XX__,_____XX_,
+ ____XX__,________,
+ ____XX__,________,
+ ____XX__,________,
+ ____XX__,________,
+ ____XX__,_____XX_,
+ _____XX_,____XX__,
+ ______XX,XXXXX___,
+ ________,________,
+ ________,________,
+ ________,________,
+};
+
+/* char: ○ code:0xA1F0 */
+static GUI_CONST_STORAGE unsigned char acA1F0[32] = {
+ ________,________,
+ ______XX,XXX_____,
+ ____XXX_,__XXX___,
+ ___XX___,____XX__,
+ ___XX___,____XX__,
+ __XX____,_____XX_,
+ __XX____,_____XX_,
+ __XX____,_____XX_,
+ __XX____,_____XX_,
+ ___XX___,____XX__,
+ ___XX___,____XX__,
+ ____XXX_,__XXX___,
+ ______XX,XXX_____,
+ ________,________,
+ ________,________,
+ ________,________,
+};
+
+/* char: → code:0xA1FA */
+static GUI_CONST_STORAGE unsigned char acA1FA[32] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,_XX_____,
+ ________,_XXXX___,
+ _XXXXXXX,XXXXXXX_,
+ ________,_XXXX___,
+ ________,_XX_____,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+};
+
+/* char: ← code:0xA1FB */
+static GUI_CONST_STORAGE unsigned char acA1FB[32] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ _____XX_,________,
+ ___XXXX_,________,
+ _XXXXXXX,XXXXXXX_,
+ ___XXXX_,________,
+ _____XX_,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+};
+
+/* char: ↑ code:0xA1FC */
+static GUI_CONST_STORAGE unsigned char acA1FC[32] = {
+ _______X,X_______,
+ _______X,X_______,
+ ______XX,XX______,
+ ______XX,XX______,
+ _____XXX,XXX_____,
+ _______X,X_______,
+ _______X,X_______,
+ _______X,X_______,
+ _______X,X_______,
+ _______X,X_______,
+ _______X,X_______,
+ _______X,X_______,
+ _______X,X_______,
+ _______X,X_______,
+ ________,________,
+ ________,________,
+};
+
+/* char: ↓ code:0xA1FD */
+static GUI_CONST_STORAGE unsigned char acA1FD[32] = {
+ _______X,X_______,
+ _______X,X_______,
+ _______X,X_______,
+ _______X,X_______,
+ _______X,X_______,
+ _______X,X_______,
+ _______X,X_______,
+ _______X,X_______,
+ _______X,X_______,
+ _____XXX,XXX_____,
+ ______XX,XX______,
+ ______XX,XX______,
+ _______X,X_______,
+ _______X,X_______,
+ ________,________,
+ ________,________,
+};
+
+/* char: ℉ code:0xA848 */
+static GUI_CONST_STORAGE unsigned char acA848[32] = {
+ ________,________,
+ __XXXXXX,XXXXXX__,
+ _XX_XXXX,____XX__,
+ _XX_XXXX,________,
+ __XXX_XX,________,
+ ______XX,__XX____,
+ ______XX,XXXX____,
+ ______XX,__XX____,
+ ______XX,________,
+ ______XX,________,
+ ______XX,________,
+ _____XXX,X_______,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+};
+
+/* char: 安 code:0xB0B2 */
+static GUI_CONST_STORAGE unsigned char acB0B2[32] = {
+ ______XX,________,
+ _______X,X_______,
+ _XXXXXXX,XXXXXXX_,
+ _XX_____,_____XX_,
+ _XX___XX,_____XX_,
+ ______XX,________,
+ _XXXXXXX,XXXXXXX_,
+ _____XX_,__XX____,
+ ____XX__,__XX____,
+ ___XXXXX,_XX_____,
+ _______X,XX______,
+ ______XX,_XXX____,
+ ____XXX_,___XX___,
+ _XXXX___,____XX__,
+ ________,________,
+ ________,________,
+};
+
+/* char: 按 code:0xB0B4 */
+static GUI_CONST_STORAGE unsigned char acB0B4[32] = {
+ ___XX___,_XX_____,
+ ___XX___,__XX____,
+ ___XX_XX,XXXXXXX_,
+ _XXXXXXX,_____XX_,
+ ___XX_XX,_XX__XX_,
+ ___XX___,_XX_____,
+ ___XX_XX,XXXXXXX_,
+ ___XXX__,XX__XX__,
+ _XXXX___,XX__XX__,
+ ___XX__X,XX_XX___,
+ ___XX___,_XXX____,
+ ___XX___,_XXXX___,
+ ___XX___,XX__XX__,
+ _XXXX_XX,X____XX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 版 code:0xB0E6 */
+static GUI_CONST_STORAGE unsigned char acB0E6[32] = {
+ _____XX_,________,
+ __XX_XX_,____XXX_,
+ __XX_XX_,XXXXX___,
+ __XX_XX_,XX______,
+ __XXXXXX,XX______,
+ __XX____,XXXXXX__,
+ __XX____,XXXXXX__,
+ __XXXXX_,XXXXXX__,
+ __XX_XX_,XXXXXX__,
+ __XX_XX_,XXXXXX__,
+ __XX_XX_,XX_XX___,
+ __XX_XX_,XX_XX___,
+ __XX_XXX,X_XXXX__,
+ _XX__XXX,_XX__XX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 薄 code:0xB1A1 */
+static GUI_CONST_STORAGE unsigned char acB1A1[32] = {
+ _____XX_,_XX_____,
+ _XXXXXXX,XXXXXXX_,
+ _____XX_,_XXXX___,
+ ______XX,XXXXXXX_,
+ __XX____,_XX_____,
+ ___XX_XX,XXXXXX__,
+ ____XXXX,_XX_XX__,
+ _XX___XX,XXXXXX__,
+ __XX__XX,_XX_XX__,
+ ____XXXX,XXXXXX__,
+ ___XX_XX,_XX_XX__,
+ ___XXXXX,XXXXXXX_,
+ __XX___X,X__XX___,
+ __XX____,XXXXX___,
+ ________,________,
+ ________,________,
+};
+
+/* char: 保 code:0xB1A3 */
+static GUI_CONST_STORAGE unsigned char acB1A3[32] = {
+ ____XX__,________,
+ ____XXXX,XXXXXX__,
+ ____XXXX,____XX__,
+ ___XX_XX,____XX__,
+ ___XX_XX,XXXXXX__,
+ __XXX___,_XX_____,
+ _XXXX___,_XX_____,
+ ___XXXXX,XXXXXXX_,
+ ___XX___,XXXX____,
+ ___XX__X,XXXXX___,
+ ___XX__X,XXXXX___,
+ ___XX_XX,_XX_XX__,
+ ___XXXX_,_XX__XX_,
+ ___XX___,_XX_____,
+ ________,________,
+ ________,________,
+};
+
+/* char: 饱 code:0xB1A5 */
+static GUI_CONST_STORAGE unsigned char acB1A5[32] = {
+ ___XX___,XX______,
+ ___XX___,XX______,
+ ___XXXXX,XXXXXX__,
+ __XX_XXX,X___XX__,
+ __XXXXXX,____XX__,
+ _XX__XXX,XXXXXX__,
+ ___XX__X,X_XXXX__,
+ ___XX__X,X_XXXX__,
+ ___XX__X,XXXXXX__,
+ ___XX__X,X___XX__,
+ ___XX__X,X_XXX___,
+ ___XXXXX,X____XX_,
+ ___XXX_X,X____XX_,
+ ___XX___,XXXXXXX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 报 code:0xB1A8 */
+static GUI_CONST_STORAGE unsigned char acB1A8[32] = {
+ ___XX___,________,
+ ___XX__X,XXXXXX__,
+ ___XX__X,X___XX__,
+ _XXXXXXX,X___XX__,
+ ___XX__X,X_XXXX__,
+ ___XX__X,X_______,
+ ___XXXXX,XXXXXX__,
+ ___XXX_X,XXX_XX__,
+ _XXXX__X,XXX_XX__,
+ ___XX__X,XXXXX___,
+ ___XX__X,X_XX____,
+ ___XX__X,XXXXX___,
+ ___XX__X,XX__XX__,
+ _XXXX__X,X____XX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 备 code:0xB1B8 */
+static GUI_CONST_STORAGE unsigned char acB1B8[32] = {
+ _____XX_,________,
+ ____XXXX,XXXXX___,
+ ___XXX__,__XX____,
+ __XX_XX_,_XX_____,
+ ______XX,XX______,
+ ____XXX_,_XXX____,
+ _XXXX___,___XXXX_,
+ ___XXXXX,XXXXX___,
+ ___XX__X,X__XX___,
+ ___XX__X,X__XX___,
+ ___XXXXX,XXXXX___,
+ ___XX__X,X__XX___,
+ ___XX__X,X__XX___,
+ ___XXXXX,XXXXX___,
+ ________,________,
+ ________,________,
+};
+
+/* char: 本 code:0xB1BE */
+static GUI_CONST_STORAGE unsigned char acB1BE[32] = {
+ _______X,X_______,
+ _______X,X_______,
+ _______X,X_______,
+ _XXXXXXX,XXXXXXX_,
+ ______XX,XX______,
+ _____XXX,XXX_____,
+ _____XXX,XXX_____,
+ ____XX_X,X_XX____,
+ ___XX__X,X__XX___,
+ __XX___X,X___XX__,
+ _XX_XXXX,XXXX_XX_,
+ _______X,X_______,
+ _______X,X_______,
+ _______X,X_______,
+ ________,________,
+ ________,________,
+};
+
+/* char: 比 code:0xB1C8 */
+static GUI_CONST_STORAGE unsigned char acB1C8[32] = {
+ ________,XX______,
+ __XX____,XX______,
+ __XX____,XX______,
+ __XX____,XX__XX__,
+ __XX____,XX_XX___,
+ __XXXXXX,XXXX____,
+ __XX____,XXX_____,
+ __XX____,XX______,
+ __XX____,XX______,
+ __XX____,XX______,
+ __XX_XX_,XX______,
+ __XXXX__,XX___XX_,
+ __XXX___,XX___XX_,
+ __XX____,_XXXXXX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 闭 code:0xB1D5 */
+static GUI_CONST_STORAGE unsigned char acB1D5[32] = {
+ __XX____,________,
+ ___XXXXX,XXXXXXX_,
+ ________,_____XX_,
+ __XX____,_XX__XX_,
+ __XX____,_XX__XX_,
+ __XXXXXX,XXXXXXX_,
+ __XX____,XXX__XX_,
+ __XX___X,XXX__XX_,
+ __XX__XX,_XX__XX_,
+ __XX_XX_,_XX__XX_,
+ __XXXX__,_XX__XX_,
+ __XX___X,XXX__XX_,
+ __XX____,_____XX_,
+ __XX____,___XXXX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 编 code:0xB1E0 */
+static GUI_CONST_STORAGE unsigned char acB1E0[32] = {
+ ___XX___,_XX_____,
+ ___XX___,__XX____,
+ __XX_XXX,XXXXXXX_,
+ __XX_XXX,X____XX_,
+ _XXXXX_X,X____XX_,
+ ____XX_X,XXXXXXX_,
+ ___XX__X,X_______,
+ __XX___X,XXXXXXX_,
+ _XXXXXXX,XXXXXXX_,
+ ______XX,XXXXXXX_,
+ _______X,XXXXXXX_,
+ ____XXXX,XXXXXXX_,
+ _XXXX__X,XXXXXXX_,
+ _______X,X___XXX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 变 code:0xB1E4 */
+static GUI_CONST_STORAGE unsigned char acB1E4[32] = {
+ ______XX,________,
+ _______X,X_______,
+ _XXXXXXX,XXXXXXX_,
+ _____XX_,_XX_____,
+ ___XXXX_,_XXXX___,
+ ___XXXX_,_XX_XX__,
+ __XX_XX_,_XX__XX_,
+ _XX_____,_____XX_,
+ ___XXXXX,XXXXX___,
+ ____XX__,__XX____,
+ _____XX_,_XX_____,
+ ______XX,XX______,
+ ____XXX_,_XXX____,
+ _XXXX___,___XXXX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 表 code:0xB1ED */
+static GUI_CONST_STORAGE unsigned char acB1ED[32] = {
+ _______X,X_______,
+ _______X,X_______,
+ __XXXXXX,XXXXXX__,
+ _______X,X_______,
+ ___XXXXX,XXXXX___,
+ _______X,X_______,
+ _XXXXXXX,XXXXXXX_,
+ ______XX,XX______,
+ _____XX_,XX__XX__,
+ ____XXX_,_XXXX___,
+ ___XXXX_,__XX____,
+ _XXX_XXX,X__XX___,
+ _____XXX,____XXX_,
+ _____XX_,________,
+ ________,________,
+ ________,________,
+};
+
+/* char: 不 code:0xB2BB */
+static GUI_CONST_STORAGE unsigned char acB2BB[32] = {
+ ________,________,
+ _XXXXXXX,XXXXXXX_,
+ ________,XX______,
+ ________,XX______,
+ _______X,X_______,
+ ______XX,X_______,
+ _____XXX,X_XX____,
+ ____XX_X,X__XX___,
+ ___XX__X,X___XX__,
+ __XX___X,X____XX_,
+ _XX____X,X____XX_,
+ _______X,X_______,
+ _______X,X_______,
+ _______X,X_______,
+ ________,________,
+ ________,________,
+};
+
+/* char: 擦 code:0xB2C1 */
+static GUI_CONST_STORAGE unsigned char acB2C1[32] = {
+ ___XX___,_XX_____,
+ ___XX_XX,XXXXXXX_,
+ ___XX_XX,_____XX_,
+ _XXXXX_X,X__XX___,
+ ___XX__X,XXXXXXX_,
+ ___XX_XX,_XXXXXX_,
+ ___XX__X,XXXXXXX_,
+ ___XXXXX,XX__XX__,
+ _XXXX__X,XXXXXXX_,
+ ___XX_XX,________,
+ ___XX_XX,XXXXXXX_,
+ ___XX__X,X_XXXX__,
+ ___XX__X,X_XX_XX_,
+ _XXXX_XX,_XXX_XX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 参 code:0xB2CE */
+static GUI_CONST_STORAGE unsigned char acB2CE[32] = {
+ _____XX_,________,
+ ____XX__,__XX____,
+ ___XXXXX,XXXXX___,
+ ______XX,___XX___,
+ _XXXXXXX,XXXXXXX_,
+ ____XX__,__XX____,
+ ___XX___,XX_XX___,
+ _XXX__XX,X___XXX_,
+ ___XXXX_,_XX_____,
+ ________,XX______,
+ _____XXX,X__XX___,
+ __XXXX__,_XXX____,
+ ______XX,XX______,
+ _XXXXXX_,________,
+ ________,________,
+ ________,________,
+};
+
+/* char: 操 code:0xB2D9 */
+static GUI_CONST_STORAGE unsigned char acB2D9[32] = {
+ ___XX__X,XXXXX___,
+ ___XX__X,X__XX___,
+ ___XX__X,XXXXX___,
+ _XXXXX__,________,
+ ___XX_XX,XXXXXX__,
+ ___XX_XX,XXXXXX__,
+ ___XX_XX,XXXXXX__,
+ ___XXX__,________,
+ _XXXX___,_XX_____,
+ ___XXXXX,XXXXXXX_,
+ ___XX___,XXXX____,
+ ___XX__X,XXXXX___,
+ ___XXXXX,_XX_XXX_,
+ _XXXX___,_XX_____,
+ ________,________,
+ ________,________,
+};
+
+/* char: 测 code:0xB2E2 */
+static GUI_CONST_STORAGE unsigned char acB2E2[32] = {
+ ________,_____XX_,
+ __XX_XXX,XXX__XX_,
+ ___XXXX_,_XX__XX_,
+ _____XXX,XXXXXXX_,
+ _XX__XXX,XXXXXXX_,
+ __XX_XXX,XXXXXXX_,
+ _____XXX,XXXXXXX_,
+ ___XXXXX,XXXXXXX_,
+ ___XXXXX,XXXXXXX_,
+ __XX___X,X__XXXX_,
+ __XX__XX,XX___XX_,
+ _XX___XX,_XX__XX_,
+ _XX__XX_,_XX__XX_,
+ ____XX__,___XXXX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 差 code:0xB2EE */
+static GUI_CONST_STORAGE unsigned char acB2EE[32] = {
+ ____XX__,__XX____,
+ _____XX_,_XX_____,
+ __XXXXXX,XXXXXX__,
+ _______X,X_______,
+ ___XXXXX,XXXXX___,
+ ______XX,________,
+ _XXXXXXX,XXXXXXX_,
+ _____XX_,________,
+ ____XX__,________,
+ ___XXXXX,XXXXX___,
+ __XX____,XX______,
+ _XX_____,XX______,
+ ________,XX______,
+ ___XXXXX,XXXXXXX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 常 code:0xB3A3 */
+static GUI_CONST_STORAGE unsigned char acB3A3[32] = {
+ _______X,X_______,
+ ___XX__X,X__XX___,
+ ____XX_X,X_XX____,
+ _XXXXXXX,XXXXXXX_,
+ _XX_____,_____XX_,
+ ____XXXX,XXXX____,
+ ____XX__,__XX____,
+ ____XXXX,XXXX____,
+ _______X,X_______,
+ __XXXXXX,XXXXXX__,
+ __XX___X,X___XX__,
+ __XX___X,X___XX__,
+ __XX___X,X_XXXX__,
+ _______X,X_______,
+ ________,________,
+ ________,________,
+};
+
+/* char: 长 code:0xB3A4 */
+static GUI_CONST_STORAGE unsigned char acB3A4[32] = {
+ ____XX__,___XX___,
+ ____XX__,__XX____,
+ ____XX__,_XX_____,
+ ____XX__,XX______,
+ ____XX_X,X_______,
+ ____XX__,________,
+ _XXXXXXX,XXXXXXX_,
+ ____XX_X,X_______,
+ ____XX__,XX______,
+ ____XX__,_XX_____,
+ ____XX__,__XX____,
+ ____XXXX,___XX___,
+ ____XXX_,____XXX_,
+ ____XX__,________,
+ ________,________,
+ ________,________,
+};
+
+/* char: 厂 code:0xB3A7 */
+static GUI_CONST_STORAGE unsigned char acB3A7[32] = {
+ ________,________,
+ ___XXXXX,XXXXXXX_,
+ ___XX___,________,
+ ___XX___,________,
+ ___XX___,________,
+ ___XX___,________,
+ ___XX___,________,
+ ___XX___,________,
+ ___XX___,________,
+ ___XX___,________,
+ ___XX___,________,
+ __XX____,________,
+ __XX____,________,
+ _XX_____,________,
+ ________,________,
+ ________,________,
+};
+
+/* char: 称 code:0xB3C6 */
+static GUI_CONST_STORAGE unsigned char acB3C6[32] = {
+ ________,XX______,
+ ____XXX_,XX______,
+ _XXXX___,XX______,
+ ___XX___,XXXXXXX_,
+ ___XX__X,X____XX_,
+ _XXXXXXX,____XX__,
+ ___XX___,__XX____,
+ ___XXX__,__XX____,
+ __XXXXXX,X_XXXX__,
+ __XXX__X,X_XX_XX_,
+ _XXXX_XX,__XX_XX_,
+ ___XX___,__XX____,
+ ___XX___,__XX____,
+ ___XX___,XXXX____,
+ ________,________,
+ ________,________,
+};
+
+/* char: 成 code:0xB3C9 */
+static GUI_CONST_STORAGE unsigned char acB3C9[32] = {
+ ________,_XXXX___,
+ ________,_XX_XX__,
+ ________,_XX_____,
+ __XXXXXX,XXXXXXX_,
+ __XX____,_XX_____,
+ __XX____,_XX_XX__,
+ __XXXXXX,_XX_XX__,
+ __XX__XX,_XX_XX__,
+ __XX__XX,_XXXX___,
+ __XX__XX,_XXXX___,
+ __XX__XX,__XX_XX_,
+ __XXXXX_,_XXXXXX_,
+ __XX____,XX__XXX_,
+ _XX____X,X____XX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 程 code:0xB3CC */
+static GUI_CONST_STORAGE unsigned char acB3CC[32] = {
+ ________,________,
+ ____XXXX,XXXXXX__,
+ _XXXX__X,X___XX__,
+ ___XX__X,X___XX__,
+ ___XX__X,XXXXXX__,
+ _XXXXXX_,________,
+ ___XX___,________,
+ ___XXX_X,XXXXXX__,
+ __XXXXX_,_XX_____,
+ __XXX___,_XX_____,
+ _XXXX__X,XXXXXX__,
+ ___XX___,_XX_____,
+ ___XX___,_XX_____,
+ ___XX_XX,XXXXXXX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 出 code:0xB3F6 */
+static GUI_CONST_STORAGE unsigned char acB3F6[32] = {
+ _______X,X_______,
+ __XX___X,X___XX__,
+ __XX___X,X___XX__,
+ __XX___X,X___XX__,
+ __XX___X,X___XX__,
+ __XXXXXX,XXXXXX__,
+ _______X,X_______,
+ _______X,X_______,
+ _XX____X,X____XX_,
+ _XX____X,X____XX_,
+ _XX____X,X____XX_,
+ _XX____X,X____XX_,
+ _XXXXXXX,XXXXXXX_,
+ ________,_____XX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 储 code:0xB4A2 */
+static GUI_CONST_STORAGE unsigned char acB4A2[32] = {
+ ____XX__,__XX____,
+ ____XXX_,__XX_XX_,
+ ____XXXX,_XXXXXX_,
+ ___XX_XX,__XXXX__,
+ ___XX___,XXXXXXX_,
+ __XXXXXX,__XX____,
+ _XXXX_XX,_XXXXX__,
+ ___XX_XX,XXX_XX__,
+ ___XX_XX,XXX_XX__,
+ ___XX_XX,_XXXXX__,
+ ___XX_XX,_XX_XX__,
+ ___XX_XX,XXX_XX__,
+ ___XX_XX,_XXXXX__,
+ ___XX___,_XX_XX__,
+ ________,________,
+ ________,________,
+};
+
+/* char: 传 code:0xB4AB */
+static GUI_CONST_STORAGE unsigned char acB4AB[32] = {
+ ____XX__,_XX_____,
+ ____XX__,_XX_____,
+ ____XXXX,XXXXXX__,
+ ___XX___,_XX_____,
+ ___XX___,XX______,
+ __XXXXXX,XXXXXXX_,
+ _XXXX___,XX______,
+ ___XX__X,X_______,
+ ___XX_XX,XXXXXX__,
+ ___XX___,____XX__,
+ ___XX___,___XX___,
+ ___XX___,XXXX____,
+ ___XX___,_XX_____,
+ ___XX___,__XX____,
+ ________,________,
+ ________,________,
+};
+
+/* char: 磁 code:0xB4C5 */
+static GUI_CONST_STORAGE unsigned char acB4C5[32] = {
+ _______X,X___XX__,
+ ________,XX_XX___,
+ _XXXXXXX,XXXXXXX_,
+ ___XX___,________,
+ ___XX__X,X___XX__,
+ __XX___X,X___XX__,
+ __XXXXXX,___XX___,
+ _XXXXXXX,XX_XXXX_,
+ __XXXXXX,XXXXXXX_,
+ __XXXX_X,X___XX__,
+ __XXXX_X,X___XX__,
+ __XXXXXX,XX_XXXX_,
+ __XXXXXX,XXXXXXX_,
+ ________,XX___XX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 次 code:0xB4CE */
+static GUI_CONST_STORAGE unsigned char acB4CE[32] = {
+ _______X,X_______,
+ __XX___X,X_______,
+ ___XX__X,X_______,
+ ___XX__X,XXXXXXX_,
+ ______XX,_____XX_,
+ ______XX,____XX__,
+ _____XX_,_XX_____,
+ ___XX___,_XX_____,
+ ___XX___,_XX_____,
+ __XX____,XXXX____,
+ __XX____,XXXX____,
+ _XX____X,X__XX___,
+ _XX___XX,____XX__,
+ _____XX_,_____XX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 存 code:0xB4E6 */
+static GUI_CONST_STORAGE unsigned char acB4E6[32] = {
+ ______XX,________,
+ ______XX,________,
+ _XXXXXXX,XXXXXXX_,
+ _____XX_,________,
+ ____XX__,________,
+ ____XX_X,XXXXXX__,
+ ___XXX__,___XX___,
+ __XXXX__,__XX____,
+ _XX_XX__,__XX____,
+ ____XXXX,XXXXXXX_,
+ ____XX__,__XX____,
+ ____XX__,__XX____,
+ ____XX__,__XX____,
+ ____XX__,XXXX____,
+ ________,________,
+ ________,________,
+};
+
+/* char: 大 code:0xB4F3 */
+static GUI_CONST_STORAGE unsigned char acB4F3[32] = {
+ _______X,X_______,
+ _______X,X_______,
+ _______X,X_______,
+ _______X,X_______,
+ _XXXXXXX,XXXXXXX_,
+ _______X,X_______,
+ ______XX,XX______,
+ ______XX,XX______,
+ ______XX,XX______,
+ _____XX_,_XX_____,
+ _____XX_,_XX_____,
+ ____XX__,__XX____,
+ ___XX___,___XX___,
+ _XXX____,____XXX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 带 code:0xB4F8 */
+static GUI_CONST_STORAGE unsigned char acB4F8[32] = {
+ ____XX_X,X_XX____,
+ ____XX_X,X_XX____,
+ _XXXXXXX,XXXXXXX_,
+ ____XX_X,X_XX____,
+ ________,________,
+ _XXXXXXX,XXXXXXX_,
+ _XX____X,X____XX_,
+ _______X,X_______,
+ ___XXXXX,XXXXX___,
+ ___XX__X,X__XX___,
+ ___XX__X,X__XX___,
+ ___XX__X,X__XX___,
+ ___XX__X,XXXXX___,
+ _______X,X_______,
+ ________,________,
+ ________,________,
+};
+
+/* char: 待 code:0xB4FD */
+static GUI_CONST_STORAGE unsigned char acB4FD[32] = {
+ ____XX__,_XX_____,
+ ___XX___,_XX_____,
+ __XX__XX,XXXXXX__,
+ _XX_XX__,_XX_____,
+ ____XX__,_XX_____,
+ ___XXXXX,XXXXXXX_,
+ __XXX___,___XX___,
+ _XXXX___,___XX___,
+ ___XXXXX,XXXXXXX_,
+ ___XX___,___XX___,
+ ___XX_XX,___XX___,
+ ___XX__X,X__XX___,
+ ___XX___,___XX___,
+ ___XX___,_XXXX___,
+ ________,________,
+ ________,________,
+};
+
+/* char: 单 code:0xB5A5 */
+static GUI_CONST_STORAGE unsigned char acB5A5[32] = {
+ ____XX__,__XX____,
+ _____XX_,_XX_____,
+ ___XXXXX,XXXXX___,
+ ___XX__X,X__XX___,
+ ___XX__X,X__XX___,
+ ___XXXXX,XXXXX___,
+ ___XX__X,X__XX___,
+ ___XX__X,X__XX___,
+ ___XXXXX,XXXXX___,
+ _______X,X_______,
+ _______X,X_______,
+ _XXXXXXX,XXXXXXX_,
+ _______X,X_______,
+ _______X,X_______,
+ ________,________,
+ ________,________,
+};
+
+/* char: 弹 code:0xB5AF */
+static GUI_CONST_STORAGE unsigned char acB5AF[32] = {
+ _______X,X__XX___,
+ _XXXXX__,XXXX____,
+ ____XXXX,XXXXXX__,
+ ____XXXX,_XX_XX__,
+ _XXXXXXX,_XX_XX__,
+ _XX___XX,XXXXXX__,
+ _XX___XX,_XX_XX__,
+ _XX___XX,_XX_XX__,
+ _XXXXXXX,XXXXXX__,
+ ____XX__,_XX_____,
+ ____XX__,_XX_____,
+ ____XXXX,XXXXXXX_,
+ ____XX__,_XX_____,
+ __XXX___,_XX_____,
+ ________,________,
+ ________,________,
+};
+
+/* char: 当 code:0xB5B1 */
+static GUI_CONST_STORAGE unsigned char acB5B1[32] = {
+ _______X,X_______,
+ __XX___X,X___XX__,
+ ___XX__X,X__XX___,
+ ____XX_X,X_XX____,
+ _XXXXXXX,XXXXXX__,
+ ________,____XX__,
+ ________,____XX__,
+ ________,____XX__,
+ __XXXXXX,XXXXXX__,
+ ________,____XX__,
+ ________,____XX__,
+ ________,____XX__,
+ _XXXXXXX,XXXXXX__,
+ ________,____XX__,
+ ________,________,
+ ________,________,
+};
+
+/* char: 的 code:0xB5C4 */
+static GUI_CONST_STORAGE unsigned char acB5C4[32] = {
+ ____XX__,_XX_____,
+ ____XX__,_XX_____,
+ ___XX___,_XXXXXX_,
+ __XXXXXX,XX___XX_,
+ __XX__XX,X____XX_,
+ __XX__XX,_____XX_,
+ __XX__XX,_XX__XX_,
+ __XXXXXX,__XX_XX_,
+ __XX__XX,__XX_XX_,
+ __XX__XX,_____XX_,
+ __XX__XX,_____XX_,
+ __XX__XX,_____XX_,
+ __XXXXXX,_____XX_,
+ __XX__XX,___XXX__,
+ ________,________,
+ ________,________,
+};
+
+/* char: 低 code:0xB5CD */
+static GUI_CONST_STORAGE unsigned char acB5CD[32] = {
+ ____XX__,________,
+ ____XX__,__XXXX__,
+ ____XXXX,XXXX____,
+ ___XX_XX,__XX____,
+ ___XX_XX,__XX____,
+ __XXX_XX,__XX____,
+ _XXXX_XX,XXXXXXX_,
+ ___XX_XX,__XX____,
+ ___XX_XX,__XX____,
+ ___XX_XX,__XX____,
+ ___XX_XX,XX_XX___,
+ ___XX_XX,X__XXXX_,
+ ___XX_XX,_XX_XXX_,
+ ___XX___,__XX_XX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 地 code:0xB5D8 */
+static GUI_CONST_STORAGE unsigned char acB5D8[32] = {
+ ___XX___,_XX_____,
+ ___XX___,_XX_____,
+ ___XX_XX,_XX_XX__,
+ ___XX_XX,_XXXXX__,
+ _XXXXXXX,XXXXXX__,
+ ___XXXXX,XXX_XX__,
+ ___XX_XX,_XX_XX__,
+ ___XX_XX,_XX_XX__,
+ ___XX_XX,_XX_XX__,
+ ___XX_XX,_XXXXX__,
+ ___XXXXX,_XX_____,
+ _XXX__XX,_____XX_,
+ ______XX,_____XX_,
+ _______X,XXXXXXX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 点 code:0xB5E3 */
+static GUI_CONST_STORAGE unsigned char acB5E3[32] = {
+ ______XX,________,
+ ______XX,________,
+ ______XX,XXXXXX__,
+ ______XX,________,
+ ______XX,________,
+ ___XXXXX,XXXXX___,
+ ___XX___,___XX___,
+ ___XX___,___XX___,
+ ___XX___,___XX___,
+ ___XXXXX,XXXXX___,
+ ________,________,
+ __XX_XX_,XX__XX__,
+ __XX__XX,_XX__XX_,
+ _XX___XX,_XX__XX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 电 code:0xB5E7 */
+static GUI_CONST_STORAGE unsigned char acB5E7[32] = {
+ _______X,X_______,
+ _______X,X_______,
+ _______X,X_______,
+ __XXXXXX,XXXXXX__,
+ __XX___X,X___XX__,
+ __XX___X,X___XX__,
+ __XXXXXX,XXXXXX__,
+ __XX___X,X___XX__,
+ __XX___X,X___XX__,
+ __XXXXXX,XXXXXX__,
+ __XX___X,X_______,
+ _______X,X____XX_,
+ _______X,X____XX_,
+ ________,XXXXXXX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 定 code:0xB6A8 */
+static GUI_CONST_STORAGE unsigned char acB6A8[32] = {
+ ______XX,________,
+ _______X,X_______,
+ _XXXXXXX,XXXXXXX_,
+ _XX_____,_____XX_,
+ ________,________,
+ ___XXXXX,XXXXX___,
+ _______X,X_______,
+ _______X,X_______,
+ ___XX__X,X_______,
+ ___XX__X,XXXXX___,
+ ___XX__X,X_______,
+ ___XX__X,X_______,
+ __XXXX_X,X_______,
+ _XX__XXX,XXXXXXX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 动 code:0xB6AF */
+static GUI_CONST_STORAGE unsigned char acB6AF[32] = {
+ ________,_XX_____,
+ __XXXXX_,_XX_____,
+ ________,_XX_____,
+ _______X,XXXXXXX_,
+ ________,_XX__XX_,
+ _XXXXXXX,_XX__XX_,
+ ___XX___,_XX__XX_,
+ ___XX___,_XX__XX_,
+ __XX_XX_,_XX__XX_,
+ __XX__XX,_XX__XX_,
+ _XXXXXXX,XX___XX_,
+ ______XX,XX___XX_,
+ _______X,X____XX_,
+ ______XX,___XXX__,
+ ________,________,
+ ________,________,
+};
+
+/* char: 度 code:0xB6C8 */
+static GUI_CONST_STORAGE unsigned char acB6C8[32] = {
+ _______X,X_______,
+ ________,XX______,
+ ___XXXXX,XXXXXXX_,
+ ___XX_XX,___XX___,
+ ___XXXXX,XXXXXXX_,
+ ___XX_XX,___XX___,
+ ___XX_XX,XXXXX___,
+ ___XX___,________,
+ ___XXXXX,XXXXXX__,
+ ___XX_XX,___XX___,
+ ___XX__X,X_XX____,
+ __XX____,XXX_____,
+ __XX__XX,X_XXX___,
+ _XX_XXX_,____XXX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 短 code:0xB6CC */
+static GUI_CONST_STORAGE unsigned char acB6CC[32] = {
+ __XX____,________,
+ __XX___X,XXXXXX__,
+ __XXXXX_,________,
+ _XXXX___,________,
+ ___XX__X,XXXXXX__,
+ ___XX__X,X___XX__,
+ ___XX__X,X___XX__,
+ _XXXXXXX,X___XX__,
+ ___XX__X,XXXXXX__,
+ ___XX___,________,
+ __XXXX_X,X___XX__,
+ __XX_XX_,XX_XX___,
+ __XX_XX_,________,
+ _XX___XX,XXXXXXX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 断 code:0xB6CF */
+static GUI_CONST_STORAGE unsigned char acB6CF[32] = {
+ ____XX__,___XXX__,
+ _XX_XX__,XXXX____,
+ _XXXXXXX,XX______,
+ _XXXXXX_,XX______,
+ _XX_XX__,XX______,
+ _XXXXXXX,XXXXXXX_,
+ _XX_XX__,XX_XX___,
+ _XXXXXX_,XX_XX___,
+ _XXXXXXX,XX_XX___,
+ _XX_XXXX,XX_XX___,
+ _XX_XX__,XX_XX___,
+ _XX_XX__,XX_XX___,
+ _XX____X,X__XX___,
+ _XXXXXXX,___XX___,
+ ________,________,
+ ________,________,
+};
+
+/* char: 阀 code:0xB7A7 */
+static GUI_CONST_STORAGE unsigned char acB7A7[32] = {
+ ___XX___,________,
+ ____XXXX,XXXXXXX_,
+ ________,_____XX_,
+ __XX__XX,XXXX_XX_,
+ __XX__XX,XX_XXXX_,
+ __XX_XX_,XXXXXXX_,
+ __XXXXXX,XXX__XX_,
+ __XXXXX_,XXXX_XX_,
+ __XX_XX_,XXXX_XX_,
+ __XX_XX_,_XXXXXX_,
+ __XX_XX_,_XXXXXX_,
+ __XX_XX_,XXXXXXX_,
+ __XX_XXX,X__XXXX_,
+ __XX____,____XXX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 法 code:0xB7A8 */
+static GUI_CONST_STORAGE unsigned char acB7A8[32] = {
+ ________,_XX_____,
+ __XX____,_XX_____,
+ ___XX___,_XX_____,
+ ______XX,XXXXXX__,
+ _XX_____,_XX_____,
+ __XX____,_XX_____,
+ ________,_XX_____,
+ ___XXXXX,XXXXXXX_,
+ ___XX___,XX______,
+ __XX____,XX______,
+ __XX___X,X__XX___,
+ _XX___XX,____XX__,
+ _XX__XXX,XXXXXXX_,
+ ________,_____XX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 反 code:0xB7B4 */
+static GUI_CONST_STORAGE unsigned char acB7B4[32] = {
+ ________,_XXXXX__,
+ ___XXXXX,XX______,
+ ___XX___,________,
+ ___XX___,________,
+ ___XXXXX,XXXXX___,
+ ___XXXX_,___XX___,
+ ___XXXX_,___XX___,
+ ___XX_XX,__XX____,
+ ___XX_XX,__XX____,
+ ___XX__X,XXX_____,
+ __XX____,XX______,
+ __XX___X,XXX_____,
+ _XX__XXX,__XXX___,
+ ___XXX__,____XXX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 返 code:0xB7B5 */
+static GUI_CONST_STORAGE unsigned char acB7B5[32] = {
+ ________,__XXXX__,
+ __XX__XX,XXX_____,
+ ___XX_XX,________,
+ ___XX_XX,________,
+ ______XX,XXXXXX__,
+ ______XX,____XX__,
+ _XXXX_XX,XX_XX___,
+ ___XX_XX,_XXXX___,
+ ___XX_XX,__XX____,
+ ___XX_XX,_XXXX___,
+ ___XXXX_,XX__XX__,
+ ___XX__X,X___XX__,
+ __XXXX__,________,
+ _XX__XXX,XXXXXXX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 范 code:0xB7B6 */
+static GUI_CONST_STORAGE unsigned char acB7B6[32] = {
+ ____XX__,__XX____,
+ ____XX__,__XX____,
+ _XXXXXXX,XXXXXXX_,
+ ____XX__,__XX____,
+ ___XX___,________,
+ ____XX_X,XXXXXX__,
+ _______X,X___XX__,
+ __XX___X,X___XX__,
+ ___XX__X,X___XX__,
+ _______X,X_XXX___,
+ _____XXX,X_______,
+ ____XX_X,X____XX_,
+ ___XX__X,X____XX_,
+ __XX____,XXXXXXX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 方 code:0xB7BD */
+static GUI_CONST_STORAGE unsigned char acB7BD[32] = {
+ ______XX,________,
+ _______X,X_______,
+ _XXXXXXX,XXXXXXX_,
+ _____XX_,________,
+ _____XX_,________,
+ _____XX_,________,
+ _____XXX,XXXXX___,
+ _____XX_,___XX___,
+ _____XX_,___XX___,
+ ____XX__,___XX___,
+ ____XX__,___XX___,
+ ___XX___,___XX___,
+ __XX____,___XX___,
+ _XX_____,_XXX____,
+ ________,________,
+ ________,________,
+};
+
+/* char: 放 code:0xB7C5 */
+static GUI_CONST_STORAGE unsigned char acB7C5[32] = {
+ ___XX___,_XX_____,
+ ____XX__,_XX_____,
+ ________,_XX_____,
+ _XXXXXXX,_XXXXXX_,
+ ___XX___,XX__XX__,
+ ___XX__X,XXX_XX__,
+ ___XXXXX,_XX_XX__,
+ ___XX_XX,_XX_XX__,
+ ___XX_XX,_XXXX___,
+ ___XX_XX,_XXXX___,
+ ___XX_XX,__XX____,
+ __XX__XX,_XXXX___,
+ __XX__XX,XX__XX__,
+ _XX_XXXX,X____XX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 非 code:0xB7C7 */
+static GUI_CONST_STORAGE unsigned char acB7C7[32] = {
+ _____XX_,_XX_____,
+ _____XX_,_XX_____,
+ _XXXXXX_,_XXXXXX_,
+ _____XX_,_XX_____,
+ _____XX_,_XX_____,
+ _____XX_,_XX_____,
+ __XXXXX_,_XXXXX__,
+ _____XX_,_XX_____,
+ _____XX_,_XX_____,
+ _____XX_,_XX_____,
+ _XXXXXX_,_XXXXXX_,
+ _____XX_,_XX_____,
+ _____XX_,_XX_____,
+ _____XX_,_XX_____,
+ ________,________,
+ ________,________,
+};
+
+/* char: 分 code:0xB7D6 */
+static GUI_CONST_STORAGE unsigned char acB7D6[32] = {
+ _____XX_,_XX_____,
+ _____XX_,_XX_____,
+ ____XX__,__XX____,
+ ____XX__,__XX____,
+ ___XX___,___XX___,
+ __XX____,____XX__,
+ _XXXXXXX,XXXX_XX_,
+ _____XX_,__XX____,
+ _____XX_,__XX____,
+ _____XX_,__XX____,
+ ____XX__,__XX____,
+ ___XX___,__XX____,
+ __XX____,__XX____,
+ _XX_____,XXX_____,
+ ________,________,
+ ________,________,
+};
+
+/* char: 服 code:0xB7FE */
+static GUI_CONST_STORAGE unsigned char acB7FE[32] = {
+ ________,________,
+ __XXXXXX,XXXXXX__,
+ __XX_XXX,X___XX__,
+ __XX_XXX,X___XX__,
+ __XX_XXX,X_XXXX__,
+ __XXXXXX,X_______,
+ __XX_XXX,XXXXXX__,
+ __XX_XXX,XXX_XX__,
+ __XXXXXX,XXX_XX__,
+ __XX_XXX,XXXXX___,
+ __XX_XXX,X_XX____,
+ __XX_XXX,XXXXX___,
+ __XX_XXX,XX__XX__,
+ _XX_XXXX,X____XX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 复 code:0xB8B4 */
+static GUI_CONST_STORAGE unsigned char acB8B4[32] = {
+ ____XX__,________,
+ ____XXXX,XXXXXXX_,
+ ___XX___,________,
+ __XXXXXX,XXXXX___,
+ _XX_XX__,___XX___,
+ ____XXXX,XXXXX___,
+ ____XX__,___XX___,
+ ____XXXX,XXXXX___,
+ _____XX_,________,
+ ____XXXX,XXXXX___,
+ __XXXXX_,_XXX____,
+ ______XX,XX______,
+ ____XXX_,_XXX____,
+ _XXXX___,___XXXX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 感 code:0xB8D0 */
+static GUI_CONST_STORAGE unsigned char acB8D0[32] = {
+ ________,_XX_XX__,
+ __XXXXXX,XXXXXXX_,
+ __XX____,_XX_____,
+ __XXXXXX,XXX_XX__,
+ __XX____,_XX_XX__,
+ __XXXXXX,XXXXX___,
+ __XXXX_X,X_XX____,
+ __XXXXXX,XXXXXXX_,
+ __XX____,XX__XXX_,
+ _XX____X,X____XX_,
+ ______XX,________,
+ __XXXX_X,X___XX__,
+ __XXXX__,__XX_XX_,
+ _XX__XXX,XXXX_XX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 缸 code:0xB8D7 */
+static GUI_CONST_STORAGE unsigned char acB8D7[32] = {
+ ___XX___,________,
+ ___XX___,________,
+ ___XXXXX,XXXXXX__,
+ __XXXX__,__XX____,
+ _XX_XX__,__XX____,
+ ____XX__,__XX____,
+ _XXXXXXX,X_XX____,
+ ____XX__,__XX____,
+ ____XX__,__XX____,
+ __XXXXXX,__XX____,
+ __XXXXXX,__XX____,
+ __XXXXXX,__XX____,
+ __XXXXXX,__XX____,
+ __XXX_XX,XXXXXXX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 高 code:0xB8DF */
+static GUI_CONST_STORAGE unsigned char acB8DF[32] = {
+ ______XX,________,
+ _______X,X_______,
+ _XXXXXXX,XXXXXXX_,
+ ________,________,
+ ____XXXX,XXXX____,
+ ____XX__,__XX____,
+ ____XXXX,XXXX____,
+ ________,________,
+ __XXXXXX,XXXXXX__,
+ __XX____,____XX__,
+ __XX_XXX,XXX_XX__,
+ __XX_XX_,_XX_XX__,
+ __XX_XXX,XXX_XX__,
+ __XX____,___XXX__,
+ ________,________,
+ ________,________,
+};
+
+/* char: 割 code:0xB8EE */
+static GUI_CONST_STORAGE unsigned char acB8EE[32] = {
+ ____XX__,_____XX_,
+ _____XX_,_____XX_,
+ _XXXXXXX,XXX__XX_,
+ _XX__XX_,_XXXXXX_,
+ __XXXXXX,XX_XXXX_,
+ _____XX_,___XXXX_,
+ __XXXXXX,XX_XXXX_,
+ _____XX_,___XXXX_,
+ _XXXXXXX,XXXXXXX_,
+ _____XX_,___XXXX_,
+ __XXXXXX,XX___XX_,
+ __XX____,XX___XX_,
+ __XXXXXX,XX___XX_,
+ __XX____,XX_XXXX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 个 code:0xB8F6 */
+static GUI_CONST_STORAGE unsigned char acB8F6[32] = {
+ _______X,X_______,
+ _______X,X_______,
+ ______XX,XX______,
+ _____XX_,_XX_____,
+ ____XX__,__XX____,
+ ___XX__X,X__XX___,
+ _XXX___X,X___XXX_,
+ _______X,X_______,
+ _______X,X_______,
+ _______X,X_______,
+ _______X,X_______,
+ _______X,X_______,
+ _______X,X_______,
+ _______X,X_______,
+ ________,________,
+ ________,________,
+};
+
+/* char: 更 code:0xB8FC */
+static GUI_CONST_STORAGE unsigned char acB8FC[32] = {
+ ________,________,
+ _XXXXXXX,XXXXXXX_,
+ _______X,X_______,
+ __XXXXXX,XXXXXX__,
+ __XX___X,X___XX__,
+ __XXXXXX,XXXXXX__,
+ __XX___X,X___XX__,
+ __XX___X,X___XX__,
+ __XXXXXX,XXXXXX__,
+ ___XX__X,X_______,
+ ____XXXX,________,
+ _____XXX,________,
+ ___XXX_X,XXX_____,
+ _XXX____,__XXXXX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 工 code:0xB9A4 */
+static GUI_CONST_STORAGE unsigned char acB9A4[32] = {
+ ________,________,
+ __XXXXXX,XXXXXX__,
+ _______X,X_______,
+ _______X,X_______,
+ _______X,X_______,
+ _______X,X_______,
+ _______X,X_______,
+ _______X,X_______,
+ _______X,X_______,
+ _______X,X_______,
+ _______X,X_______,
+ _______X,X_______,
+ _XXXXXXX,XXXXXXX_,
+ ________,________,
+ ________,________,
+ ________,________,
+};
+
+/* char: 功 code:0xB9A6 */
+static GUI_CONST_STORAGE unsigned char acB9A6[32] = {
+ ________,XX______,
+ ________,XX______,
+ _XXXXXX_,XX______,
+ ___XX__X,XXXXXX__,
+ ___XX___,XX__XX__,
+ ___XX___,XX__XX__,
+ ___XX___,XX__XX__,
+ ___XX___,XX__XX__,
+ ___XX___,XX__XX__,
+ ___XXXX_,XX__XX__,
+ _XXX___X,X___XX__,
+ _______X,X___XX__,
+ ______XX,____XX__,
+ _____XX_,__XXX___,
+ ________,________,
+ ________,________,
+};
+
+/* char: 公 code:0xB9AB */
+static GUI_CONST_STORAGE unsigned char acB9AB[32] = {
+ ________,XX______,
+ _____XX_,XX______,
+ _____XX_,_XX_____,
+ ____XX__,_XX_____,
+ ____XX__,__XX____,
+ ___XX___,___XX___,
+ __XX__XX,____XX__,
+ _XX___XX,_____XX_,
+ _____XX_,________,
+ _____XX_,XX______,
+ ____XX__,_XX_____,
+ ___XX___,__XX____,
+ __XXXXXX,XXXXX___,
+ ________,___XX___,
+ ________,________,
+ ________,________,
+};
+
+/* char: 构 code:0xB9B9 */
+static GUI_CONST_STORAGE unsigned char acB9B9[32] = {
+ ___XX___,XX______,
+ ___XX___,XX______,
+ ___XX___,XXXXXXX_,
+ _XXXXXXX,X____XX_,
+ ___XX_XX,_____XX_,
+ ___XX___,_XX__XX_,
+ __XXXX__,_XX__XX_,
+ __XXXXX_,XX___XX_,
+ _XXXX___,XXXX_XX_,
+ ___XX__X,XXXXXXX_,
+ ___XX___,___XXXX_,
+ ___XX___,_____XX_,
+ ___XX___,_____XX_,
+ ___XX___,___XXX__,
+ ________,________,
+ ________,________,
+};
+
+/* char: 故 code:0xB9CA */
+static GUI_CONST_STORAGE unsigned char acB9CA[32] = {
+ ____XX__,_XX_____,
+ ____XX__,_XX_____,
+ ____XX__,_XX_____,
+ _XXXXXXX,_XXXXXX_,
+ ____XX__,XX__XX__,
+ ____XX_X,XXX_XX__,
+ ____XX__,_XX_XX__,
+ __XXXXXX,_XX_XX__,
+ __XX__XX,_XXXX___,
+ __XX__XX,_XXXX___,
+ __XX__XX,__XX____,
+ __XXXXXX,_XXXX___,
+ __XX____,XX__XX__,
+ _______X,X____XX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 固 code:0xB9CC */
+static GUI_CONST_STORAGE unsigned char acB9CC[32] = {
+ __XXXXXX,XXXXXXX_,
+ __XX___X,X____XX_,
+ __XX___X,X____XX_,
+ __XXXXXX,XXXXXXX_,
+ __XX___X,X____XX_,
+ __XX___X,X____XX_,
+ __XXXXXX,XXXX_XX_,
+ __XXXX__,__XX_XX_,
+ __XXXX__,__XX_XX_,
+ __XXXXXX,XXXX_XX_,
+ __XX____,_____XX_,
+ __XX____,_____XX_,
+ __XXXXXX,XXXXXXX_,
+ __XX____,_____XX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 关 code:0xB9D8 */
+static GUI_CONST_STORAGE unsigned char acB9D8[32] = {
+ ____XX__,__XX____,
+ _____XX_,__XX____,
+ _____XX_,_XX_____,
+ __XXXXXX,XXXXXX__,
+ _______X,X_______,
+ _______X,X_______,
+ _______X,X_______,
+ _XXXXXXX,XXXXXXX_,
+ ______XX,XX______,
+ ______XX,XX______,
+ _____XX_,_XX_____,
+ ____XX__,__XX____,
+ ___XX___,___XX___,
+ _XXX____,____XXX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 过 code:0xB9FD */
+static GUI_CONST_STORAGE unsigned char acB9FD[32] = {
+ ________,___XX___,
+ __XX____,___XX___,
+ ___XX___,___XX___,
+ ___XXXXX,XXXXXXX_,
+ ________,___XX___,
+ ______XX,___XX___,
+ _XXXX__X,X__XX___,
+ ___XX__X,X__XX___,
+ ___XX___,___XX___,
+ ___XX___,___XX___,
+ ___XX___,___XX___,
+ ___XX___,_XXXX___,
+ __XXXX__,________,
+ _XX__XXX,XXXXXXX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 耗 code:0xBAC4 */
+static GUI_CONST_STORAGE unsigned char acBAC4[32] = {
+ ____XX__,___XXX__,
+ ____XX__,XXXX____,
+ ____XX__,_XX_____,
+ _XXXXXXX,_XX_____,
+ ____XX__,_XXXXX__,
+ __XXXXXX,XXXX____,
+ ____XX__,_XX_____,
+ _XXXXXXX,_XX_____,
+ ___XXX__,_XXXXXX_,
+ ___XXXXX,XXXX____,
+ __XXXXXX,_XX_____,
+ __XXXX__,_XX__XX_,
+ _XX_XX__,_XX__XX_,
+ ____XX__,__XXXXX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 号 code:0xBAC5 */
+static GUI_CONST_STORAGE unsigned char acBAC5[32] = {
+ ___XXXXX,XXXXX___,
+ ___XX___,___XX___,
+ ___XX___,___XX___,
+ ___XXXXX,XXXXX___,
+ ________,________,
+ ________,________,
+ _XXXXXXX,XXXXXXX_,
+ _____XX_,________,
+ ____XX__,________,
+ ___XXXXX,XXXXX___,
+ ________,___XX___,
+ ________,___XX___,
+ ________,___XX___,
+ ________,_XXX____,
+ ________,________,
+ ________,________,
+};
+
+/* char: 和 code:0xBACD */
+static GUI_CONST_STORAGE unsigned char acBACD[32] = {
+ _____XXX,________,
+ __XXXX__,________,
+ ____XX__,XXXXXXX_,
+ ____XX__,XX___XX_,
+ _XXXXXXX,XX___XX_,
+ ____XX__,XX___XX_,
+ ___XXX__,XX___XX_,
+ ___XXXX_,XX___XX_,
+ __XXXXXX,XX___XX_,
+ __XXXX__,XX___XX_,
+ _XX_XX__,XXXXXXX_,
+ ____XX__,XX___XX_,
+ ____XX__,________,
+ ____XX__,________,
+ ________,________,
+ ________,________,
+};
+
+/* char: 恒 code:0xBAE3 */
+static GUI_CONST_STORAGE unsigned char acBAE3[32] = {
+ ___XX___,________,
+ ___XX_XX,XXXXXXX_,
+ ___XX___,________,
+ ___XXX__,________,
+ _XXXXXXX,XXXXXX__,
+ _XXXX__X,X___XX__,
+ _XXXX__X,X___XX__,
+ ___XX__X,XXXXXX__,
+ ___XX__X,X___XX__,
+ ___XX__X,X___XX__,
+ ___XX__X,XXXXXX__,
+ ___XX___,________,
+ ___XX___,________,
+ ___XX_XX,XXXXXXX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 护 code:0xBBA4 */
+static GUI_CONST_STORAGE unsigned char acBBA4[32] = {
+ ___XX___,_XX_____,
+ ___XX___,__XX____,
+ ___XX__X,XXXXXXX_,
+ _XXXXXXX,X____XX_,
+ ___XX__X,X____XX_,
+ ___XX__X,X____XX_,
+ ___XXXXX,XXXXXXX_,
+ ___XXX_X,X____XX_,
+ _XXXX__X,X_______,
+ ___XX__X,X_______,
+ ___XX__X,X_______,
+ ___XX_XX,________,
+ ___XX_XX,________,
+ _XXXXXX_,________,
+ ________,________,
+ ________,________,
+};
+
+/* char: 欢 code:0xBBB6 */
+static GUI_CONST_STORAGE unsigned char acBBB6[32] = {
+ ________,_XX_____,
+ ________,_XX_____,
+ __XXXXXX,_XX_____,
+ ______XX,XXXXXXX_,
+ ______XX,XX___XX_,
+ __XX_XXX,X_XXXX__,
+ ___XXXX_,__XX____,
+ ____XX__,__XX____,
+ ____XXX_,__XX____,
+ ___XXXX_,__XX____,
+ ___XX_XX,_XXXX___,
+ __XX__XX,_XXXX___,
+ _XX_____,XX__XX__,
+ _______X,X____XX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 环 code:0xBBB7 */
+static GUI_CONST_STORAGE unsigned char acBBB7[32] = {
+ ________,________,
+ ______XX,XXXXXXX_,
+ _XXXXXX_,__XX____,
+ ___XX___,__XX____,
+ ___XX___,_XX_____,
+ ___XX___,_XX_____,
+ _XXXXXX_,XXXXX___,
+ ___XX__X,XXX_XX__,
+ ___XX_XX,_XX__XX_,
+ ___XX___,_XX__XX_,
+ ___XXXX_,_XX_____,
+ _XXXX___,_XX_____,
+ ________,_XX_____,
+ ________,_XX_____,
+ ________,________,
+ ________,________,
+};
+
+/* char: 换 code:0xBBBB */
+static GUI_CONST_STORAGE unsigned char acBBBB[32] = {
+ ___XX__X,X_______,
+ ___XX__X,X_______,
+ ___XX__X,XXXXX___,
+ _XXXXXXX,___XX___,
+ ___XXXX_,__XX____,
+ ___XX_XX,XXXXXX__,
+ ___XX_XX,_XX_XX__,
+ ___XXXXX,_XX_XX__,
+ _XXXX_XX,_XX_XX__,
+ ___XXXXX,XXXXXXX_,
+ ___XX___,XXXX____,
+ ___XX__X,X__XX___,
+ ___XX_XX,____XX__,
+ _XXXXXX_,_____XX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 簧 code:0xBBC9 */
+static GUI_CONST_STORAGE unsigned char acBBC9[32] = {
+ ___XX___,_XX_____,
+ __XXXXXX,XXXXXXX_,
+ _XX__XX_,XX_XX___,
+ _____XX_,_XX_____,
+ ___XXXXX,XXXXX___,
+ _____XX_,_XX_____,
+ _XXXXXXX,XXXXXXX_,
+ _______X,X_______,
+ ___XXXXX,XXXXX___,
+ ___XX__X,X__XX___,
+ ___XXXXX,XXXXX___,
+ ___XX__X,X__XX___,
+ ___XXXXX,XXXXX___,
+ ____XX__,__XX____,
+ ________,________,
+ ________,________,
+};
+
+/* char: 恢 code:0xBBD6 */
+static GUI_CONST_STORAGE unsigned char acBBD6[32] = {
+ ___XX___,_XX_____,
+ ___XX___,_XX_____,
+ ___XX___,_XX_____,
+ ___XXXXX,XXXXXXX_,
+ _XXXXXX_,XX______,
+ _XXXX__X,X_XX____,
+ _XXXX__X,X_XX_XX_,
+ ___XX_XX,XXXX_XX_,
+ ___XXXX_,XXXXXX__,
+ ___XX__X,XXXXX___,
+ ___XX___,_XXXX___,
+ ___XX___,XX__XX__,
+ ___XX__X,X___XX__,
+ ___XX_XX,_____XX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 回 code:0xBBD8 */
+static GUI_CONST_STORAGE unsigned char acBBD8[32] = {
+ ________,________,
+ __XXXXXX,XXXXXXX_,
+ __XX____,_____XX_,
+ __XX____,_____XX_,
+ __XX_XXX,XXXX_XX_,
+ __XX_XX_,__XX_XX_,
+ __XX_XX_,__XX_XX_,
+ __XX_XX_,__XX_XX_,
+ __XX_XX_,__XX_XX_,
+ __XX_XXX,XXXX_XX_,
+ __XX____,_____XX_,
+ __XX____,_____XX_,
+ __XXXXXX,XXXXXXX_,
+ __XX____,_____XX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 基 code:0xBBF9 */
+static GUI_CONST_STORAGE unsigned char acBBF9[32] = {
+ ____XX__,__XX____,
+ __XXXXXX,XXXXXX__,
+ ____XX__,__XX____,
+ ____XXXX,XXXX____,
+ ____XX__,__XX____,
+ ____XXXX,XXXX____,
+ ____XX__,__XX____,
+ _XXXXXXX,XXXXXXX_,
+ ___XX___,___XX___,
+ __XX___X,X___XX__,
+ _XX_XXXX,XXXX_XX_,
+ _______X,X_______,
+ _______X,X_______,
+ _XXXXXXX,XXXXXXX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 机 code:0xBBFA */
+static GUI_CONST_STORAGE unsigned char acBBFA[32] = {
+ ___XX___,________,
+ ___XX__X,XXXXX___,
+ ___XX__X,X__XX___,
+ _XXXXXXX,X__XX___,
+ ___XX__X,X__XX___,
+ ___XX__X,X__XX___,
+ __XXXX_X,X__XX___,
+ __XXXXXX,X__XX___,
+ _XXXX__X,X__XX___,
+ ___XX__X,X__XX___,
+ ___XX__X,X__XX___,
+ ___XX_XX,___XXXX_,
+ ___XX_XX,___XXXX_,
+ ___XXXX_,____XXX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 积 code:0xBBFD */
+static GUI_CONST_STORAGE unsigned char acBBFD[32] = {
+ ________,________,
+ ____XXXX,XXXXXX__,
+ _XXXX__X,X___XX__,
+ ___XX__X,X___XX__,
+ ___XX__X,X___XX__,
+ _XXXXXXX,X___XX__,
+ ___XX__X,X___XX__,
+ ___XXX_X,XXXXXX__,
+ __XXXXX_,________,
+ __XXX___,________,
+ _XXXX___,XX_XX___,
+ ___XX___,XX__XX__,
+ ___XX__X,X____XX_,
+ ___XX_XX,_____XX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 辑 code:0xBCAD */
+static GUI_CONST_STORAGE unsigned char acBCAD[32] = {
+ ___XX___,________,
+ ___XX__X,XXXXXX__,
+ _XXXXXXX,X___XX__,
+ __XX___X,XXXXXX__,
+ __XX____,________,
+ _XXXX_XX,XXXXXXX_,
+ _XXXXXXX,X___XX__,
+ ___XX__X,XXXXXX__,
+ ___XX__X,X___XX__,
+ ___XXXXX,XXXXXX__,
+ _XXXX__X,X___XX__,
+ ___XX__X,X_XXXXX_,
+ ___XX_XX,XXX_XX__,
+ ___XX___,____XX__,
+ ________,________,
+ ________,________,
+};
+
+/* char: 技 code:0xBCBC */
+static GUI_CONST_STORAGE unsigned char acBCBC[32] = {
+ ___XX___,_XX_____,
+ ___XX___,_XX_____,
+ ___XX___,_XX_____,
+ _XXXXXXX,XXXXXX__,
+ ___XX___,_XX_____,
+ ___XX___,_XX_____,
+ ___XX_XX,XXXXX___,
+ ___XXX_X,X__XX___,
+ _XXXX__X,X__XX___,
+ ___XX___,XXXX____,
+ ___XX___,_XX_____,
+ ___XX___,XXXX____,
+ ___XX__X,X__XX___,
+ _XXXXXXX,____XXX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 计 code:0xBCC6 */
+static GUI_CONST_STORAGE unsigned char acBCC6[32] = {
+ __XX____,_XX_____,
+ ___XX___,_XX_____,
+ ___XX___,_XX_____,
+ ________,_XX_____,
+ ________,_XX_____,
+ _XXXXXXX,XXXXXXX_,
+ ___XX___,_XX_____,
+ ___XX___,_XX_____,
+ ___XX___,_XX_____,
+ ___XX___,_XX_____,
+ ___XXXX_,_XX_____,
+ ___XXX__,_XX_____,
+ ___XX___,_XX_____,
+ ________,_XX_____,
+ ________,________,
+ ________,________,
+};
+
+/* char: 记 code:0xBCC7 */
+static GUI_CONST_STORAGE unsigned char acBCC7[32] = {
+ __XX____,________,
+ ___XX_XX,XXXXXX__,
+ ___XX___,____XX__,
+ ________,____XX__,
+ ________,____XX__,
+ _XXXX___,____XX__,
+ ___XX_XX,XXXXXX__,
+ ___XX_XX,________,
+ ___XX_XX,________,
+ ___XX_XX,________,
+ ___XXXXX,________,
+ ___XXXXX,_____XX_,
+ ___XX_XX,_____XX_,
+ _______X,XXXXXXX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 加 code:0xBCD3 */
+static GUI_CONST_STORAGE unsigned char acBCD3[32] = {
+ ____XX__,________,
+ ____XX__,________,
+ ____XX__,________,
+ _XXXXXXX,XXXXXXX_,
+ ____XX_X,XXX__XX_,
+ ____XX_X,XXX__XX_,
+ ____XX_X,XXX__XX_,
+ ____XX_X,XXX__XX_,
+ ___XX__X,XXX__XX_,
+ ___XX__X,XXX__XX_,
+ ___XX__X,XXX__XX_,
+ __XX___X,XXXXXXX_,
+ __XX___X,XXX__XX_,
+ _XX__XXX,________,
+ ________,________,
+ ________,________,
+};
+
+/* char: 间 code:0xBCE4 */
+static GUI_CONST_STORAGE unsigned char acBCE4[32] = {
+ ___XX___,________,
+ ____XXXX,XXXXXXX_,
+ ____XX__,_____XX_,
+ __XX____,_____XX_,
+ __XX_XXX,XXXX_XX_,
+ __XX_XX_,__XX_XX_,
+ __XX_XX_,__XX_XX_,
+ __XX_XXX,XXXX_XX_,
+ __XX_XX_,__XX_XX_,
+ __XX_XX_,__XX_XX_,
+ __XX_XXX,XXXX_XX_,
+ __XX____,_____XX_,
+ __XX____,_____XX_,
+ __XX____,___XXXX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 减 code:0xBCF5 */
+static GUI_CONST_STORAGE unsigned char acBCF5[32] = {
+ ________,___XXXX_,
+ __XX____,___XX___,
+ ___XXXXX,XXXXXXX_,
+ ___XXXX_,___XX___,
+ _____XX_,___XX___,
+ _____XXX,XXXXX___,
+ _____XX_,___XXXX_,
+ ___XXXXX,XXXXXXX_,
+ ___XXXXX,XXXXXX__,
+ __XX_XXX,XXXXXX__,
+ __XX_XXX,XXXXXXX_,
+ _XX__XX_,__XXXXX_,
+ _XX__XX_,_XX_XXX_,
+ ____XX__,XX___XX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 件 code:0xBCFE */
+static GUI_CONST_STORAGE unsigned char acBCFE[32] = {
+ ____XX__,_XX_____,
+ ____XXXX,_XX_____,
+ ___XX_XX,_XX_____,
+ ___XX_XX,XXXXXX__,
+ __XXXXX_,_XX_____,
+ _XXXX___,_XX_____,
+ ___XX___,_XX_____,
+ ___XX___,_XX_____,
+ ___XXXXX,XXXXXXX_,
+ ___XX___,_XX_____,
+ ___XX___,_XX_____,
+ ___XX___,_XX_____,
+ ___XX___,_XX_____,
+ ___XX___,_XX_____,
+ ________,________,
+ ________,________,
+};
+
+/* char: 江 code:0xBDAD */
+static GUI_CONST_STORAGE unsigned char acBDAD[32] = {
+ ________,________,
+ __XX____,________,
+ ___XX_XX,XXXXXX__,
+ ____XX__,_XX_____,
+ ________,_XX_____,
+ _XX_____,_XX_____,
+ __XX____,_XX_____,
+ ________,_XX_____,
+ ____XX__,_XX_____,
+ ____XX__,_XX_____,
+ ___XX___,_XX_____,
+ ___XX___,_XX_____,
+ __XX____,_XX_____,
+ __XX_XXX,XXXXXXX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 角 code:0xBDC7 */
+static GUI_CONST_STORAGE unsigned char acBDC7[32] = {
+ _____XX_,________,
+ ____XXXX,XXXX____,
+ ___XX___,_XX_____,
+ __XX____,XX______,
+ _XXXXXXX,XXXXXX__,
+ ___XX__X,X___XX__,
+ ___XX__X,X___XX__,
+ ___XXXXX,XXXXXX__,
+ ___XX__X,X___XX__,
+ ___XX__X,X___XX__,
+ ___XXXXX,XXXXXX__,
+ __XX___X,X___XX__,
+ __XX___X,X___XX__,
+ _XX_____,__XXXX__,
+ ________,________,
+ ________,________,
+};
+
+/* char: 进 code:0xBDF8 */
+static GUI_CONST_STORAGE unsigned char acBDF8[32] = {
+ _______X,X__XX___,
+ __XX___X,X__XX___,
+ ___XX__X,X__XX___,
+ ___XXXXX,XXXXXXX_,
+ _______X,X__XX___,
+ _______X,X__XX___,
+ _XXXX__X,X__XX___,
+ ___XXXXX,XXXXXXX_,
+ ___XX__X,X__XX___,
+ ___XX__X,X__XX___,
+ ___XX__X,X__XX___,
+ ___XX_XX,___XX___,
+ __XXXX__,________,
+ _XX__XXX,XXXXXXX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 尽 code:0xBEA1 */
+static GUI_CONST_STORAGE unsigned char acBEA1[32] = {
+ ________,________,
+ ___XXXXX,XXXXXX__,
+ ___XX___,____XX__,
+ ___XX___,____XX__,
+ ___XXXXX,XXXXXX__,
+ ___XX___,XX______,
+ ___XX___,_XX_____,
+ __XX____,__XX____,
+ __XX_XXX,___XX___,
+ _XX____X,XX__XXX_,
+ ________,________,
+ ____XXXX,________,
+ _______X,XX______,
+ ________,_XXX____,
+ ________,________,
+ ________,________,
+};
+
+/* char: 警 code:0xBEAF */
+static GUI_CONST_STORAGE unsigned char acBEAF[32] = {
+ ___XX_XX,__XX____,
+ __XXXXXX,XXXXXXX_,
+ ___XX_XX,XX__XX__,
+ __XXXXXX,XXX_XX__,
+ _XXXXXXX,X_XXX___,
+ ___XXXXX,XXX_XXX_,
+ ______XX,X_______,
+ _XXXXXXX,XXXXXXX_,
+ ________,________,
+ ___XXXXX,XXXXX___,
+ ________,________,
+ ___XXXXX,XXXXX___,
+ ___XX___,___XX___,
+ ___XXXXX,XXXXX___,
+ ________,________,
+ ________,________,
+};
+
+/* char: 境 code:0xBEB3 */
+static GUI_CONST_STORAGE unsigned char acBEB3[32] = {
+ ___XX___,_XX_____,
+ ___XX_XX,XXXXXX__,
+ ___XX__X,X__XX___,
+ ___XX___,XXXX____,
+ _XXXXXXX,XXXXXXX_,
+ ___XX___,________,
+ ___XX_XX,XXXXXX__,
+ ___XX_XX,____XX__,
+ ___XX_XX,XXXXXX__,
+ ___XX_XX,____XX__,
+ ___XXXXX,XXXXXX__,
+ _XXX____,XXXX____,
+ _______X,X_XX_XX_,
+ _____XXX,___XXXX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 据 code:0xBEDD */
+static GUI_CONST_STORAGE unsigned char acBEDD[32] = {
+ ___XX___,________,
+ ___XX_XX,XXXXXX__,
+ ___XX_XX,____XX__,
+ _XXXXXXX,____XX__,
+ ___XX_XX,XXXXXX__,
+ ___XX_XX,__XX____,
+ ___XX_XX,__XX____,
+ ___XXXXX,XXXXXXX_,
+ _XXXX_XX,__XX____,
+ ___XX_XX,__XX____,
+ ___XX_XX,XXXXXX__,
+ ___XXXX_,XX__XX__,
+ ___XXXX_,XX__XX__,
+ _XXXXX__,XXXXXX__,
+ ________,________,
+ ________,________,
+};
+
+/* char: 巨 code:0xBEDE */
+static GUI_CONST_STORAGE unsigned char acBEDE[32] = {
+ ________,________,
+ __XXXXXX,XXXXXX__,
+ __XX____,________,
+ __XX____,________,
+ __XX____,________,
+ __XXXXXX,XXXXX___,
+ __XX____,___XX___,
+ __XX____,___XX___,
+ __XX____,___XX___,
+ __XXXXXX,XXXXX___,
+ __XX____,________,
+ __XX____,________,
+ __XX____,________,
+ __XXXXXX,XXXXXXX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 开 code:0xBFAA */
+static GUI_CONST_STORAGE unsigned char acBFAA[32] = {
+ __XXXXXX,XXXXXX__,
+ ____XX__,__XX____,
+ ____XX__,__XX____,
+ ____XX__,__XX____,
+ ____XX__,__XX____,
+ ____XX__,__XX____,
+ _XXXXXXX,XXXXXXX_,
+ ____XX__,__XX____,
+ ____XX__,__XX____,
+ ____XX__,__XX____,
+ ___XX___,__XX____,
+ ___XX___,__XX____,
+ __XX____,__XX____,
+ _XX_____,__XX____,
+ ________,________,
+ ________,________,
+};
+
+/* char: 可 code:0xBFC9 */
+static GUI_CONST_STORAGE unsigned char acBFC9[32] = {
+ ________,________,
+ _XXXXXXX,XXXXXXX_,
+ ________,___XX___,
+ ________,___XX___,
+ ___XXXXX,XX_XX___,
+ ___XX___,XX_XX___,
+ ___XX___,XX_XX___,
+ ___XX___,XX_XX___,
+ ___XX___,XX_XX___,
+ ___XXXXX,XX_XX___,
+ ___XX___,___XX___,
+ ________,___XX___,
+ ________,___XX___,
+ ________,_XXXX___,
+ ________,________,
+ ________,________,
+};
+
+/* char: 空 code:0xBFD5 */
+static GUI_CONST_STORAGE unsigned char acBFD5[32] = {
+ ______XX,________,
+ _______X,X_______,
+ _XXXXXXX,XXXXXXX_,
+ _XX__XX_,_XX__XX_,
+ _XX_XX__,__XX_XX_,
+ ___XX___,___XX___,
+ ________,________,
+ ___XXXXX,XXXXX___,
+ _______X,X_______,
+ _______X,X_______,
+ _______X,X_______,
+ _______X,X_______,
+ _______X,X_______,
+ _XXXXXXX,XXXXXXX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 控 code:0xBFD8 */
+static GUI_CONST_STORAGE unsigned char acBFD8[32] = {
+ ___XX___,XX______,
+ ___XX___,_XX_____,
+ ___XX_XX,XXXXXXX_,
+ _XXXXXXX,_____XX_,
+ ___XX___,XX_XX___,
+ ___XX__X,X___XX__,
+ ___XX_XX,_____XX_,
+ ___XXX__,________,
+ _XXXX__X,XXXXXX__,
+ ___XX___,_XX_____,
+ ___XX___,_XX_____,
+ ___XX___,_XX_____,
+ ___XX___,_XX_____,
+ _XXXX_XX,XXXXXXX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 跨 code:0xBFE7 */
+static GUI_CONST_STORAGE unsigned char acBFE7[32] = {
+ ________,_XX_____,
+ _XXXXX__,_XX_____,
+ _XX_XXXX,XXXXXXX_,
+ _XX_XX__,XX_XX___,
+ _XX_XX_X,X___XX__,
+ _XXXXXXX,XXXXXXX_,
+ ___XX___,________,
+ _XXXX_XX,XXXXXXX_,
+ _XXXXX_X,X_______,
+ _XXXX__X,XXXXXX__,
+ _XXXX___,____XX__,
+ _XXXXX__,____XX__,
+ _XXX____,____XX__,
+ ________,__XXX___,
+ ________,________,
+ ________,________,
+};
+
+/* char: 块 code:0xBFE9 */
+static GUI_CONST_STORAGE unsigned char acBFE9[32] = {
+ ___XX___,XX______,
+ ___XX___,XX______,
+ ___XX_XX,XXXXXX__,
+ ___XX___,XX__XX__,
+ _XXXXXX_,XX__XX__,
+ ___XX___,XX__XX__,
+ ___XX___,XX__XX__,
+ ___XXXXX,XXXXXXX_,
+ ___XX___,XXXX____,
+ ___XXXX_,XXXX____,
+ _XXXX__X,X__XX___,
+ _______X,X__XX___,
+ ______XX,____XX__,
+ _____XX_,_____XX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 蓝 code:0xC0B6 */
+static GUI_CONST_STORAGE unsigned char acC0B6[32] = {
+ ____XX__,__XX____,
+ _XXXXXXX,XXXXXXX_,
+ ____XX__,__XX____,
+ ________,________,
+ _____XX_,XX______,
+ __XX_XX_,XXXXXX__,
+ __XX_XXX,X_XX____,
+ __XX_XXX,___XX___,
+ _____XX_,____XX__,
+ ___XXXXX,XXXXX___,
+ ___XX_XX,XX_XX___,
+ ___XX_XX,XX_XX___,
+ ___XX_XX,XX_XX___,
+ _XXXXXXX,XXXXXXX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 累 code:0xC0DB */
+static GUI_CONST_STORAGE unsigned char acC0DB[32] = {
+ __XXXXXX,XXXXXX__,
+ __XX___X,X___XX__,
+ __XXXXXX,XXXXXX__,
+ __XX___X,X___XX__,
+ __XXXXXX,XXXXXX__,
+ _____XX_,________,
+ ____XX__,_XX_____,
+ ___XXXXX,XX______,
+ ______XX,___XX___,
+ __XXXXXX,XXXXXX__,
+ _______X,X___XX__,
+ ___XX__X,X_XX____,
+ __XX___X,X__XX___,
+ _XX__XXX,X___XX__,
+ ________,________,
+ ________,________,
+};
+
+/* char: 类 code:0xC0E0 */
+static GUI_CONST_STORAGE unsigned char acC0E0[32] = {
+ _______X,X_______,
+ ___XX__X,X__XX___,
+ ____XX_X,X_XX____,
+ _XXXXXXX,XXXXXXX_,
+ _____XXX,XXX_____,
+ ____XX_X,X_XX____,
+ ___XX__X,X__XX___,
+ _XXX____,____XX__,
+ _______X,X_______,
+ _XXXXXXX,XXXXXXX_,
+ ______XX,XX______,
+ _____XX_,_XX_____,
+ ___XXX__,__XXX___,
+ _XXX____,____XXX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 离 code:0xC0EB */
+static GUI_CONST_STORAGE unsigned char acC0EB[32] = {
+ ______XX,________,
+ _______X,X_______,
+ _XXXXXXX,XXXXXXX_,
+ ________,________,
+ ___XXXX_,_XXXX___,
+ ___XX_XX,XX_XX___,
+ ___XXXX_,_XXXX___,
+ ___XXXXX,XXXXX___,
+ _______X,X_______,
+ __XXXXXX,XXXXXX__,
+ __XX_XX_,_XX_XX__,
+ __XXXXXX,XXXXXX__,
+ __XX____,____XX__,
+ __XX____,__XXXX__,
+ ________,________,
+ ________,________,
+};
+
+/* char: 例 code:0xC0FD */
+static GUI_CONST_STORAGE unsigned char acC0FD[32] = {
+ ____XX__,_____XX_,
+ ____XXXX,XXXX_XX_,
+ ___XX__X,X____XX_,
+ ___XX__X,X__XXXX_,
+ __XXX__X,XXXXXXX_,
+ _XXXX_XX,_XXXXXX_,
+ ___XX_XX,_XXXXXX_,
+ ___XX_XX,_XXXXXX_,
+ ___XXXXX,XXXXXXX_,
+ ___XX___,XX_XXXX_,
+ ___XX___,XX___XX_,
+ ___XX__X,X____XX_,
+ ___XX_XX,_____XX_,
+ ___XXXX_,___XXXX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 力 code:0xC1A6 */
+static GUI_CONST_STORAGE unsigned char acC1A6[32] = {
+ ______XX,________,
+ ______XX,________,
+ ______XX,________,
+ ______XX,________,
+ _XXXXXXX,XXXXXX__,
+ ______XX,____XX__,
+ _____XX_,____XX__,
+ _____XX_,____XX__,
+ _____XX_,____XX__,
+ ____XX__,____XX__,
+ ____XX__,____XX__,
+ ___XX___,____XX__,
+ __XX____,___XX___,
+ _XX_____,_XXX____,
+ ________,________,
+ ________,________,
+};
+
+/* char: 量 code:0xC1BF */
+static GUI_CONST_STORAGE unsigned char acC1BF[32] = {
+ ___XXXXX,XXXXX___,
+ ___XX_XX,___XX___,
+ ___XX__X,X__XX___,
+ ___XXXXX,XXXXX___,
+ ________,________,
+ _XXXXXXX,XXXXXXX_,
+ ___XX__X,X__XX___,
+ ___XXXXX,XXXXX___,
+ ___XX__X,X__XX___,
+ ___XXXXX,XXXXX___,
+ _______X,X_______,
+ __XXXXXX,XXXXXX__,
+ _______X,X_______,
+ _XXXXXXX,XXXXXXX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 列 code:0xC1D0 */
+static GUI_CONST_STORAGE unsigned char acC1D0[32] = {
+ ________,_____XX_,
+ __XXXXXX,X____XX_,
+ ____XX__,_____XX_,
+ ____XX__,__XX_XX_,
+ ____XXXX,X_XX_XX_,
+ ___XX__X,X_XX_XX_,
+ ___XX__X,X_XX_XX_,
+ __XXXX_X,X_XX_XX_,
+ _XX__XXX,__XX_XX_,
+ ______XX,__XX_XX_,
+ _____XX_,_____XX_,
+ ____XX__,_____XX_,
+ ___XX___,_____XX_,
+ __XX____,___XXXX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 零 code:0xC1E3 */
+static GUI_CONST_STORAGE unsigned char acC1E3[32] = {
+ ___XXXXX,XXXXX___,
+ _______X,X_______,
+ _XXXXXXX,XXXXXXX_,
+ _XX____X,X____XX_,
+ _XXXXXXX,XXXXXXX_,
+ _______X,X_______,
+ ___XXXXX,XXXXX___,
+ _____XXX,XXX_____,
+ ___XXX__,__XXX___,
+ _XXX___X,X___XXX_,
+ ____XXXX,XXXX____,
+ ________,_XX_____,
+ ____XXXX,XX______,
+ _______X,XX______,
+ ________,________,
+ ________,________,
+};
+
+/* char: 流 code:0xC1F7 */
+static GUI_CONST_STORAGE unsigned char acC1F7[32] = {
+ ________,_XX_____,
+ __XX____,__XX____,
+ ___XX_XX,XXXXXXX_,
+ ____XX__,_XX_____,
+ ________,XX_XX___,
+ _XX____X,X___XX__,
+ __XX__XX,XXXXXXX_,
+ ____XX__,_____XX_,
+ ____XX_X,XXXXX___,
+ ___XX__X,XXXXX___,
+ ___XX__X,XXXXX___,
+ __XX___X,XXXXX___,
+ __XX__XX,_XXXXXX_,
+ _____XX_,____XXX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 路 code:0xC2B7 */
+static GUI_CONST_STORAGE unsigned char acC2B7[32] = {
+ ________,_XX_____,
+ __XXXXX_,_XX_____,
+ __XX_XX_,_XXXXX__,
+ __XX_XX_,XX__XX__,
+ __XX_XXX,XXXXX___,
+ __XXXXX_,__XX____,
+ ____XX__,_XXXX___,
+ __XXXX_X,XX__XXX_,
+ __XXXXXX,________,
+ __XXXX__,XXXXXX__,
+ __XXXX__,XX__XX__,
+ __XXXXXX,XX__XX__,
+ _XXXX___,XXXXXX__,
+ ________,XX__XX__,
+ ________,________,
+ ________,________,
+};
+
+/* char: 录 code:0xC2BC */
+static GUI_CONST_STORAGE unsigned char acC2BC[32] = {
+ ________,________,
+ __XXXXXX,XXXXX___,
+ ________,___XX___,
+ ___XXXXX,XXXXX___,
+ ________,___XX___,
+ _XXXXXXX,XXXXXXX_,
+ _______X,X_______,
+ ___XX__X,X__XX___,
+ ____XX_X,XXXX____,
+ _____XXX,XXX_____,
+ ____XX_X,X_XX____,
+ ___XX__X,X__XX___,
+ _XXX___X,X___XXX_,
+ _____XXX,X_______,
+ ________,________,
+ ________,________,
+};
+
+/* char: 率 code:0xC2CA */
+static GUI_CONST_STORAGE unsigned char acC2CA[32] = {
+ ______XX,________,
+ _______X,X_______,
+ __XXXXXX,XXXXXX__,
+ _______X,X_______,
+ _XX___XX,_XX__XX_,
+ __XX_XXX,XX__XX__,
+ ___XX__X,X__XX___,
+ __XX__XX,_XX_XX__,
+ _XX__XXX,XXXX_XX_,
+ _______X,X_XX____,
+ _XXXXXXX,XXXXXXX_,
+ _______X,X_______,
+ _______X,X_______,
+ _______X,X_______,
+ ________,________,
+ ________,________,
+};
+
+/* char: 满 code:0xC2FA */
+static GUI_CONST_STORAGE unsigned char acC2FA[32] = {
+ _______X,X__XX___,
+ __XX_XXX,XXXXXXX_,
+ ___XX__X,X__XX___,
+ ________,________,
+ _XX__XXX,XXXXXXX_,
+ __XX___X,X__XX___,
+ _______X,X__XX___,
+ ___XXXXX,XXXXXXX_,
+ ___XXXXX,X__XXXX_,
+ __XX_XXX,X__XXXX_,
+ __XX_XXX,XXXXXXX_,
+ _XX__XX_,_____XX_,
+ _XX__XX_,_____XX_,
+ _____XX_,___XXXX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 门 code:0xC3C5 */
+static GUI_CONST_STORAGE unsigned char acC3C5[32] = {
+ ___XX___,________,
+ ____XXXX,XXXXXXX_,
+ ____XX__,_____XX_,
+ __XX____,_____XX_,
+ __XX____,_____XX_,
+ __XX____,_____XX_,
+ __XX____,_____XX_,
+ __XX____,_____XX_,
+ __XX____,_____XX_,
+ __XX____,_____XX_,
+ __XX____,_____XX_,
+ __XX____,_____XX_,
+ __XX____,_____XX_,
+ __XX____,___XXXX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 面 code:0xC3E6 */
+static GUI_CONST_STORAGE unsigned char acC3E6[32] = {
+ _XXXXXXX,XXXXXXX_,
+ _______X,X_______,
+ ______XX,________,
+ __XXXXXX,XXXXXX__,
+ __XX_XX_,_XX_XX__,
+ __XX_XX_,_XX_XX__,
+ __XX_XXX,XXX_XX__,
+ __XX_XX_,_XX_XX__,
+ __XX_XX_,_XX_XX__,
+ __XX_XXX,XXX_XX__,
+ __XX_XX_,_XX_XX__,
+ __XX_XX_,_XX_XX__,
+ __XXXXXX,XXXXXX__,
+ __XX____,____XX__,
+ ________,________,
+ ________,________,
+};
+
+/* char: 名 code:0xC3FB */
+static GUI_CONST_STORAGE unsigned char acC3FB[32] = {
+ ______XX,________,
+ ______XX,________,
+ _____XXX,XXXXXX__,
+ ____XX__,___XX___,
+ __XXXXX_,__XX____,
+ ______XX,_XX_____,
+ _______X,XX______,
+ _____XXX,________,
+ ___XXXXX,XXXXXX__,
+ _XXXXX__,____XX__,
+ ____XX__,____XX__,
+ ____XX__,____XX__,
+ ____XXXX,XXXXXX__,
+ ____XX__,____XX__,
+ ________,________,
+ ________,________,
+};
+
+/* char: 模 code:0xC4A3 */
+static GUI_CONST_STORAGE unsigned char acC4A3[32] = {
+ ___XX__X,X__XX___,
+ ___XX__X,X__XX___,
+ ___XX_XX,XXXXXXX_,
+ _XXXXX_X,X__XX___,
+ ___XX_XX,XXXXXX__,
+ ___XX_XX,____XX__,
+ __XXXXXX,XXXXXX__,
+ __XXXXXX,____XX__,
+ _XXXX_XX,XXXXXX__,
+ ___XX___,_XX_____,
+ ___XXXXX,XXXXXXX_,
+ ___XX___,XXXX____,
+ ___XX__X,X__XX___,
+ ___XXXXX,____XXX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 膜 code:0xC4A4 */
+static GUI_CONST_STORAGE unsigned char acC4A4[32] = {
+ ________,_XXXX___,
+ __XXXXX_,_XXXX___,
+ __XX_XXX,XXXXXXX_,
+ __XX_XX_,_XXXX___,
+ __XX_XX_,XXXXXX__,
+ __XXXXX_,XX__XX__,
+ __XX_XX_,XXXXXX__,
+ __XX_XX_,XX__XX__,
+ __XXXXX_,XXXXXX__,
+ __XX_XX_,__XX____,
+ __XX_XXX,XXXXXXX_,
+ __XX_XX_,_XXXX___,
+ __XX_XX_,XX__XX__,
+ _XX_XXXX,X____XX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 摩 code:0xC4A6 */
+static GUI_CONST_STORAGE unsigned char acC4A6[32] = {
+ _______X,X_______,
+ __XXXXXX,XXXXXXX_,
+ __XX_XX_,__XX____,
+ __XXXXXX,XXXXXX__,
+ __XX_XX_,_XXXX___,
+ __XXXXXX,XXXXXXX_,
+ __XXXXX_,__XX____,
+ __XX_XXX,XXXXX___,
+ __XX____,XX______,
+ __XX_XXX,XXXXX___,
+ __XX____,XX______,
+ __XXXXXX,XXXXXXX_,
+ __XX____,XX______,
+ _XX___XX,XX______,
+ ________,________,
+ ________,________,
+};
+
+/* char: 内 code:0xC4DA */
+static GUI_CONST_STORAGE unsigned char acC4DA[32] = {
+ _______X,X_______,
+ _______X,X_______,
+ _______X,X_______,
+ __XXXXXX,XXXXXXX_,
+ __XX___X,X____XX_,
+ __XX___X,X____XX_,
+ __XX__XX,XX___XX_,
+ __XX_XX_,_XX__XX_,
+ __XXXX__,__XX_XX_,
+ __XXX___,___XXXX_,
+ __XX____,_____XX_,
+ __XX____,_____XX_,
+ __XX____,_____XX_,
+ __XX____,___XXXX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 能 code:0xC4DC */
+static GUI_CONST_STORAGE unsigned char acC4DC[32] = {
+ ____XX__,_XX_____,
+ ___XX___,_XX_XXX_,
+ __XX__XX,_XXXX___,
+ _XXXXXXX,XXX__XX_,
+ _______X,XXX__XX_,
+ ________,__XXXXX_,
+ __XXXXXX,________,
+ __XX__XX,_XX__XX_,
+ __XXXXXX,_XX_XX__,
+ __XX__XX,_XXXX___,
+ __XXXXXX,_XX_____,
+ __XX__XX,_XX__XX_,
+ __XX__XX,_XX__XX_,
+ __XX_XXX,__XXXXX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 拟 code:0xC4E2 */
+static GUI_CONST_STORAGE unsigned char acC4E2[32] = {
+ ___XX___,___XX___,
+ ___XX___,XX_XX___,
+ ___XX_XX,_XXXX___,
+ _XXXXXXX,_XXXX___,
+ ___XX_XX,_XXXX___,
+ ___XX_XX,___XX___,
+ ___XX_XX,___XX___,
+ ___XXXXX,___XX___,
+ _XXXX_XX,___XX___,
+ ___XX_XX,XXXXXX__,
+ ___XX_XX,X_XXXX__,
+ ___XX_XX,_XX__XX_,
+ ___XX___,XX___XX_,
+ _XXXX__X,X____XX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 配 code:0xC5E4 */
+static GUI_CONST_STORAGE unsigned char acC5E4[32] = {
+ ________,________,
+ _XXXXXXX,XXXXXX__,
+ ___XXXX_,____XX__,
+ ___XXXX_,____XX__,
+ _XXXXXXX,X___XX__,
+ _XXXXXXX,X___XX__,
+ _XXXXXXX,XXXXXX__,
+ _XXX__XX,XXX_____,
+ _XX____X,XXX_____,
+ _XXXXXXX,XXX_____,
+ _XX____X,XXX_____,
+ _XX____X,XXX__XX_,
+ _XXXXXXX,XXX__XX_,
+ _XX____X,X_XXXXX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 偏 code:0xC6AB */
+static GUI_CONST_STORAGE unsigned char acC6AB[32] = {
+ ____XX__,XX______,
+ ____XX__,_XX_____,
+ ____XXXX,XXXXXX__,
+ ___XX_XX,____XX__,
+ ___XX_XX,____XX__,
+ __XXX_XX,XXXXXX__,
+ _XXXX_XX,________,
+ ___XX_XX,XXXXXX__,
+ ___XXXXX,XXXXXX__,
+ ___XXXXX,XXXXXX__,
+ ___XXXXX,XXXXXX__,
+ ___XX_XX,XXXXXX__,
+ ___XX_XX,XXXXXX__,
+ ___XX_XX,___XXX__,
+ ________,________,
+ ________,________,
+};
+
+/* char: 频 code:0xC6B5 */
+static GUI_CONST_STORAGE unsigned char acC6B5[32] = {
+ ____XX__,________,
+ ____XX_X,XXXXXXX_,
+ __XXXXXX,__XX____,
+ __XXXX__,_XX_____,
+ __XXXX__,XXXXXX__,
+ _XXXXXXX,XX__XX__,
+ ________,XXXXXX__,
+ ____XX__,XXXXXX__,
+ __XXXXXX,XXXXXX__,
+ _XX_XXXX,XXXXXX__,
+ _____XX_,XXXXXX__,
+ ____XX__,_XXXX___,
+ ___XX___,XX__XX__,
+ _XXX___X,X___XX__,
+ ________,________,
+ ________,________,
+};
+
+/* char: 平 code:0xC6BD */
+static GUI_CONST_STORAGE unsigned char acC6BD[32] = {
+ __XXXXXX,XXXXXX__,
+ _______X,X_______,
+ _______X,X_______,
+ ___XX__X,X__XX___,
+ ____XX_X,X__XX___,
+ ____XX_X,X_XX____,
+ _______X,X_______,
+ _XXXXXXX,XXXXXXX_,
+ _______X,X_______,
+ _______X,X_______,
+ _______X,X_______,
+ _______X,X_______,
+ _______X,X_______,
+ _______X,X_______,
+ ________,________,
+ ________,________,
+};
+
+/* char: 启 code:0xC6F4 */
+static GUI_CONST_STORAGE unsigned char acC6F4[32] = {
+ ______XX,________,
+ _______X,X_______,
+ ___XXXXX,XXXXXX__,
+ ___XX___,____XX__,
+ ___XX___,____XX__,
+ ___XXXXX,XXXXXX__,
+ ___XX___,________,
+ ___XX___,________,
+ ___XXXXX,XXXXXX__,
+ ___XXXX_,____XX__,
+ __XX_XX_,____XX__,
+ __XX_XX_,____XX__,
+ _XX__XXX,XXXXXX__,
+ _____XX_,____XX__,
+ ________,________,
+ ________,________,
+};
+
+/* char: 器 code:0xC6F7 */
+static GUI_CONST_STORAGE unsigned char acC6F7[32] = {
+ __XXXXXX,XXXXXX__,
+ __XX__XX,XX__XX__,
+ __XX__XX,XX__XX__,
+ __XXXXXX,XXXXXX__,
+ ________,__XX____,
+ _______X,X__XX___,
+ _XXXXXXX,XXXXXXX_,
+ _____XX_,_XX_____,
+ ___XXX__,__XXX___,
+ _XXX____,____XXX_,
+ __XXXXXX,XXXXXX__,
+ __XX__XX,XX__XX__,
+ __XX__XX,XX__XX__,
+ __XXXXXX,XXXXXX__,
+ ________,________,
+ ________,________,
+};
+
+/* char: 气 code:0xC6F8 */
+static GUI_CONST_STORAGE unsigned char acC6F8[32] = {
+ ___XX___,________,
+ ___XX___,________,
+ ___XXXXX,XXXXXXX_,
+ __XX____,________,
+ _XX_XXXX,XXXXX___,
+ ________,________,
+ __XXXXXX,XXXXX___,
+ ________,___XX___,
+ ________,___XX___,
+ ________,___XX___,
+ ________,___XX___,
+ ________,___XXXX_,
+ ________,____XXX_,
+ ________,_____XX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 前 code:0xC7B0 */
+static GUI_CONST_STORAGE unsigned char acC7B0[32] = {
+ ___XX___,___XX___,
+ ____XX__,__XX____,
+ _XXXXXXX,XXXXXXX_,
+ ________,________,
+ __XXXXXX,X___XX__,
+ __XX___X,XXX_XX__,
+ __XX___X,XXX_XX__,
+ __XXXXXX,XXX_XX__,
+ __XX___X,XXX_XX__,
+ __XX___X,XXX_XX__,
+ __XXXXXX,XXX_XX__,
+ __XX___X,X___XX__,
+ __XX___X,X___XX__,
+ __XX_XXX,X_XXXX__,
+ ________,________,
+ ________,________,
+};
+
+/* char: 切 code:0xC7D0 */
+static GUI_CONST_STORAGE unsigned char acC7D0[32] = {
+ ___XX___,________,
+ ___XX__X,XXXXXXX_,
+ ___XX___,_XX__XX_,
+ ___XX___,_XX__XX_,
+ ___XXXXX,_XX__XX_,
+ _XXXX___,_XX__XX_,
+ ___XX___,_XX__XX_,
+ ___XX___,_XX__XX_,
+ ___XX_XX,_XX__XX_,
+ ___XXXX_,XX___XX_,
+ ___XXX__,XX___XX_,
+ ___XX__X,X____XX_,
+ ______XX,_____XX_,
+ _____XX_,___XXX__,
+ ________,________,
+ ________,________,
+};
+
+/* char: 区 code:0xC7F8 */
+static GUI_CONST_STORAGE unsigned char acC7F8[32] = {
+ __XXXXXX,XXXXXXX_,
+ __XX____,________,
+ __XX____,___XX___,
+ __XXXX__,___XX___,
+ __XX_XX_,__XX____,
+ __XX__XX,__XX____,
+ __XX___X,XXX_____,
+ __XX____,XX______,
+ __XX___X,XXX_____,
+ __XX__XX,__XX____,
+ __XX_XX_,___XX___,
+ __XXXX__,___XX___,
+ __XX____,________,
+ __XXXXXX,XXXXXXX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 驱 code:0xC7FD */
+static GUI_CONST_STORAGE unsigned char acC7FD[32] = {
+ ________,________,
+ _XXXXXX_,XXXXXXX_,
+ _____XX_,XX______,
+ __XX_XX_,XX______,
+ __XX_XX_,XXX_XX__,
+ __XX_XX_,XXXXXX__,
+ __XX_XX_,XXXXXX__,
+ __XXXXXX,XX_XX___,
+ ______XX,XX_XX___,
+ ______XX,XXXXXX__,
+ ___XXXXX,XXXXXX__,
+ _XXX__XX,XXX_XX__,
+ ______XX,XX______,
+ ____XXX_,XXXXXXX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 取 code:0xC8A1 */
+static GUI_CONST_STORAGE unsigned char acC8A1[32] = {
+ ________,________,
+ _XXXXXXX,________,
+ __XX_XXX,XXXXXX__,
+ __XX_XX_,XX__XX__,
+ __XXXXX_,XX__XX__,
+ __XX_XX_,XX__XX__,
+ __XX_XX_,XX__XX__,
+ __XXXXX_,_XXXX___,
+ __XX_XX_,_XXXX___,
+ __XX_XXX,X_XX____,
+ _XXXXXX_,__XX____,
+ _____XX_,_XXXX___,
+ _____XX_,XX__XX__,
+ _____XXX,X____XX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 全 code:0xC8AB */
+static GUI_CONST_STORAGE unsigned char acC8AB[32] = {
+ _______X,X_______,
+ _______X,X_______,
+ ______XX,XX______,
+ _____XX_,_XX_____,
+ ____XX__,__XX____,
+ ___XX___,___XX___,
+ _XXXXXXX,XXXXXXX_,
+ _______X,X_______,
+ _______X,X_______,
+ ____XXXX,XXXX____,
+ _______X,X_______,
+ _______X,X_______,
+ _______X,X_______,
+ _XXXXXXX,XXXXXXX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 确 code:0xC8B7 */
+static GUI_CONST_STORAGE unsigned char acC8B7[32] = {
+ ________,XX______,
+ ________,XXXXXX__,
+ _XXXXXXX,X___XX__,
+ ___XX_XX,___XX___,
+ ___XX__X,XXXXXXX_,
+ __XX___X,X_XX_XX_,
+ __XXXXXX,X_XX_XX_,
+ _XXX_XXX,XXXXXXX_,
+ __XX_XXX,X_XX_XX_,
+ __XX_XXX,X_XX_XX_,
+ __XX_XXX,XXXXXXX_,
+ __XXXXXX,X_XX_XX_,
+ __XX___X,X_XX_XX_,
+ ______XX,____XXX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 认 code:0xC8CF */
+static GUI_CONST_STORAGE unsigned char acC8CF[32] = {
+ __XX____,_XX_____,
+ ___XX___,_XX_____,
+ ___XX___,_XX_____,
+ ________,_XX_____,
+ _XXXX___,_XX_____,
+ ___XX___,_XX_____,
+ ___XX___,_XX_____,
+ ___XX___,XXXX____,
+ ___XX___,XXXX____,
+ ___XXXX_,XXXX____,
+ ___XXX_X,X__XX___,
+ ___XX__X,X__XX___,
+ ______XX,____XX__,
+ _____XX_,_____XX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 入 code:0xC8EB */
+static GUI_CONST_STORAGE unsigned char acC8EB[32] = {
+ _____XX_,________,
+ ______XX,________,
+ ______XX,________,
+ _______X,X_______,
+ _______X,X_______,
+ ______XX,XX______,
+ ______XX,XX______,
+ _____XX_,_XX_____,
+ _____XX_,_XX_____,
+ ____XX__,__XX____,
+ ____XX__,__XX____,
+ ___XX___,___XX___,
+ __XX____,____XX__,
+ _XX_____,_____XX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 软 code:0xC8ED */
+static GUI_CONST_STORAGE unsigned char acC8ED[32] = {
+ ____XX__,_XX_____,
+ ____XX__,_XX_____,
+ _XXXXXXX,_XX_____,
+ ___XX___,_XXXXXX_,
+ __XXXX__,XX___XX_,
+ __XXXX__,XX__XX__,
+ _XXXXXXX,X_XX____,
+ ____XX__,__XX____,
+ ____XX__,__XX____,
+ ____XXXX,__XX____,
+ _XXXXX__,_XXXX___,
+ ____XX__,_XXXX___,
+ ____XX__,XX__XX__,
+ ____XX_X,X____XX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 商 code:0xC9CC */
+static GUI_CONST_STORAGE unsigned char acC9CC[32] = {
+ ______XX,________,
+ _______X,X_______,
+ _XXXXXXX,XXXXXXX_,
+ ____XX__,__XX____,
+ _____XX_,_XX_____,
+ __XXXXXX,XXXXXX__,
+ __XX_XX_,_XX_XX__,
+ __XXXX__,__XXXX__,
+ __XXXXXX,XXXXXX__,
+ __XX_XX_,_XX_XX__,
+ __XX_XX_,_XX_XX__,
+ __XX_XXX,XXX_XX__,
+ __XX____,____XX__,
+ __XX____,__XXXX__,
+ ________,________,
+ ________,________,
+};
+
+/* char: 上 code:0xC9CF */
+static GUI_CONST_STORAGE unsigned char acC9CF[32] = {
+ _______X,X_______,
+ _______X,X_______,
+ _______X,X_______,
+ _______X,X_______,
+ _______X,X_______,
+ _______X,XXXXXX__,
+ _______X,X_______,
+ _______X,X_______,
+ _______X,X_______,
+ _______X,X_______,
+ _______X,X_______,
+ _______X,X_______,
+ _______X,X_______,
+ _XXXXXXX,XXXXXXX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 少 code:0xC9D9 */
+static GUI_CONST_STORAGE unsigned char acC9D9[32] = {
+ _______X,X_______,
+ _______X,X_______,
+ ____XX_X,X_XX____,
+ ____XX_X,X__XX___,
+ ___XX__X,X___XX__,
+ __XX___X,X____XX_,
+ _XX____X,X____XX_,
+ _______X,X__XX___,
+ _______X,X_XX____,
+ ________,_XX_____,
+ ________,XX______,
+ ______XX,X_______,
+ ____XXX_,________,
+ _XXXX___,________,
+ ________,________,
+ ________,________,
+};
+
+/* char: 设 code:0xC9E8 */
+static GUI_CONST_STORAGE unsigned char acC9E8[32] = {
+ __XX____,________,
+ ___XX__X,XXXXX___,
+ ___XX__X,X__XX___,
+ _______X,X__XX___,
+ _______X,X__XX___,
+ _XXXX_XX,____XXX_,
+ ___XXXX_,________,
+ ___XX_XX,XXXXXX__,
+ ___XX__X,X___XX__,
+ ___XX__X,X__XX___,
+ ___XXXX_,XXXX____,
+ ___XXX__,_XX_____,
+ ___XX__X,XXXXX___,
+ _____XXX,____XXX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 湿 code:0xCAAA */
+static GUI_CONST_STORAGE unsigned char acCAAA[32] = {
+ ________,________,
+ __XX_XXX,XXXXXX__,
+ ___XXXX_,____XX__,
+ _____XX_,____XX__,
+ _XX__XXX,XXXXXX__,
+ __XX_XX_,____XX__,
+ _____XX_,____XX__,
+ ___XXXXX,XXXXXX__,
+ ___XX__X,X_XX____,
+ __XXXX_X,X_XX_XX_,
+ __XX_XXX,X_XXXX__,
+ _XX___XX,X_XXX___,
+ _XX____X,X_XX____,
+ ____XXXX,XXXXXXX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 石 code:0xCAAF */
+static GUI_CONST_STORAGE unsigned char acCAAF[32] = {
+ ________,________,
+ _XXXXXXX,XXXXXXX_,
+ ______XX,________,
+ ______XX,________,
+ _____XX_,________,
+ ____XX__,________,
+ ___XXXXX,XXXXXX__,
+ __XXXX__,____XX__,
+ _XX_XX__,____XX__,
+ ____XX__,____XX__,
+ ____XX__,____XX__,
+ ____XX__,____XX__,
+ ____XXXX,XXXXXX__,
+ ____XX__,____XX__,
+ ________,________,
+ ________,________,
+};
+
+/* char: 时 code:0xCAB1 */
+static GUI_CONST_STORAGE unsigned char acCAB1[32] = {
+ ________,___XX___,
+ ________,___XX___,
+ _XXXXX__,___XX___,
+ _XX_XXXX,XXXXXXX_,
+ _XX_XX__,___XX___,
+ _XX_XX__,___XX___,
+ _XXXXX_X,X__XX___,
+ _XX_XX__,XX_XX___,
+ _XX_XX__,XX_XX___,
+ _XX_XX__,___XX___,
+ _XXXXX__,___XX___,
+ _XX_XX__,___XX___,
+ ________,___XX___,
+ ________,_XXXX___,
+ ________,________,
+ ________,________,
+};
+
+/* char: 实 code:0xCAB5 */
+static GUI_CONST_STORAGE unsigned char acCAB5[32] = {
+ ______XX,________,
+ _______X,X_______,
+ _XXXXXXX,XXXXXXX_,
+ _XX_____,_____XX_,
+ _____XX_,_XX_____,
+ ______XX,_XX_____,
+ ___XX___,_XX_____,
+ ____XX__,_XX_____,
+ ________,XX______,
+ _XXXXXXX,XXXXXXX_,
+ _______X,XXX_____,
+ ______XX,__XX____,
+ ____XXX_,___XX___,
+ __XXX___,____XX__,
+ ________,________,
+ ________,________,
+};
+
+/* char: 使 code:0xCAB9 */
+static GUI_CONST_STORAGE unsigned char acCAB9[32] = {
+ ____XX__,_XX_____,
+ ____XX__,_XX_____,
+ ___XXXXX,XXXXXXX_,
+ ___XX___,_XX_____,
+ __XXXXXX,XXXXXXX_,
+ _XXXXXX_,_XX__XX_,
+ ___XXXX_,_XX__XX_,
+ ___XXXXX,XXXXXXX_,
+ ___XX_XX,_XX_____,
+ ___XX__X,XXX_____,
+ ___XX___,XX______,
+ ___XX__X,XXX_____,
+ ___XX_XX,__XXX___,
+ ___XXXX_,____XXX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 式 code:0xCABD */
+static GUI_CONST_STORAGE unsigned char acCABD[32] = {
+ ________,_XXXX___,
+ ________,_XX_XX__,
+ ________,_XX_____,
+ _XXXXXXX,XXXXXXX_,
+ ________,_XX_____,
+ ________,_XX_____,
+ __XXXXXX,_XX_____,
+ ____XX__,_XX_____,
+ ____XX__,_XX_____,
+ ____XX__,__XX____,
+ ____XX__,__XX_XX_,
+ ____XXXX,X__XXXX_,
+ _XXXXX__,____XXX_,
+ ________,_____XX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 示 code:0xCABE */
+static GUI_CONST_STORAGE unsigned char acCABE[32] = {
+ ________,________,
+ ___XXXXX,XXXXX___,
+ ________,________,
+ ________,________,
+ ________,________,
+ _XXXXXXX,XXXXXXX_,
+ _______X,X_______,
+ ____XX_X,X_XX____,
+ ____XX_X,X__XX___,
+ ___XX__X,X___XX__,
+ __XX___X,X____XX_,
+ _XX____X,X____XX_,
+ _______X,X_______,
+ _____XXX,X_______,
+ ________,________,
+ ________,________,
+};
+
+/* char: 试 code:0xCAD4 */
+static GUI_CONST_STORAGE unsigned char acCAD4[32] = {
+ __XX____,__XXXX__,
+ ___XX___,__XX_XX_,
+ ___XX___,__XX____,
+ _____XXX,XXXXXXX_,
+ ________,__XX____,
+ _XXXX___,__XX____,
+ ___XX_XX,XXXX____,
+ ___XX__X,X_XX____,
+ ___XX__X,X_XX____,
+ ___XX__X,X__XX___,
+ ___XXXXX,X__XXXX_,
+ ___XXX_X,XXXXXXX_,
+ ___XXXXX,X___XXX_,
+ ________,_____XX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 手 code:0xCAD6 */
+static GUI_CONST_STORAGE unsigned char acCAD6[32] = {
+ ________,_XXXXX__,
+ __XXXXXX,XX______,
+ _______X,X_______,
+ _______X,X_______,
+ __XXXXXX,XXXXXX__,
+ _______X,X_______,
+ _______X,X_______,
+ _______X,X_______,
+ _XXXXXXX,XXXXXXX_,
+ _______X,X_______,
+ _______X,X_______,
+ _______X,X_______,
+ _______X,X_______,
+ _____XXX,X_______,
+ ________,________,
+ ________,________,
+};
+
+/* char: 首 code:0xCAD7 */
+static GUI_CONST_STORAGE unsigned char acCAD7[32] = {
+ ___XX___,___XX___,
+ ____XX__,__XX____,
+ _XXXXXXX,XXXXXXX_,
+ ______XX,________,
+ _____XX_,________,
+ ___XXXXX,XXXXX___,
+ ___XX___,___XX___,
+ ___XXXXX,XXXXX___,
+ ___XX___,___XX___,
+ ___XXXXX,XXXXX___,
+ ___XX___,___XX___,
+ ___XX___,___XX___,
+ ___XXXXX,XXXXX___,
+ ___XX___,___XX___,
+ ________,________,
+ ________,________,
+};
+
+/* char: 输 code:0xCAE4 */
+static GUI_CONST_STORAGE unsigned char acCAE4[32] = {
+ __XX____,_XX_____,
+ __XX____,XXXX____,
+ _XXXXX_X,X__XX___,
+ __XX__XX,____XX__,
+ _XX__XXX,XXXXXXX_,
+ _XXXX___,________,
+ _XXXXXXX,XXX__XX_,
+ ___XX_XX,_XXXXXX_,
+ ___XX_XX,XXXXXXX_,
+ ___XXXXX,_XXXXXX_,
+ _XXXX_XX,XXXXXXX_,
+ ___XX_XX,_XXXXXX_,
+ ___XX_XX,_XX__XX_,
+ ___XX_XX,XXXXXXX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 术 code:0xCAF5 */
+static GUI_CONST_STORAGE unsigned char acCAF5[32] = {
+ _______X,X_______,
+ _______X,X_XX____,
+ _______X,X__XX___,
+ _______X,X_______,
+ _XXXXXXX,XXXXXXX_,
+ ______XX,XX______,
+ _____XXX,XXX_____,
+ _____XXX,XXX_____,
+ ____XX_X,X_XX____,
+ ___XX__X,X__XX___,
+ __XX___X,X___XX__,
+ _XX____X,X____XX_,
+ _______X,X_______,
+ _______X,X_______,
+ ________,________,
+ ________,________,
+};
+
+/* char: 数 code:0xCAFD */
+static GUI_CONST_STORAGE unsigned char acCAFD[32] = {
+ ____XX__,__XX____,
+ _XX_XX_X,X_XX____,
+ __XXXXXX,__XX____,
+ _XXXXXXX,X_XXXXX_,
+ ___XXXX_,_XX_XX__,
+ __XXXXXX,_XX_XX__,
+ _XX_XX_X,XXXXXX__,
+ ___XX___,__XXXX__,
+ _XXXXXXX,__XXXX__,
+ ___XX_XX,__XXXX__,
+ __XXX_XX,___XX___,
+ ____XXX_,___XX___,
+ ___XXXXX,__XXXX__,
+ _XXX___X,XXX__XX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 双 code:0xCBAB */
+static GUI_CONST_STORAGE unsigned char acCBAB[32] = {
+ ________,________,
+ _XXXXXXX,XXXXXX__,
+ ______XX,XX__XX__,
+ ______XX,XX__XX__,
+ __XX__XX,XX__XX__,
+ ___XXXX_,XX__XX__,
+ ___XXXX_,_XXXX___,
+ ____XX__,_XXXX___,
+ ____XX__,__XX____,
+ ___XXXX_,__XX____,
+ ___XXXX_,_XXXX___,
+ __XX_XX_,XX_XX___,
+ __XX___X,X___XX__,
+ _XX___XX,_____XX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 司 code:0xCBBE */
+static GUI_CONST_STORAGE unsigned char acCBBE[32] = {
+ __XXXXXX,XXXXXX__,
+ ________,____XX__,
+ ________,____XX__,
+ _XXXXXXX,XXXXXX__,
+ ________,____XX__,
+ ________,____XX__,
+ __XXXXXX,XXX_XX__,
+ __XX____,_XX_XX__,
+ __XX____,_XX_XX__,
+ __XX____,_XX_XX__,
+ __XXXXXX,XXX_XX__,
+ __XX____,____XX__,
+ ________,____XX__,
+ ________,__XXXX__,
+ ________,________,
+ ________,________,
+};
+
+/* char: 死 code:0xCBC0 */
+static GUI_CONST_STORAGE unsigned char acCBC0[32] = {
+ ________,________,
+ _XXXXXXX,XXXXXXX_,
+ ___XX___,XX______,
+ ___XX___,XX______,
+ ___XXXXX,XX______,
+ __XX__XX,XX__XX__,
+ __XX__XX,XX_XX___,
+ _XXXX_XX,XXXX____,
+ ____XXX_,XXX_____,
+ _____XX_,XX______,
+ ____XX__,XX______,
+ ___XX___,XX___XX_,
+ __XX____,XX___XX_,
+ _XX_____,_XXXXXX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 苏 code:0xCBD5 */
+static GUI_CONST_STORAGE unsigned char acCBD5[32] = {
+ ____XX__,__XX____,
+ ____XX__,__XX____,
+ _XXXXXXX,XXXXXXX_,
+ ____XX__,__XX____,
+ ______XX,________,
+ ______XX,________,
+ __XXXXXX,XXXX____,
+ ______XX,__XX____,
+ __XX__XX,__XXXX__,
+ __XX_XX_,__XX_XX_,
+ _XX__XX_,__XX_XX_,
+ ____XX__,__XX____,
+ ___XX___,__XX____,
+ __XX____,XXX_____,
+ ________,________,
+ ________,________,
+};
+
+/* char: 速 code:0xCBD9 */
+static GUI_CONST_STORAGE unsigned char acCBD9[32] = {
+ ________,_XX_____,
+ __XX____,_XX_____,
+ ___XXXXX,XXXXXXX_,
+ ___XX___,_XX_____,
+ ______XX,XXXXXX__,
+ ______XX,_XX_XX__,
+ _XXXX_XX,_XX_XX__,
+ ___XX_XX,XXXXXX__,
+ ___XX___,XXXX____,
+ ___XX__X,XXXXX___,
+ ___XX_XX,_XX_XX__,
+ ___XXXX_,_XX__XX_,
+ __XXXX__,_XX_____,
+ _XX__XXX,XXXXXXX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 算 code:0xCBE3 */
+static GUI_CONST_STORAGE unsigned char acCBE3[32] = {
+ ___XX___,_XX_____,
+ __XXXXXX,XXXXXXX_,
+ _XX__XX_,XX_XX___,
+ ___XXXXX,XXXXX___,
+ ___XX___,___XX___,
+ ___XXXXX,XXXXX___,
+ ___XX___,___XX___,
+ ___XXXXX,XXXXX___,
+ ___XX___,___XX___,
+ ___XXXXX,XXXXX___,
+ _____XX_,_XX_____,
+ _XXXXXXX,XXXXXXX_,
+ ____XX__,_XX_____,
+ ___XX___,_XX_____,
+ ________,________,
+ ________,________,
+};
+
+/* char: 所 code:0xCBF9 */
+static GUI_CONST_STORAGE unsigned char acCBF9[32] = {
+ _____XXX,___XXX__,
+ __XXXX__,XXXX____,
+ __XX____,XX______,
+ __XX____,XX______,
+ __XXXXXX,XX______,
+ __XX__XX,XXXXXXX_,
+ __XX__XX,XX_XX___,
+ __XX__XX,XX_XX___,
+ __XXXXXX,XX_XX___,
+ __XX____,XX_XX___,
+ __XX____,XX_XX___,
+ __XX____,XX_XX___,
+ __XX___X,X__XX___,
+ _XX___XX,___XX___,
+ ________,________,
+ ________,________,
+};
+
+/* char: 态 code:0xCCAC */
+static GUI_CONST_STORAGE unsigned char acCCAC[32] = {
+ _______X,X_______,
+ _______X,X_______,
+ _XXXXXXX,XXXXXXX_,
+ _______X,X_______,
+ ______XX,XX______,
+ _____XX_,_XX_____,
+ ___XXXXX,__XXX___,
+ _XXX___X,X___XXX_,
+ ________,________,
+ _______X,X_______,
+ ____XX__,XX__XX__,
+ __XXXX__,XX___XX_,
+ __XXXX__,__XX_XX_,
+ _XX__XXX,XXXX____,
+ ________,________,
+ ________,________,
+};
+
+/* char: 条 code:0xCCF5 */
+static GUI_CONST_STORAGE unsigned char acCCF5[32] = {
+ ____XX__,________,
+ ____XXXX,XXXXX___,
+ ___XXX__,__XX____,
+ __XX_XX_,_XX_____,
+ ______XX,XX______,
+ ____XXX_,_XXX____,
+ _XXXX__X,X__XXXX_,
+ _______X,X_______,
+ __XXXXXX,XXXXXX__,
+ _______X,X_______,
+ ____XX_X,X_XX____,
+ ___XX__X,X__XX___,
+ __XX___X,X___XX__,
+ _____XXX,X_______,
+ ________,________,
+ ________,________,
+};
+
+/* char: 停 code:0xCDA3 */
+static GUI_CONST_STORAGE unsigned char acCDA3[32] = {
+ ____XX__,_XX_____,
+ ____XXXX,XXXXXXX_,
+ ____XX__,________,
+ ___XX_XX,XXXXXX__,
+ ___XX_XX,____XX__,
+ __XXX_XX,XXXXXX__,
+ _XXXX___,________,
+ ___XXXXX,XXXXXXX_,
+ ___XXXX_,_____XX_,
+ ___XX_XX,XXXXXX__,
+ ___XX___,__XX____,
+ ___XX___,__XX____,
+ ___XX___,__XX____,
+ ___XX___,XXXX____,
+ ________,________,
+ ________,________,
+};
+
+/* char: 通 code:0xCDA8 */
+static GUI_CONST_STORAGE unsigned char acCDA8[32] = {
+ __XX__XX,XXXXXX__,
+ ___XX___,XX_XX___,
+ ___XX___,_XXX____,
+ ______XX,XXXXXX__,
+ ______XX,_XX_XX__,
+ _XXXX_XX,_XX_XX__,
+ ___XX_XX,XXXXXX__,
+ ___XX_XX,_XX_XX__,
+ ___XX_XX,_XX_XX__,
+ ___XX_XX,XXXXXX__,
+ ___XX_XX,_XX_XX__,
+ ___XX_XX,_XXXXX__,
+ __XXXX__,________,
+ _XX__XXX,XXXXXXX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 投 code:0xCDB6 */
+static GUI_CONST_STORAGE unsigned char acCDB6[32] = {
+ ___XX___,________,
+ ___XX__X,XXXXX___,
+ ___XX__X,X__XX___,
+ _XXXXXXX,X__XX___,
+ ___XX__X,X__XX___,
+ ___XX_XX,____XXX_,
+ ___XXXX_,________,
+ ___XXXXX,XXXXXX__,
+ _XXXX__X,X___XX__,
+ ___XX__X,X__XX___,
+ ___XX___,XXXX____,
+ ___XX___,_XX_____,
+ ___XX__X,XXXXX___,
+ _XXXXXXX,____XXX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 图 code:0xCDBC */
+static GUI_CONST_STORAGE unsigned char acCDBC[32] = {
+ __XXXXXX,XXXXXXX_,
+ __XX____,_____XX_,
+ __XX__XX,_____XX_,
+ __XX__XX,XXXX_XX_,
+ __XX_XX_,__XX_XX_,
+ __XXXXXX,_XX__XX_,
+ __XX___X,XX___XX_,
+ __XX_XXX,_XXX_XX_,
+ __XXXX_X,XX_XXXX_,
+ __XX____,_XX__XX_,
+ __XX_XXX,_____XX_,
+ __XX___X,XX___XX_,
+ __XX____,_XX__XX_,
+ __XXXXXX,XXXXXXX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 外 code:0xCDE2 */
+static GUI_CONST_STORAGE unsigned char acCDE2[32] = {
+ ___XX___,_XX_____,
+ ___XX___,_XX_____,
+ ___XX___,_XX_____,
+ ___XXXXX,_XX_____,
+ __XX__XX,_XXX____,
+ __XX__XX,_XXXX___,
+ _XXXX_XX,_XX_XX__,
+ ____XXX_,_XX__XX_,
+ _____XX_,_XX__XX_,
+ ____XX__,_XX_____,
+ ____XX__,_XX_____,
+ ___XX___,_XX_____,
+ __XX____,_XX_____,
+ _XX_____,_XX_____,
+ ________,________,
+ ________,________,
+};
+
+/* char: 微 code:0xCEA2 */
+static GUI_CONST_STORAGE unsigned char acCEA2[32] = {
+ ___XX_XX,__XX____,
+ ___XXXXX,XXXX____,
+ __XXXXXX,XXXX____,
+ _XX_XXXX,XXXXXXX_,
+ ___XX___,_XX_XX__,
+ ___XX___,__XXXX__,
+ __XXXXXX,XXXXXX__,
+ _XXX____,__XXXX__,
+ __XX_XXX,X_XXXX__,
+ __XX_XXX,X__XX___,
+ __XX_XXX,X__XX___,
+ __XX_XXX,XXXXXX__,
+ __XX_XXX,X_XXXX__,
+ __XXXX__,_XX__XX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 围 code:0xCEA7 */
+static GUI_CONST_STORAGE unsigned char acCEA7[32] = {
+ __XXXXXX,XXXXXXX_,
+ __XX___X,X____XX_,
+ __XX___X,X____XX_,
+ __XXXXXX,XXXXXXX_,
+ __XX___X,X____XX_,
+ __XX_XXX,XXXX_XX_,
+ __XX___X,X____XX_,
+ __XXXXXX,XXXXXXX_,
+ __XX___X,X__XXXX_,
+ __XX___X,X__XXXX_,
+ __XX___X,XXXX_XX_,
+ __XX___X,X____XX_,
+ __XXXXXX,XXXXXXX_,
+ __XX____,_____XX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 为 code:0xCEAA */
+static GUI_CONST_STORAGE unsigned char acCEAA[32] = {
+ ______XX,________,
+ ___XX_XX,________,
+ ____XXXX,________,
+ ______XX,________,
+ _XXXXXXX,XXXXXX__,
+ ______XX,____XX__,
+ _____XX_,____XX__,
+ _____XX_,XX__XX__,
+ _____XX_,_XX_XX__,
+ ____XX__,_XX_XX__,
+ ____XX__,____XX__,
+ ___XX___,____XX__,
+ __XX____,___XX___,
+ _XX_____,_XXX____,
+ ________,________,
+ ________,________,
+};
+
+/* char: 未 code:0xCEB4 */
+static GUI_CONST_STORAGE unsigned char acCEB4[32] = {
+ _______X,X_______,
+ _______X,X_______,
+ __XXXXXX,XXXXXX__,
+ _______X,X_______,
+ _______X,X_______,
+ _______X,X_______,
+ _XXXXXXX,XXXXXXX_,
+ ______XX,XX______,
+ _____XXX,XXX_____,
+ ____XX_X,X_XX____,
+ ___XX__X,X__XX___,
+ _XXX___X,X___XXX_,
+ _______X,X_______,
+ _______X,X_______,
+ ________,________,
+ ________,________,
+};
+
+/* char: 位 code:0xCEBB */
+static GUI_CONST_STORAGE unsigned char acCEBB[32] = {
+ ____XX__,XX______,
+ ____XX__,_XX_____,
+ ____XX__,_XX_____,
+ ___XX_XX,XXXXXX__,
+ ___XX___,________,
+ __XXX___,___XX___,
+ _XXXX_XX,___XX___,
+ ___XX_XX,___XX___,
+ ___XX__X,X__XX___,
+ ___XX__X,X_XX____,
+ ___XX__X,X_XX____,
+ ___XX___,__XX____,
+ ___XX___,_XX_____,
+ ___XXXXX,XXXXXXX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 温 code:0xCEC2 */
+static GUI_CONST_STORAGE unsigned char acCEC2[32] = {
+ ______XX,XXXXX___,
+ __XX__XX,___XX___,
+ ___XX_XX,___XX___,
+ ______XX,XXXXX___,
+ _XX___XX,___XX___,
+ __XX__XX,___XX___,
+ ______XX,XXXXX___,
+ ___XX___,________,
+ ___XXXXX,XXXXXX__,
+ __XX_XXX,X_XXXX__,
+ __XX_XXX,X_XXXX__,
+ _XX__XXX,X_XXXX__,
+ _XX__XXX,X_XXXX__,
+ ____XXXX,XXXXXXX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 文 code:0xCEC4 */
+static GUI_CONST_STORAGE unsigned char acCEC4[32] = {
+ ______XX,________,
+ _______X,X_______,
+ _______X,X_______,
+ _XXXXXXX,XXXXXXX_,
+ ____XX__,__XX____,
+ ____XX__,__XX____,
+ _____XX_,_XX_____,
+ _____XX_,_XX_____,
+ ______XX,XX______,
+ _______X,X_______,
+ ______XX,XX______,
+ _____XX_,_XX_____,
+ ___XXX__,__XXX___,
+ _XXX____,____XXX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 务 code:0xCEF1 */
+static GUI_CONST_STORAGE unsigned char acCEF1[32] = {
+ _____XX_,________,
+ ____XXXX,XXXXX___,
+ ___XXX__,__XX____,
+ __XX_XX_,_XX_____,
+ ______XX,XX______,
+ ____XXX_,_XXX____,
+ _XXXX___,___XXXX_,
+ ______XX,________,
+ __XXXXXX,XXXXX___,
+ ______XX,___XX___,
+ _____XX_,___XX___,
+ ____XX__,___XX___,
+ ___XX___,___XX___,
+ __XX____,_XXX____,
+ ________,________,
+ ________,________,
+};
+
+/* char: 息 code:0xCFA2 */
+static GUI_CONST_STORAGE unsigned char acCFA2[32] = {
+ ______XX,________,
+ _____XX_,________,
+ ___XXXXX,XXXXX___,
+ ___XX___,___XX___,
+ ___XXXXX,XXXXX___,
+ ___XX___,___XX___,
+ ___XXXXX,XXXXX___,
+ ___XX___,___XX___,
+ ___XXXXX,XXXXX___,
+ _______X,X_______,
+ ____XX__,XX__XX__,
+ __XXXX__,XX___XX_,
+ __XXXX__,__XX_XX_,
+ _XX__XXX,XXXX____,
+ ________,________,
+ ________,________,
+};
+
+/* char: 系 code:0xCFB5 */
+static GUI_CONST_STORAGE unsigned char acCFB5[32] = {
+ ________,XXXXX___,
+ __XXXXXX,X_______,
+ ______XX,________,
+ _____XX_,__XX____,
+ ____XX__,_XX_____,
+ ___XXXXX,XX______,
+ ______XX,__XX____,
+ ____XXX_,___XX___,
+ __XXXXXX,XXXXXX__,
+ _______X,X___XX__,
+ ____XX_X,X_XX____,
+ ___XX__X,X__XX___,
+ __XX___X,X___XX__,
+ _____XXX,X_______,
+ ________,________,
+ ________,________,
+};
+
+/* char: 下 code:0xCFC2 */
+static GUI_CONST_STORAGE unsigned char acCFC2[32] = {
+ ________,________,
+ _XXXXXXX,XXXXXXX_,
+ ______XX,________,
+ ______XX,________,
+ ______XX,________,
+ ______XX,_XX_____,
+ ______XX,__XX____,
+ ______XX,___XX___,
+ ______XX,___XX___,
+ ______XX,________,
+ ______XX,________,
+ ______XX,________,
+ ______XX,________,
+ ______XX,________,
+ ________,________,
+ ________,________,
+};
+
+/* char: 显 code:0xCFD4 */
+static GUI_CONST_STORAGE unsigned char acCFD4[32] = {
+ ___XXXXX,XXXXX___,
+ ___XX___,___XX___,
+ ___XX___,___XX___,
+ ___XXXXX,XXXXX___,
+ ___XX___,___XX___,
+ ___XX___,___XX___,
+ ___XXXXX,XXXXX___,
+ _____XX_,_XX_____,
+ __XX_XX_,_XX_XX__,
+ ___XXXX_,_XX_XX__,
+ ___XXXX_,_XXXX___,
+ _____XX_,_XX_____,
+ _____XX_,_XX_____,
+ _XXXXXXX,XXXXXXX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 限 code:0xCFDE */
+static GUI_CONST_STORAGE unsigned char acCFDE[32] = {
+ ________,________,
+ __XXXXXX,XXXXXX__,
+ __XX_XXX,X___XX__,
+ __XX_XXX,X___XX__,
+ __XXXX_X,XXXXXX__,
+ __XXXX_X,X___XX__,
+ __XX_XXX,X___XX__,
+ __XX_XXX,XXXXXX__,
+ __XX_XXX,X_XX_XX_,
+ __XX_XXX,X_XXXX__,
+ __XXXX_X,X__XX___,
+ __XX___X,XXXXX___,
+ __XX___X,XX__XX__,
+ __XX___X,X____XX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 线 code:0xCFDF */
+static GUI_CONST_STORAGE unsigned char acCFDF[32] = {
+ ___XX___,_XXXX___,
+ ___XX___,_XX_XX__,
+ __XX_XX_,_XX_____,
+ __XX_XX_,_XXXXX__,
+ _XXXXX_X,XXX_____,
+ ____XX__,_XX_____,
+ ___XX___,_XXXXXX_,
+ __XX___X,XXXX____,
+ _XXXXXX_,_XX_XX__,
+ ________,_XXXX___,
+ ________,__XX_XX_,
+ ____XXX_,_XXXXXX_,
+ _XXXX__X,XX__XXX_,
+ ________,_____XX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 相 code:0xCFE0 */
+static GUI_CONST_STORAGE unsigned char acCFE0[32] = {
+ ____XX__,________,
+ ____XX__,XXXXXXX_,
+ ____XX__,XX___XX_,
+ _XXXXXXX,XX___XX_,
+ ____XX__,XX___XX_,
+ ___XXX__,XXXXXXX_,
+ ___XXXX_,XX___XX_,
+ __XXXXXX,XX___XX_,
+ __XXXX__,XXXXXXX_,
+ _XX_XX__,XX___XX_,
+ ____XX__,XX___XX_,
+ ____XX__,XX___XX_,
+ ____XX__,XXXXXXX_,
+ ____XX__,XX___XX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 项 code:0xCFEE */
+static GUI_CONST_STORAGE unsigned char acCFEE[32] = {
+ ________,________,
+ ______XX,XXXXXXX_,
+ _XXXXX__,_XX_____,
+ ___XX___,XX______,
+ ___XX_XX,XXXXXX__,
+ ___XX_XX,____XX__,
+ ___XX_XX,_XX_XX__,
+ ___XX_XX,_XX_XX__,
+ ___XX_XX,_XX_XX__,
+ ___XXXXX,XX__XX__,
+ _XXX____,XXXX____,
+ _______X,X__XX___,
+ ______XX,____XX__,
+ _____XX_,____XX__,
+ ________,________,
+ ________,________,
+};
+
+/* char: 向 code:0xCFF2 */
+static GUI_CONST_STORAGE unsigned char acCFF2[32] = {
+ ______XX,________,
+ _____XX_,________,
+ __XXXXXX,XXXXXXX_,
+ __XX____,_____XX_,
+ __XX____,_____XX_,
+ __XX_XXX,XXXX_XX_,
+ __XX_XX_,__XX_XX_,
+ __XX_XX_,__XX_XX_,
+ __XX_XX_,__XX_XX_,
+ __XX_XXX,XXXX_XX_,
+ __XX____,_____XX_,
+ __XX____,_____XX_,
+ __XX____,_____XX_,
+ __XX____,___XXXX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 消 code:0xCFFB */
+static GUI_CONST_STORAGE unsigned char acCFFB[32] = {
+ ________,_XX_____,
+ __XX__XX,_XX_XX__,
+ ___XX__X,XXXXX___,
+ ____XX__,_XX_____,
+ ______XX,XXXXXX__,
+ _XX___XX,____XX__,
+ __XX__XX,____XX__,
+ ____XXXX,XXXXXX__,
+ ____XXXX,____XX__,
+ ___XX_XX,____XX__,
+ ___XX_XX,XXXXXX__,
+ __XX__XX,____XX__,
+ __XX__XX,____XX__,
+ ______XX,__XXXX__,
+ ________,________,
+ ________,________,
+};
+
+/* char: 小 code:0xD0A1 */
+static GUI_CONST_STORAGE unsigned char acD0A1[32] = {
+ _______X,X_______,
+ _______X,X_______,
+ _______X,X_______,
+ _______X,X_______,
+ ____XX_X,X_XX____,
+ ____XX_X,X__XX___,
+ ___XX__X,X___XX__,
+ __XX___X,X____XX_,
+ _XX____X,X____XX_,
+ _______X,X_______,
+ _______X,X_______,
+ _______X,X_______,
+ _______X,X_______,
+ _____XXX,X_______,
+ ________,________,
+ ________,________,
+};
+
+/* char: 校 code:0xD0A3 */
+static GUI_CONST_STORAGE unsigned char acD0A3[32] = {
+ ____XX__,_XX_____,
+ ____XX__,__XX____,
+ ____XX_X,XXXXXXX_,
+ _XXXXXXX,________,
+ ____XX__,_XXXX___,
+ ___XXX__,XX__XX__,
+ ___XXXXX,X____XX_,
+ __XXXXXX,XX__XX__,
+ __XXXX__,XX__XX__,
+ _XX_XX__,_XXXX___,
+ ____XX__,__XX____,
+ ____XX__,_XXXX___,
+ ____XX__,XX__XX__,
+ ____XX_X,X____XX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 写 code:0xD0B4 */
+static GUI_CONST_STORAGE unsigned char acD0B4[32] = {
+ ________,________,
+ _XXXXXXX,XXXXXXX_,
+ _XX_____,_____XX_,
+ ____XX__,________,
+ ____XXXX,XXXXX___,
+ ____XX__,________,
+ ___XX___,________,
+ ___XXXXX,XXXXXX__,
+ ________,____XX__,
+ ________,____XX__,
+ _XXXXXXX,XXXXXX__,
+ ________,____XX__,
+ ________,____XX__,
+ ________,__XXX___,
+ ________,________,
+ ________,________,
+};
+
+/* char: 新 code:0xD0C2 */
+static GUI_CONST_STORAGE unsigned char acD0C2[32] = {
+ ___XX___,____XXX_,
+ ____XX__,_XXXX___,
+ _XXXXXXX,XXX_____,
+ __XX__XX,_XX_____,
+ ___XXXX_,_XX_____,
+ _XXXXXXX,XXXXXXX_,
+ ________,_XX_XX__,
+ ____XX__,_XX_XX__,
+ _XXXXXXX,XXX_XX__,
+ ____XX__,_XX_XX__,
+ __XXXXXX,_XX_XX__,
+ _XX_XX_X,XXX_XX__,
+ ____XX__,XX__XX__,
+ __XXXX_X,X___XX__,
+ ________,________,
+ ________,________,
+};
+
+/* char: 信 code:0xD0C5 */
+static GUI_CONST_STORAGE unsigned char acD0C5[32] = {
+ ____XX__,XX______,
+ ____XX__,_XX_____,
+ ___XXXXX,XXXXXXX_,
+ ___XX___,________,
+ __XXX_XX,XXXXXX__,
+ _XXXX___,________,
+ ___XX_XX,XXXXXX__,
+ ___XX___,________,
+ ___XX_XX,XXXXXX__,
+ ___XX_XX,____XX__,
+ ___XX_XX,____XX__,
+ ___XX_XX,____XX__,
+ ___XX_XX,XXXXXX__,
+ ___XX_XX,____XX__,
+ ________,________,
+ ________,________,
+};
+
+/* char: 型 code:0xD0CD */
+static GUI_CONST_STORAGE unsigned char acD0CD[32] = {
+ ________,____XX__,
+ __XXXXXX,XXX_XX__,
+ ___XX_XX,_XX_XX__,
+ ___XX_XX,_XX_XX__,
+ _XXXXXXX,XXX_XX__,
+ ___XX_XX,_XX_XX__,
+ ___XX_XX,____XX__,
+ __XX__XX,____XX__,
+ _XX____X,X_XXXX__,
+ _______X,X_______,
+ __XXXXXX,XXXXXX__,
+ _______X,X_______,
+ _______X,X_______,
+ _XXXXXXX,XXXXXXX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 行 code:0xD0D0 */
+static GUI_CONST_STORAGE unsigned char acD0D0[32] = {
+ ____XX__,________,
+ ___XX__X,XXXXXX__,
+ __XX____,________,
+ _XX_XX__,________,
+ ____XX__,________,
+ ___XX_XX,XXXXXXX_,
+ __XXX___,__XX____,
+ _XXXX___,__XX____,
+ ___XX___,__XX____,
+ ___XX___,__XX____,
+ ___XX___,__XX____,
+ ___XX___,__XX____,
+ ___XX___,__XX____,
+ ___XX___,XXXX____,
+ ________,________,
+ ________,________,
+};
+
+/* char: 序 code:0xD0F2 */
+static GUI_CONST_STORAGE unsigned char acD0F2[32] = {
+ _______X,X_______,
+ ________,XX______,
+ ___XXXXX,XXXXXXX_,
+ ___XX___,________,
+ ___XXXXX,XXXXXX__,
+ ___XX___,___XX___,
+ ___XX__X,X_XX____,
+ ___XX___,XXX_____,
+ ___XXXXX,XXXXXXX_,
+ ___XX___,_XX__XX_,
+ ___XX___,_XX_XX__,
+ __XX____,_XX_____,
+ __XX____,_XX_____,
+ _XX____X,XXX_____,
+ ________,________,
+ ________,________,
+};
+
+/* char: 选 code:0xD1A1 */
+static GUI_CONST_STORAGE unsigned char acD1A1[32] = {
+ ________,_XX_____,
+ __XX__XX,_XX_____,
+ ___XX_XX,_XX_____,
+ ___XX_XX,XXXXXX__,
+ _____XX_,_XX_____,
+ ________,_XX_____,
+ _XXXXXXX,XXXXXXX_,
+ ___XX___,XXXX____,
+ ___XX___,XXXX____,
+ ___XX__X,X_XX____,
+ ___XX_XX,__XX_XX_,
+ ___XXXX_,___XXXX_,
+ __XXXX__,________,
+ _XX__XXX,XXXXXXX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 讯 code:0xD1B6 */
+static GUI_CONST_STORAGE unsigned char acD1B6[32] = {
+ __XX____,________,
+ ___XXXXX,XXXXX___,
+ ___XX__X,X__XX___,
+ _______X,X__XX___,
+ _______X,X__XX___,
+ _XXXX__X,X__XX___,
+ ___XXXXX,XXXXX___,
+ ___XX__X,X__XX___,
+ ___XX__X,X__XX___,
+ ___XX__X,X__XXXX_,
+ ___XXXXX,X__XXXX_,
+ ___XXX_X,X__XXXX_,
+ ___XX__X,X___XXX_,
+ _______X,X____XX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 压 code:0xD1B9 */
+static GUI_CONST_STORAGE unsigned char acD1B9[32] = {
+ ________,________,
+ ___XXXXX,XXXXXXX_,
+ ___XX___,________,
+ ___XX___,XX______,
+ ___XX___,XX______,
+ ___XX___,XX______,
+ ___XXXXX,XXXXXX__,
+ ___XX___,XX______,
+ ___XX___,XX______,
+ ___XX___,XX_XX___,
+ ___XX___,XX__XX__,
+ __XX____,XX__XX__,
+ __XX____,XX______,
+ _XX_XXXX,XXXXXXX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 牙 code:0xD1C0 */
+static GUI_CONST_STORAGE unsigned char acD1C0[32] = {
+ ________,________,
+ __XXXXXX,XXXXXX__,
+ ________,__XX____,
+ ____XX__,__XX____,
+ ____XX__,__XX____,
+ ___XX___,__XX____,
+ ___XXXXX,XXXXXXX_,
+ ________,XXXX____,
+ _______X,X_XX____,
+ ______XX,__XX____,
+ _____XX_,__XX____,
+ ___XXX__,__XX____,
+ _XXX____,__XX____,
+ ________,XXXX____,
+ ________,________,
+ ________,________,
+};
+
+/* char: 言 code:0xD1D4 */
+static GUI_CONST_STORAGE unsigned char acD1D4[32] = {
+ ______XX,________,
+ _______X,X_______,
+ _XXXXXXX,XXXXXXX_,
+ ________,________,
+ ___XXXXX,XXXXX___,
+ ________,________,
+ ___XXXXX,XXXXX___,
+ ________,________,
+ ___XXXXX,XXXXX___,
+ ___XX___,___XX___,
+ ___XX___,___XX___,
+ ___XX___,___XX___,
+ ___XXXXX,XXXXX___,
+ ___XX___,___XX___,
+ ________,________,
+ ________,________,
+};
+
+/* char: 要 code:0xD2AA */
+static GUI_CONST_STORAGE unsigned char acD2AA[32] = {
+ _XXXXXXX,XXXXXXX_,
+ _____XX_,_XX_____,
+ _____XX_,_XX_____,
+ __XXXXXX,XXXXXX__,
+ __XX_XX_,_XX_XX__,
+ __XX_XX_,_XX_XX__,
+ __XXXXXX,XXXXXX__,
+ ______XX,________,
+ _XXXXXXX,XXXXXXX_,
+ _____XX_,__XX____,
+ ____XXX_,_XX_____,
+ ______XX,XX______,
+ ____XXX_,_XXXX___,
+ _XXXX___,____XX__,
+ ________,________,
+ ________,________,
+};
+
+/* char: 页 code:0xD2B3 */
+static GUI_CONST_STORAGE unsigned char acD2B3[32] = {
+ ________,________,
+ _XXXXXXX,XXXXXXX_,
+ _______X,X_______,
+ ______XX,________,
+ __XXXXXX,XXXXXX__,
+ __XX____,____XX__,
+ __XX___X,X___XX__,
+ __XX___X,X___XX__,
+ __XX___X,X___XX__,
+ __XX___X,X___XX__,
+ __XX__XX,____XX__,
+ _____XX_,XXXX____,
+ ___XXX__,___XXX__,
+ _XXX____,_____XX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 一 code:0xD2BB */
+static GUI_CONST_STORAGE unsigned char acD2BB[32] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ _XXXXXXX,XXXXXXX_,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+};
+
+/* char: 移 code:0xD2C6 */
+static GUI_CONST_STORAGE unsigned char acD2C6[32] = {
+ ________,_XX_____,
+ ____XXX_,_XX_____,
+ _XXXX___,XXXXX___,
+ ___XX__X,X__XX___,
+ ___XX_XX,XXXX____,
+ _XXXXXX_,_XX_____,
+ ___XX___,XX_XX___,
+ ___XXXXX,X_XX____,
+ __XXXXX_,_XXXXXX_,
+ __XXX___,XX__XX__,
+ _XXXX_XX,XXXXX___,
+ ___XX___,__XX____,
+ ___XX___,XXX_____,
+ ___XX_XX,X_______,
+ ________,________,
+ ________,________,
+};
+
+/* char: 仪 code:0xD2C7 */
+static GUI_CONST_STORAGE unsigned char acD2C7[32] = {
+ ____XX__,XX______,
+ ____XX__,_XX_____,
+ ____XX__,_XX_XX__,
+ ___XX_XX,____XX__,
+ ___XX_XX,____XX__,
+ __XXX__X,X__XX___,
+ _XXXX__X,X__XX___,
+ ___XX___,XXXX____,
+ ___XX___,XXXX____,
+ ___XX___,_XX_____,
+ ___XX___,XXXX____,
+ ___XX__X,X__XX___,
+ ___XX_XX,____XX__,
+ ___XXXX_,_____XX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 已 code:0xD2D1 */
+static GUI_CONST_STORAGE unsigned char acD2D1[32] = {
+ ________,________,
+ __XXXXXX,XXXXXX__,
+ ________,____XX__,
+ ________,____XX__,
+ __XX____,____XX__,
+ __XX____,____XX__,
+ __XXXXXX,XXXXXX__,
+ __XX____,________,
+ __XX____,________,
+ __XX____,________,
+ __XX____,________,
+ __XX____,_____XX_,
+ __XX____,_____XX_,
+ ___XXXXX,XXXXXXX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 益 code:0xD2E6 */
+static GUI_CONST_STORAGE unsigned char acD2E6[32] = {
+ ___XX___,___XX___,
+ ____XX__,__XX____,
+ ________,________,
+ _XXXXXXX,XXXXXXX_,
+ ________,________,
+ ____XX__,__XX____,
+ ___XX___,___XX___,
+ __XX____,____XX__,
+ ___XXXXX,XXXXX___,
+ ___XX_XX,XX_XX___,
+ ___XX_XX,XX_XX___,
+ ___XX_XX,XX_XX___,
+ ___XX_XX,XX_XX___,
+ _XXXXXXX,XXXXXXX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 英 code:0xD3A2 */
+static GUI_CONST_STORAGE unsigned char acD3A2[32] = {
+ _____XX_,_XX_____,
+ _____XX_,_XX_____,
+ _XXXXXXX,XXXXXXX_,
+ _____XX_,_XX_____,
+ _______X,X_______,
+ ___XXXXX,XXXXX___,
+ ___XX__X,X__XX___,
+ ___XX__X,X__XX___,
+ ___XX__X,X__XX___,
+ _XXXXXXX,XXXXXXX_,
+ ______XX,XX______,
+ _____XX_,_XX_____,
+ ___XXX__,__XXX___,
+ _XXX____,____XXX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 迎 code:0xD3AD */
+static GUI_CONST_STORAGE unsigned char acD3AD[32] = {
+ ________,________,
+ __XX___X,X_______,
+ ___XXXXX,_XXXXXX_,
+ ___XXXX_,_XX__XX_,
+ _____XX_,_XX__XX_,
+ _____XX_,_XX__XX_,
+ _XXXXXX_,_XX__XX_,
+ ___XXXX_,_XX__XX_,
+ ___XXXXX,XXX__XX_,
+ ___XXXXX,_XXXXXX_,
+ ___XXXX_,_XX_____,
+ ___XX___,_XX_____,
+ __XXXX__,_XX_____,
+ _XX__XXX,XXXXXXX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 硬 code:0xD3B2 */
+static GUI_CONST_STORAGE unsigned char acD3B2[32] = {
+ ________,________,
+ _XXXXXXX,XXXXXXX_,
+ ___XX___,__XX____,
+ ___XX__X,XXXXXXX_,
+ __XX___X,X_XX_XX_,
+ __XXXXXX,X_XX_XX_,
+ _XXX_XXX,XXXXXXX_,
+ __XX_XXX,X_XX_XX_,
+ __XX_XXX,X_XX_XX_,
+ __XX_XXX,XXXXXXX_,
+ __XXXXX_,XXXX____,
+ __XX_XX_,_XX_____,
+ ________,XXXXX___,
+ ______XX,X___XXX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 用 code:0xD3C3 */
+static GUI_CONST_STORAGE unsigned char acD3C3[32] = {
+ ________,________,
+ ___XXXXX,XXXXXXX_,
+ ___XX___,XX___XX_,
+ ___XX___,XX___XX_,
+ ___XX___,XX___XX_,
+ ___XXXXX,XXXXXXX_,
+ ___XX___,XX___XX_,
+ ___XX___,XX___XX_,
+ ___XXXXX,XXXXXXX_,
+ ___XX___,XX___XX_,
+ ___XX___,XX___XX_,
+ __XX____,XX___XX_,
+ __XX____,XX___XX_,
+ _XX_____,___XXXX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 有 code:0xD3D0 */
+static GUI_CONST_STORAGE unsigned char acD3D0[32] = {
+ ______XX,________,
+ ______XX,________,
+ _XXXXXXX,XXXXXXX_,
+ _____XX_,________,
+ ____XXXX,XXXXX___,
+ ___XXX__,___XX___,
+ __XXXX__,___XX___,
+ _XX_XXXX,XXXXX___,
+ ____XX__,___XX___,
+ ____XX__,___XX___,
+ ____XXXX,XXXXX___,
+ ____XX__,___XX___,
+ ____XX__,___XX___,
+ ____XX__,_XXXX___,
+ ________,________,
+ ________,________,
+};
+
+/* char: 语 code:0xD3EF */
+static GUI_CONST_STORAGE unsigned char acD3EF[32] = {
+ __XX_XXX,XXXXXXX_,
+ ___XX___,XX______,
+ ___XX___,XX______,
+ ______XX,XXXXXX__,
+ _______X,X___XX__,
+ _XXXX__X,X___XX__,
+ ___XXXXX,XXXXXXX_,
+ ___XX___,________,
+ ___XX___,________,
+ ___XX_XX,XXXXXX__,
+ ___XXXXX,____XX__,
+ ___XXXXX,____XX__,
+ ___XX_XX,XXXXXX__,
+ ______XX,____XX__,
+ ________,________,
+ ________,________,
+};
+
+/* char: 域 code:0xD3F2 */
+static GUI_CONST_STORAGE unsigned char acD3F2[32] = {
+ ___XX___,__XX____,
+ ___XX___,__XXXX__,
+ ___XX___,__XX_XX_,
+ ___XX_XX,XXXXXXX_,
+ _XXXXX__,__XX____,
+ ___XX_XX,XXXX_XX_,
+ ___XX_XX,XXXX_XX_,
+ ___XX_XX,XXXX_XX_,
+ ___XX_XX,XXXXXX__,
+ ___XX___,__XXXX__,
+ ___XXX__,XX_XXXX_,
+ _XXX__XX,X_XXXXX_,
+ ________,_XX_XXX_,
+ ________,XX___XX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 源 code:0xD4B4 */
+static GUI_CONST_STORAGE unsigned char acD4B4[32] = {
+ ________,________,
+ __XX__XX,XXXXXXX_,
+ ___XX_XX,__XX____,
+ ____XXXX,_XX_____,
+ ______XX,XXXXXX__,
+ _XX___XX,XX__XX__,
+ __XX__XX,XXXXXX__,
+ ____XXXX,XX__XX__,
+ ____XXXX,XXXXXX__,
+ ___XX_XX,__XX____,
+ ___XX_XX,XXXXXX__,
+ __XX_XX_,XXXX_XX_,
+ __XX_XXX,X_XX_XX_,
+ ____XX__,_XXX____,
+ ________,________,
+ ________,________,
+};
+
+/* char: 运 code:0xD4CB */
+static GUI_CONST_STORAGE unsigned char acD4CB[32] = {
+ ________,________,
+ __XX__XX,XXXXX___,
+ ___XX___,________,
+ ___XX___,________,
+ ________,________,
+ _____XXX,XXXXXXX_,
+ _XXXX___,XX______,
+ ___XX___,XX______,
+ ___XX__X,X_XX____,
+ ___XX_XX,___XX___,
+ ___XXXXX,XXXXXX__,
+ ___XX___,____XX__,
+ __XXXX__,________,
+ _XX__XXX,XXXXXXX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 在 code:0xD4DA */
+static GUI_CONST_STORAGE unsigned char acD4DA[32] = {
+ ______XX,________,
+ ______XX,________,
+ _XXXXXXX,XXXXXXX_,
+ _____XX_,________,
+ ____XX__,_XX_____,
+ ____XX__,_XX_____,
+ ___XXX__,_XX_____,
+ __XXXXXX,XXXXXX__,
+ _XX_XX__,_XX_____,
+ ____XX__,_XX_____,
+ ____XX__,_XX_____,
+ ____XX__,_XX_____,
+ ____XXXX,XXXXXXX_,
+ ____XX__,________,
+ ________,________,
+ ________,________,
+};
+
+/* char: 造 code:0xD4EC */
+static GUI_CONST_STORAGE unsigned char acD4EC[32] = {
+ ________,_XX_____,
+ __XX__XX,_XX_____,
+ ___XX_XX,XXXXXX__,
+ ___XXXX_,_XX_____,
+ ________,_XX_____,
+ _____XXX,XXXXXXX_,
+ _XXXX___,________,
+ ___XX___,________,
+ ___XX_XX,XXXXXX__,
+ ___XX_XX,____XX__,
+ ___XX_XX,____XX__,
+ ___XX_XX,XXXXXX__,
+ __XXXX__,________,
+ _XX__XXX,XXXXXXX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 择 code:0xD4F1 */
+static GUI_CONST_STORAGE unsigned char acD4F1[32] = {
+ ___XX___,________,
+ ___XX_XX,XXXXXX__,
+ ___XX__X,X__XX___,
+ _XXXXXX_,XXXX____,
+ ___XX___,_XX_____,
+ ___XX___,XXXXX___,
+ ___XX_XX,X___XXX_,
+ ___XXX__,_XX_____,
+ _XXXX__X,XXXXX___,
+ ___XX___,_XX_____,
+ ___XX___,_XX_____,
+ ___XXXXX,XXXXXXX_,
+ ___XX___,_XX_____,
+ _XXXX___,_XX_____,
+ ________,________,
+ ________,________,
+};
+
+/* char: 增 code:0xD4F6 */
+static GUI_CONST_STORAGE unsigned char acD4F6[32] = {
+ ___XX_XX,____XX__,
+ ___XX__X,X__XX___,
+ ___XXXXX,XXXXXXX_,
+ ___XXXX_,_XX__XX_,
+ _XXXXXXX,XXXXXXX_,
+ ___XXXX_,_XX__XX_,
+ ___XXXXX,XXXXXXX_,
+ ___XX___,________,
+ ___XX_XX,XXXXXX__,
+ ___XX_XX,____XX__,
+ ___XXXXX,XXXXXX__,
+ _XXX__XX,____XX__,
+ ______XX,XXXXXX__,
+ ______XX,____XX__,
+ ________,________,
+ ________,________,
+};
+
+/* char: 障 code:0xD5CF */
+static GUI_CONST_STORAGE unsigned char acD5CF[32] = {
+ ________,_XX_____,
+ _XXXXXXX,XXXXXX__,
+ _XX_XX_X,X__XX___,
+ _XX_XXXX,XXXXXXX_,
+ _XXXX___,________,
+ _XXXX_XX,XXXXXX__,
+ _XX_XXXX,____XX__,
+ _XX_XXXX,XXXXXX__,
+ _XX_XXXX,____XX__,
+ _XX_XXXX,XXXXXX__,
+ _XXXX___,_XX_____,
+ _XX__XXX,XXXXXXX_,
+ _XX_____,_XX_____,
+ _XX_____,_XX_____,
+ ________,________,
+ ________,________,
+};
+
+/* char: 诊 code:0xD5EF */
+static GUI_CONST_STORAGE unsigned char acD5EF[32] = {
+ __XX____,_XX_____,
+ ___XX___,_XX_____,
+ ___XX___,XXXX____,
+ _______X,X__XX___,
+ _____XXX,_XX_XXX_,
+ _XXXX___,XX______,
+ ___XX__X,X_______,
+ ___XX_XX,__XX____,
+ ___XX___,_XX_____,
+ ___XX___,XX__XX__,
+ ___XX_XX,X__XX___,
+ ___XXX__,__XX____,
+ ___XX___,XXX_____,
+ ______XX,X_______,
+ ________,________,
+ ________,________,
+};
+
+/* char: 整 code:0xD5FB */
+static GUI_CONST_STORAGE unsigned char acD5FB[32] = {
+ ____XX__,_XX_____,
+ _XXXXXXX,XXX_____,
+ ____XX__,_XXXXXX_,
+ __XXXXXX,XX__XX__,
+ __XXXXXX,XXXXX___,
+ __XXXXXX,__XX____,
+ ___XXXX_,_XXXX___,
+ __XXXXXX,XX__XXX_,
+ _XX_XX__,________,
+ __XXXXXX,XXXXXX__,
+ _______X,X_______,
+ ____XX_X,XXXXX___,
+ ____XX_X,X_______,
+ _XXXXXXX,XXXXXXX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 正 code:0xD5FD */
+static GUI_CONST_STORAGE unsigned char acD5FD[32] = {
+ ________,________,
+ __XXXXXX,XXXXXX__,
+ _______X,X_______,
+ _______X,X_______,
+ _______X,X_______,
+ ___XX__X,X_______,
+ ___XX__X,X_______,
+ ___XX__X,XXXXX___,
+ ___XX__X,X_______,
+ ___XX__X,X_______,
+ ___XX__X,X_______,
+ ___XX__X,X_______,
+ ___XX__X,X_______,
+ _XXXXXXX,XXXXXXX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 知 code:0xD6AA */
+static GUI_CONST_STORAGE unsigned char acD6AA[32] = {
+ ___XX___,________,
+ ___XX___,________,
+ ___XX___,_XXXXXX_,
+ __XXXXXX,_XX__XX_,
+ __XXXX__,_XX__XX_,
+ _XX_XX__,_XX__XX_,
+ ____XX__,_XX__XX_,
+ _XXXXXXX,XXX__XX_,
+ ____XX__,_XX__XX_,
+ ____XX__,_XX__XX_,
+ ___XXXX_,_XX__XX_,
+ ___XX_XX,_XXXXXX_,
+ __XX__XX,_XX__XX_,
+ _XX_____,________,
+ ________,________,
+ ________,________,
+};
+
+/* char: 直 code:0xD6B1 */
+static GUI_CONST_STORAGE unsigned char acD6B1[32] = {
+ _______X,X_______,
+ _______X,X_______,
+ __XXXXXX,XXXXXX__,
+ _______X,X_______,
+ ___XXXXX,XXXXX___,
+ ___XX___,___XX___,
+ ___XXXXX,XXXXX___,
+ ___XX___,___XX___,
+ ___XXXXX,XXXXX___,
+ ___XX___,___XX___,
+ ___XXXXX,XXXXX___,
+ ___XX___,___XX___,
+ ___XX___,___XX___,
+ _XXXXXXX,XXXXXXX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 执 code:0xD6B4 */
+static GUI_CONST_STORAGE unsigned char acD6B4[32] = {
+ ___XX___,XX______,
+ ___XX___,XX______,
+ ___XX___,XX______,
+ _XXXXXXX,XXXXX___,
+ ___XX___,XX_XX___,
+ ___XX___,XX_XX___,
+ ___XX_XX,XX_XX___,
+ ___XXX_X,XX_XX___,
+ _XXXX___,XX_XX___,
+ ___XX___,XX_XX___,
+ ___XX__X,XXXXX___,
+ ___XX__X,XXXXXXX_,
+ ___XX_XX,____XXX_,
+ _XXXXXX_,_____XX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 址 code:0xD6B7 */
+static GUI_CONST_STORAGE unsigned char acD6B7[32] = {
+ ___XX___,__XX____,
+ ___XX___,__XX____,
+ ___XX___,__XX____,
+ ___XX___,__XX____,
+ _XXXXXXX,X_XX____,
+ ___XX__X,X_XXXXX_,
+ ___XX__X,X_XX____,
+ ___XX__X,X_XX____,
+ ___XX__X,X_XX____,
+ ___XX__X,X_XX____,
+ ___XXXXX,X_XX____,
+ _XXXX__X,X_XX____,
+ _______X,X_XX____,
+ _____XXX,XXXXXXX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 指 code:0xD6B8 */
+static GUI_CONST_STORAGE unsigned char acD6B8[32] = {
+ ___XX__X,X_______,
+ ___XX__X,X__XXX__,
+ ___XX__X,XXXX____,
+ _XXXXXXX,X____XX_,
+ ___XX__X,X____XX_,
+ ___XX___,XXXXXXX_,
+ ___XXXX_,________,
+ ___XXX_X,XXXXXX__,
+ _XXXX__X,X___XX__,
+ ___XX__X,X___XX__,
+ ___XX__X,XXXXXX__,
+ ___XX__X,X___XX__,
+ ___XX__X,X___XX__,
+ _XXXX__X,XXXXXX__,
+ ________,________,
+ ________,________,
+};
+
+/* char: 置 code:0xD6C3 */
+static GUI_CONST_STORAGE unsigned char acD6C3[32] = {
+ __XXXXXX,XXXXXX__,
+ __XX_XX_,_XX_XX__,
+ __XX_XX_,_XX_XX__,
+ __XXXXXX,XXXXXX__,
+ _______X,X_______,
+ __XXXXXX,XXXXXX__,
+ _______X,X_______,
+ ___XXXXX,XXXXX___,
+ ___XX___,___XX___,
+ ___XX___,___XX___,
+ ___XX__X,X__XX___,
+ ___XX__X,X__XX___,
+ ___XX__X,X__XX___,
+ _XXXXXXX,XXXXXXX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 制 code:0xD6C6 */
+static GUI_CONST_STORAGE unsigned char acD6C6[32] = {
+ _____XX_,____XX__,
+ __XX_XX_,____XX__,
+ __XXXXXX,XXXXXX__,
+ _XX__XX_,__XXXX__,
+ _____XX_,__XXXX__,
+ _XXXXXXX,XXXXXX__,
+ _____XX_,__XXXX__,
+ _____XX_,__XXXX__,
+ __XXXXXX,XXXXXX__,
+ __XX_XX_,XXXXXX__,
+ __XX_XX_,XX__XX__,
+ __XX_XX_,XX__XX__,
+ __XX_XXX,XX__XX__,
+ _____XX_,__XXXX__,
+ ________,________,
+ ________,________,
+};
+
+/* char: 智 code:0xD6C7 */
+static GUI_CONST_STORAGE unsigned char acD6C7[32] = {
+ __XX____,________,
+ __XXXXXX,XXXXXX__,
+ _XX_XX__,XX__XX__,
+ ____XX__,XX__XX__,
+ _XXXXXXX,XX__XX__,
+ ___XXXX_,XX__XX__,
+ __XX__XX,XXXXXX__,
+ _XX_____,________,
+ ___XXXXX,XXXXX___,
+ ___XX___,___XX___,
+ ___XXXXX,XXXXX___,
+ ___XX___,___XX___,
+ ___XXXXX,XXXXX___,
+ ___XX___,___XX___,
+ ________,________,
+ ________,________,
+};
+
+/* char: 中 code:0xD6D0 */
+static GUI_CONST_STORAGE unsigned char acD6D0[32] = {
+ _______X,X_______,
+ _______X,X_______,
+ __XXXXXX,XXXXXX__,
+ __XX___X,X___XX__,
+ __XX___X,X___XX__,
+ __XX___X,X___XX__,
+ __XX___X,X___XX__,
+ __XX___X,X___XX__,
+ __XXXXXX,XXXXXX__,
+ __XX___X,X___XX__,
+ _______X,X_______,
+ _______X,X_______,
+ _______X,X_______,
+ _______X,X_______,
+ ________,________,
+ ________,________,
+};
+
+/* char: 重 code:0xD6D8 */
+static GUI_CONST_STORAGE unsigned char acD6D8[32] = {
+ ________,XXXXXX__,
+ __XXXXXX,X_______,
+ _______X,X_______,
+ _XXXXXXX,XXXXXXX_,
+ _______X,X_______,
+ ___XXXXX,XXXXX___,
+ ___XX__X,X__XX___,
+ ___XXXXX,XXXXX___,
+ ___XX__X,X__XX___,
+ ___XXXXX,XXXXX___,
+ _______X,X_______,
+ __XXXXXX,XXXXXX__,
+ _______X,X_______,
+ _XXXXXXX,XXXXXXX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 主 code:0xD6F7 */
+static GUI_CONST_STORAGE unsigned char acD6F7[32] = {
+ ______XX,________,
+ _______X,X_______,
+ __XXXXXX,XXXXXX__,
+ _______X,X_______,
+ _______X,X_______,
+ _______X,X_______,
+ _______X,X_______,
+ ___XXXXX,XXXXX___,
+ _______X,X_______,
+ _______X,X_______,
+ _______X,X_______,
+ _______X,X_______,
+ _______X,X_______,
+ _XXXXXXX,XXXXXXX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 装 code:0xD7B0 */
+static GUI_CONST_STORAGE unsigned char acD7B0[32] = {
+ ____XX__,_XX_____,
+ _XX_XX__,_XX_____,
+ __XXXXXX,XXXXXXX_,
+ ____XX__,_XX_____,
+ ___XXX__,_XX_____,
+ _XXXXX_X,XXXXXX__,
+ ____XXXX,________,
+ _______X,X_______,
+ _XXXXXXX,XXXXXXX_,
+ _____XXX,X__XX___,
+ ____XXX_,XXXX____,
+ ___XXXX_,_XX_____,
+ _XXX_XXX,X_XXX___,
+ _____XXX,____XXX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 状 code:0xD7B4 */
+static GUI_CONST_STORAGE unsigned char acD7B4[32] = {
+ ____XX__,_XX_____,
+ ____XX__,_XXXX___,
+ _XX_XX__,_XX_XX__,
+ __XXXX__,_XX_____,
+ __XXXXXX,XXXXXXX_,
+ ____XX__,_XX_____,
+ ____XX__,_XX_____,
+ ___XXX__,XXXX____,
+ __XXXX__,XXXX____,
+ _XX_XX__,XXXX____,
+ ____XX_X,X__XX___,
+ ____XX_X,X__XX___,
+ ____XXXX,____XX__,
+ ____XXX_,_____XX_,
+ ________,________,
+ ________,________,
+};
+
+/* char: 准 code:0xD7BC */
+static GUI_CONST_STORAGE unsigned char acD7BC[32] = {
+ _______X,X_XX____,
+ __XX___X,X__XX___,
+ ___XX_XX,________,
+ ___XX_XX,XXXXXXX_,
+ _____XXX,__XX____,
+ ____XXXX,__XX____,
+ ______XX,XXXXXX__,
+ ___XX_XX,__XX____,
+ ___XX_XX,__XX____,
+ __XX__XX,XXXXXX__,
+ __XX__XX,__XX____,
+ _XX___XX,__XX____,
+ _XX___XX,XXXXXXX_,
+ ______XX,________,
+ ________,________,
+ ________,________,
+};
+
+/* char: 自 code:0xD7D4 */
+static GUI_CONST_STORAGE unsigned char acD7D4[32] = {
+ ______XX,________,
+ _____XX_,________,
+ __XXXXXX,XXXXXX__,
+ __XX____,____XX__,
+ __XX____,____XX__,
+ __XXXXXX,XXXXXX__,
+ __XX____,____XX__,
+ __XX____,____XX__,
+ __XXXXXX,XXXXXX__,
+ __XX____,____XX__,
+ __XX____,____XX__,
+ __XX____,____XX__,
+ __XXXXXX,XXXXXX__,
+ __XX____,____XX__,
+ ________,________,
+ ________,________,
+};
+
+/* char: 字 code:0xD7D6 */
+static GUI_CONST_STORAGE unsigned char acD7D6[32] = {
+ ______XX,________,
+ _______X,X_______,
+ _XXXXXXX,XXXXXXX_,
+ _XX_____,_____XX_,
+ _XX_____,_____XX_,
+ ___XXXXX,XXXX____,
+ ________,_XX_____,
+ ________,XX______,
+ _______X,X_______,
+ _XXXXXXX,XXXXXXX_,
+ _______X,X_______,
+ _______X,X_______,
+ _______X,X_______,
+ _____XXX,X_______,
+ ________,________,
+ ________,________,
+};
+
+/* char: 作 code:0xD7F7 */
+static GUI_CONST_STORAGE unsigned char acD7F7[32] = {
+ ____XX_X,X_______,
+ ____XX_X,X_______,
+ ____XX_X,XXXXXXX_,
+ ___XX_XX,XX______,
+ ___XX_XX,XX______,
+ __XXXXX_,XX______,
+ _XXXX___,XXXXXX__,
+ ___XX___,XX______,
+ ___XX___,XX______,
+ ___XX___,XX______,
+ ___XX___,XXXXXXX_,
+ ___XX___,XX______,
+ ___XX___,XX______,
+ ___XX___,XX______,
+ ________,________,
+ ________,________,
+};
+
+static GUI_CONST_STORAGE GUI_CHARINFO Cinfo[359] = {
+ { 6, 6, 2, (unsigned char *)&ac0020 }, /*0: */
+ { 5, 5, 2, (unsigned char *)&ac0021 }, /*1: !*/
+ { 7, 7, 2, (unsigned char *)&ac0022 }, /*2: "*/
+ { 8, 8, 2, (unsigned char *)&ac0023 }, /*3: #*/
+ { 8, 8, 2, (unsigned char *)&ac0024 }, /*4: $*/
+ { 8, 8, 2, (unsigned char *)&ac0025 }, /*5: %*/
+ { 9, 9, 2, (unsigned char *)&ac0026 }, /*6: &*/
+ { 4, 4, 2, (unsigned char *)&ac0027 }, /*7: '*/
+ { 8, 8, 2, (unsigned char *)&ac0028 }, /*8: (*/
+ { 5, 5, 2, (unsigned char *)&ac0029 }, /*9: )*/
+ { 8, 8, 2, (unsigned char *)&ac002A }, /*10: **/
+ { 9, 9, 2, (unsigned char *)&ac002B }, /*11: +*/
+ { 4, 4, 2, (unsigned char *)&ac002C }, /*12: ,*/
+ { 8, 8, 2, (unsigned char *)&ac002D }, /*13: -*/
+ { 4, 4, 2, (unsigned char *)&ac002E }, /*14: .*/
+ { 8, 8, 2, (unsigned char *)&ac002F }, /*15: /*/
+ { 8, 8, 2, (unsigned char *)&ac0030 }, /*16: 0*/
+ { 7, 7, 2, (unsigned char *)&ac0031 }, /*17: 1*/
+ { 8, 8, 2, (unsigned char *)&ac0032 }, /*18: 2*/
+ { 8, 8, 2, (unsigned char *)&ac0033 }, /*19: 3*/
+ { 9, 9, 2, (unsigned char *)&ac0034 }, /*20: 4*/
+ { 8, 8, 2, (unsigned char *)&ac0035 }, /*21: 5*/
+ { 8, 8, 2, (unsigned char *)&ac0036 }, /*22: 6*/
+ { 8, 8, 2, (unsigned char *)&ac0037 }, /*23: 7*/
+ { 8, 8, 2, (unsigned char *)&ac0038 }, /*24: 8*/
+ { 8, 8, 2, (unsigned char *)&ac0039 }, /*25: 9*/
+ { 6, 6, 2, (unsigned char *)&ac003A }, /*26: :*/
+ { 5, 5, 2, (unsigned char *)&ac003B }, /*27: ;*/
+ { 7, 7, 2, (unsigned char *)&ac003C }, /*28: <*/
+ { 8, 8, 2, (unsigned char *)&ac003D }, /*29: =*/
+ { 8, 8, 2, (unsigned char *)&ac003E }, /*30: >*/
+ { 8, 8, 2, (unsigned char *)&ac003F }, /*31: ?*/
+ { 8, 8, 2, (unsigned char *)&ac0040 }, /*32: @*/
+ { 8, 8, 2, (unsigned char *)&ac0041 }, /*33: A*/
+ { 8, 8, 2, (unsigned char *)&ac0042 }, /*34: B*/
+ { 8, 8, 2, (unsigned char *)&ac0043 }, /*35: C*/
+ { 8, 8, 2, (unsigned char *)&ac0044 }, /*36: D*/
+ { 8, 8, 2, (unsigned char *)&ac0045 }, /*37: E*/
+ { 8, 8, 2, (unsigned char *)&ac0046 }, /*38: F*/
+ { 8, 8, 2, (unsigned char *)&ac0047 }, /*39: G*/
+ { 8, 8, 2, (unsigned char *)&ac0048 }, /*40: H*/
+ { 7, 7, 2, (unsigned char *)&ac0049 }, /*41: I*/
+ { 8, 8, 2, (unsigned char *)&ac004A }, /*42: J*/
+ { 8, 8, 2, (unsigned char *)&ac004B }, /*43: K*/
+ { 8, 8, 2, (unsigned char *)&ac004C }, /*44: L*/
+ { 8, 8, 2, (unsigned char *)&ac004D }, /*45: M*/
+ { 8, 8, 2, (unsigned char *)&ac004E }, /*46: N*/
+ { 8, 8, 2, (unsigned char *)&ac004F }, /*47: O*/
+ { 8, 8, 2, (unsigned char *)&ac0050 }, /*48: P*/
+ { 8, 8, 2, (unsigned char *)&ac0051 }, /*49: Q*/
+ { 8, 8, 2, (unsigned char *)&ac0052 }, /*50: R*/
+ { 8, 8, 2, (unsigned char *)&ac0053 }, /*51: S*/
+ { 8, 8, 2, (unsigned char *)&ac0054 }, /*52: T*/
+ { 8, 8, 2, (unsigned char *)&ac0055 }, /*53: U*/
+ { 8, 8, 2, (unsigned char *)&ac0056 }, /*54: V*/
+ { 8, 8, 2, (unsigned char *)&ac0057 }, /*55: W*/
+ { 8, 8, 2, (unsigned char *)&ac0058 }, /*56: X*/
+ { 8, 8, 2, (unsigned char *)&ac0059 }, /*57: Y*/
+ { 8, 8, 2, (unsigned char *)&ac005A }, /*58: Z*/
+ { 7, 7, 2, (unsigned char *)&ac005B }, /*59: [*/
+ { 8, 8, 2, (unsigned char *)&ac005C }, /*60: \*/
+ { 6, 6, 2, (unsigned char *)&ac005D }, /*61: ]*/
+ { 7, 7, 2, (unsigned char *)&ac005E }, /*62: ^*/
+ { 8, 8, 2, (unsigned char *)&ac005F }, /*63: _*/
+ { 5, 5, 2, (unsigned char *)&ac0060 }, /*64: `*/
+ { 8, 8, 2, (unsigned char *)&ac0061 }, /*65: a*/
+ { 8, 8, 2, (unsigned char *)&ac0062 }, /*66: b*/
+ { 8, 8, 2, (unsigned char *)&ac0063 }, /*67: c*/
+ { 9, 9, 2, (unsigned char *)&ac0064 }, /*68: d*/
+ { 8, 8, 2, (unsigned char *)&ac0065 }, /*69: e*/
+ { 8, 8, 2, (unsigned char *)&ac0066 }, /*70: f*/
+ { 8, 8, 2, (unsigned char *)&ac0067 }, /*71: g*/
+ { 9, 9, 2, (unsigned char *)&ac0068 }, /*72: h*/
+ { 7, 7, 2, (unsigned char *)&ac0069 }, /*73: i*/
+ { 7, 7, 2, (unsigned char *)&ac006A }, /*74: j*/
+ { 8, 8, 2, (unsigned char *)&ac006B }, /*75: k*/
+ { 7, 7, 2, (unsigned char *)&ac006C }, /*76: l*/
+ { 8, 8, 2, (unsigned char *)&ac006D }, /*77: m*/
+ { 9, 9, 2, (unsigned char *)&ac006E }, /*78: n*/
+ { 8, 8, 2, (unsigned char *)&ac006F }, /*79: o*/
+ { 8, 8, 2, (unsigned char *)&ac0070 }, /*80: p*/
+ { 9, 9, 2, (unsigned char *)&ac0071 }, /*81: q*/
+ { 8, 8, 2, (unsigned char *)&ac0072 }, /*82: r*/
+ { 7, 7, 2, (unsigned char *)&ac0073 }, /*83: s*/
+ { 8, 8, 2, (unsigned char *)&ac0074 }, /*84: t*/
+ { 9, 9, 2, (unsigned char *)&ac0075 }, /*85: u*/
+ { 8, 8, 2, (unsigned char *)&ac0076 }, /*86: v*/
+ { 8, 8, 2, (unsigned char *)&ac0077 }, /*87: w*/
+ { 8, 8, 2, (unsigned char *)&ac0078 }, /*88: x*/
+ { 9, 9, 2, (unsigned char *)&ac0079 }, /*89: y*/
+ { 8, 8, 2, (unsigned char *)&ac007A }, /*90: z*/
+ { 8, 8, 2, (unsigned char *)&ac007B }, /*91: {*/
+ { 6, 6, 2, (unsigned char *)&ac007C }, /*92: |*/
+ { 5, 5, 2, (unsigned char *)&ac007D }, /*93: }*/
+ { 8, 8, 2, (unsigned char *)&ac007E }, /*94: ~*/
+ { 6, 6, 2, (unsigned char *)&ac007F }, /*95: */
+ { 15, 15, 2, (unsigned char *)&acA1AB }, /*96: ~*/
+ { 13, 13, 2, (unsigned char *)&acA1C1 }, /*97: ×*/
+ { 15, 15, 2, (unsigned char *)&acA1CC }, /*98: √*/
+ { 8, 8, 2, (unsigned char *)&acA1E3 }, /*99: °*/
+ { 15, 15, 2, (unsigned char *)&acA1E6 }, /*100: ℃*/
+ { 15, 15, 2, (unsigned char *)&acA1F0 }, /*101: ○*/
+ { 15, 15, 2, (unsigned char *)&acA1FA }, /*102: →*/
+ { 15, 15, 2, (unsigned char *)&acA1FB }, /*103: ←*/
+ { 11, 11, 2, (unsigned char *)&acA1FC }, /*104: ↑*/
+ { 11, 11, 2, (unsigned char *)&acA1FD }, /*105: ↓*/
+ { 14, 14, 2, (unsigned char *)&acA848 }, /*106: ℉*/
+ { 15, 15, 2, (unsigned char *)&acB0B2 }, /*107: 安*/
+ { 15, 15, 2, (unsigned char *)&acB0B4 }, /*108: 按*/
+ { 15, 15, 2, (unsigned char *)&acB0E6 }, /*109: 版*/
+ { 15, 15, 2, (unsigned char *)&acB1A1 }, /*110: 薄*/
+ { 15, 15, 2, (unsigned char *)&acB1A3 }, /*111: 保*/
+ { 15, 15, 2, (unsigned char *)&acB1A5 }, /*112: 饱*/
+ { 15, 15, 2, (unsigned char *)&acB1A8 }, /*113: 报*/
+ { 15, 15, 2, (unsigned char *)&acB1B8 }, /*114: 备*/
+ { 15, 15, 2, (unsigned char *)&acB1BE }, /*115: 本*/
+ { 15, 15, 2, (unsigned char *)&acB1C8 }, /*116: 比*/
+ { 15, 15, 2, (unsigned char *)&acB1D5 }, /*117: 闭*/
+ { 15, 15, 2, (unsigned char *)&acB1E0 }, /*118: 编*/
+ { 15, 15, 2, (unsigned char *)&acB1E4 }, /*119: 变*/
+ { 15, 15, 2, (unsigned char *)&acB1ED }, /*120: 表*/
+ { 15, 15, 2, (unsigned char *)&acB2BB }, /*121: 不*/
+ { 15, 15, 2, (unsigned char *)&acB2C1 }, /*122: 擦*/
+ { 15, 15, 2, (unsigned char *)&acB2CE }, /*123: 参*/
+ { 15, 15, 2, (unsigned char *)&acB2D9 }, /*124: 操*/
+ { 15, 15, 2, (unsigned char *)&acB2E2 }, /*125: 测*/
+ { 15, 15, 2, (unsigned char *)&acB2EE }, /*126: 差*/
+ { 15, 15, 2, (unsigned char *)&acB3A3 }, /*127: 常*/
+ { 15, 15, 2, (unsigned char *)&acB3A4 }, /*128: 长*/
+ { 15, 15, 2, (unsigned char *)&acB3A7 }, /*129: 厂*/
+ { 15, 15, 2, (unsigned char *)&acB3C6 }, /*130: 称*/
+ { 15, 15, 2, (unsigned char *)&acB3C9 }, /*131: 成*/
+ { 15, 15, 2, (unsigned char *)&acB3CC }, /*132: 程*/
+ { 15, 15, 2, (unsigned char *)&acB3F6 }, /*133: 出*/
+ { 15, 15, 2, (unsigned char *)&acB4A2 }, /*134: 储*/
+ { 15, 15, 2, (unsigned char *)&acB4AB }, /*135: 传*/
+ { 15, 15, 2, (unsigned char *)&acB4C5 }, /*136: 磁*/
+ { 15, 15, 2, (unsigned char *)&acB4CE }, /*137: 次*/
+ { 15, 15, 2, (unsigned char *)&acB4E6 }, /*138: 存*/
+ { 15, 15, 2, (unsigned char *)&acB4F3 }, /*139: 大*/
+ { 15, 15, 2, (unsigned char *)&acB4F8 }, /*140: 带*/
+ { 15, 15, 2, (unsigned char *)&acB4FD }, /*141: 待*/
+ { 15, 15, 2, (unsigned char *)&acB5A5 }, /*142: 单*/
+ { 15, 15, 2, (unsigned char *)&acB5AF }, /*143: 弹*/
+ { 14, 14, 2, (unsigned char *)&acB5B1 }, /*144: 当*/
+ { 15, 15, 2, (unsigned char *)&acB5C4 }, /*145: 的*/
+ { 15, 15, 2, (unsigned char *)&acB5CD }, /*146: 低*/
+ { 15, 15, 2, (unsigned char *)&acB5D8 }, /*147: 地*/
+ { 15, 15, 2, (unsigned char *)&acB5E3 }, /*148: 点*/
+ { 15, 15, 2, (unsigned char *)&acB5E7 }, /*149: 电*/
+ { 15, 15, 2, (unsigned char *)&acB6A8 }, /*150: 定*/
+ { 15, 15, 2, (unsigned char *)&acB6AF }, /*151: 动*/
+ { 15, 15, 2, (unsigned char *)&acB6C8 }, /*152: 度*/
+ { 15, 15, 2, (unsigned char *)&acB6CC }, /*153: 短*/
+ { 15, 15, 2, (unsigned char *)&acB6CF }, /*154: 断*/
+ { 15, 15, 2, (unsigned char *)&acB7A7 }, /*155: 阀*/
+ { 15, 15, 2, (unsigned char *)&acB7A8 }, /*156: 法*/
+ { 15, 15, 2, (unsigned char *)&acB7B4 }, /*157: 反*/
+ { 15, 15, 2, (unsigned char *)&acB7B5 }, /*158: 返*/
+ { 15, 15, 2, (unsigned char *)&acB7B6 }, /*159: 范*/
+ { 15, 15, 2, (unsigned char *)&acB7BD }, /*160: 方*/
+ { 15, 15, 2, (unsigned char *)&acB7C5 }, /*161: 放*/
+ { 15, 15, 2, (unsigned char *)&acB7C7 }, /*162: 非*/
+ { 15, 15, 2, (unsigned char *)&acB7D6 }, /*163: 分*/
+ { 15, 15, 2, (unsigned char *)&acB7FE }, /*164: 服*/
+ { 15, 15, 2, (unsigned char *)&acB8B4 }, /*165: 复*/
+ { 15, 15, 2, (unsigned char *)&acB8D0 }, /*166: 感*/
+ { 15, 15, 2, (unsigned char *)&acB8D7 }, /*167: 缸*/
+ { 15, 15, 2, (unsigned char *)&acB8DF }, /*168: 高*/
+ { 15, 15, 2, (unsigned char *)&acB8EE }, /*169: 割*/
+ { 15, 15, 2, (unsigned char *)&acB8F6 }, /*170: 个*/
+ { 15, 15, 2, (unsigned char *)&acB8FC }, /*171: 更*/
+ { 15, 15, 2, (unsigned char *)&acB9A4 }, /*172: 工*/
+ { 14, 14, 2, (unsigned char *)&acB9A6 }, /*173: 功*/
+ { 15, 15, 2, (unsigned char *)&acB9AB }, /*174: 公*/
+ { 15, 15, 2, (unsigned char *)&acB9B9 }, /*175: 构*/
+ { 15, 15, 2, (unsigned char *)&acB9CA }, /*176: 故*/
+ { 15, 15, 2, (unsigned char *)&acB9CC }, /*177: 固*/
+ { 15, 15, 2, (unsigned char *)&acB9D8 }, /*178: 关*/
+ { 15, 15, 2, (unsigned char *)&acB9FD }, /*179: 过*/
+ { 15, 15, 2, (unsigned char *)&acBAC4 }, /*180: 耗*/
+ { 15, 15, 2, (unsigned char *)&acBAC5 }, /*181: 号*/
+ { 15, 15, 2, (unsigned char *)&acBACD }, /*182: 和*/
+ { 15, 15, 2, (unsigned char *)&acBAE3 }, /*183: 恒*/
+ { 15, 15, 2, (unsigned char *)&acBBA4 }, /*184: 护*/
+ { 15, 15, 2, (unsigned char *)&acBBB6 }, /*185: 欢*/
+ { 15, 15, 2, (unsigned char *)&acBBB7 }, /*186: 环*/
+ { 15, 15, 2, (unsigned char *)&acBBBB }, /*187: 换*/
+ { 15, 15, 2, (unsigned char *)&acBBC9 }, /*188: 簧*/
+ { 15, 15, 2, (unsigned char *)&acBBD6 }, /*189: 恢*/
+ { 15, 15, 2, (unsigned char *)&acBBD8 }, /*190: 回*/
+ { 15, 15, 2, (unsigned char *)&acBBF9 }, /*191: 基*/
+ { 15, 15, 2, (unsigned char *)&acBBFA }, /*192: 机*/
+ { 15, 15, 2, (unsigned char *)&acBBFD }, /*193: 积*/
+ { 15, 15, 2, (unsigned char *)&acBCAD }, /*194: 辑*/
+ { 15, 15, 2, (unsigned char *)&acBCBC }, /*195: 技*/
+ { 15, 15, 2, (unsigned char *)&acBCC6 }, /*196: 计*/
+ { 15, 15, 2, (unsigned char *)&acBCC7 }, /*197: 记*/
+ { 15, 15, 2, (unsigned char *)&acBCD3 }, /*198: 加*/
+ { 15, 15, 2, (unsigned char *)&acBCE4 }, /*199: 间*/
+ { 15, 15, 2, (unsigned char *)&acBCF5 }, /*200: 减*/
+ { 15, 15, 2, (unsigned char *)&acBCFE }, /*201: 件*/
+ { 15, 15, 2, (unsigned char *)&acBDAD }, /*202: 江*/
+ { 14, 14, 2, (unsigned char *)&acBDC7 }, /*203: 角*/
+ { 15, 15, 2, (unsigned char *)&acBDF8 }, /*204: 进*/
+ { 15, 15, 2, (unsigned char *)&acBEA1 }, /*205: 尽*/
+ { 15, 15, 2, (unsigned char *)&acBEAF }, /*206: 警*/
+ { 15, 15, 2, (unsigned char *)&acBEB3 }, /*207: 境*/
+ { 15, 15, 2, (unsigned char *)&acBEDD }, /*208: 据*/
+ { 15, 15, 2, (unsigned char *)&acBEDE }, /*209: 巨*/
+ { 15, 15, 2, (unsigned char *)&acBFAA }, /*210: 开*/
+ { 15, 15, 2, (unsigned char *)&acBFC9 }, /*211: 可*/
+ { 15, 15, 2, (unsigned char *)&acBFD5 }, /*212: 空*/
+ { 15, 15, 2, (unsigned char *)&acBFD8 }, /*213: 控*/
+ { 15, 15, 2, (unsigned char *)&acBFE7 }, /*214: 跨*/
+ { 15, 15, 2, (unsigned char *)&acBFE9 }, /*215: 块*/
+ { 15, 15, 2, (unsigned char *)&acC0B6 }, /*216: 蓝*/
+ { 14, 14, 2, (unsigned char *)&acC0DB }, /*217: 累*/
+ { 15, 15, 2, (unsigned char *)&acC0E0 }, /*218: 类*/
+ { 15, 15, 2, (unsigned char *)&acC0EB }, /*219: 离*/
+ { 15, 15, 2, (unsigned char *)&acC0FD }, /*220: 例*/
+ { 14, 14, 2, (unsigned char *)&acC1A6 }, /*221: 力*/
+ { 15, 15, 2, (unsigned char *)&acC1BF }, /*222: 量*/
+ { 15, 15, 2, (unsigned char *)&acC1D0 }, /*223: 列*/
+ { 15, 15, 2, (unsigned char *)&acC1E3 }, /*224: 零*/
+ { 15, 15, 2, (unsigned char *)&acC1F7 }, /*225: 流*/
+ { 15, 15, 2, (unsigned char *)&acC2B7 }, /*226: 路*/
+ { 15, 15, 2, (unsigned char *)&acC2BC }, /*227: 录*/
+ { 15, 15, 2, (unsigned char *)&acC2CA }, /*228: 率*/
+ { 15, 15, 2, (unsigned char *)&acC2FA }, /*229: 满*/
+ { 15, 15, 2, (unsigned char *)&acC3C5 }, /*230: 门*/
+ { 15, 15, 2, (unsigned char *)&acC3E6 }, /*231: 面*/
+ { 14, 14, 2, (unsigned char *)&acC3FB }, /*232: 名*/
+ { 15, 15, 2, (unsigned char *)&acC4A3 }, /*233: 模*/
+ { 15, 15, 2, (unsigned char *)&acC4A4 }, /*234: 膜*/
+ { 15, 15, 2, (unsigned char *)&acC4A6 }, /*235: 摩*/
+ { 15, 15, 2, (unsigned char *)&acC4DA }, /*236: 内*/
+ { 15, 15, 2, (unsigned char *)&acC4DC }, /*237: 能*/
+ { 15, 15, 2, (unsigned char *)&acC4E2 }, /*238: 拟*/
+ { 15, 15, 2, (unsigned char *)&acC5E4 }, /*239: 配*/
+ { 14, 14, 2, (unsigned char *)&acC6AB }, /*240: 偏*/
+ { 15, 15, 2, (unsigned char *)&acC6B5 }, /*241: 频*/
+ { 15, 15, 2, (unsigned char *)&acC6BD }, /*242: 平*/
+ { 14, 14, 2, (unsigned char *)&acC6F4 }, /*243: 启*/
+ { 15, 15, 2, (unsigned char *)&acC6F7 }, /*244: 器*/
+ { 15, 15, 2, (unsigned char *)&acC6F8 }, /*245: 气*/
+ { 15, 15, 2, (unsigned char *)&acC7B0 }, /*246: 前*/
+ { 15, 15, 2, (unsigned char *)&acC7D0 }, /*247: 切*/
+ { 15, 15, 2, (unsigned char *)&acC7F8 }, /*248: 区*/
+ { 15, 15, 2, (unsigned char *)&acC7FD }, /*249: 驱*/
+ { 15, 15, 2, (unsigned char *)&acC8A1 }, /*250: 取*/
+ { 15, 15, 2, (unsigned char *)&acC8AB }, /*251: 全*/
+ { 15, 15, 2, (unsigned char *)&acC8B7 }, /*252: 确*/
+ { 15, 15, 2, (unsigned char *)&acC8CF }, /*253: 认*/
+ { 15, 15, 2, (unsigned char *)&acC8EB }, /*254: 入*/
+ { 15, 15, 2, (unsigned char *)&acC8ED }, /*255: 软*/
+ { 15, 15, 2, (unsigned char *)&acC9CC }, /*256: 商*/
+ { 15, 15, 2, (unsigned char *)&acC9CF }, /*257: 上*/
+ { 15, 15, 2, (unsigned char *)&acC9D9 }, /*258: 少*/
+ { 15, 15, 2, (unsigned char *)&acC9E8 }, /*259: 设*/
+ { 15, 15, 2, (unsigned char *)&acCAAA }, /*260: 湿*/
+ { 15, 15, 2, (unsigned char *)&acCAAF }, /*261: 石*/
+ { 15, 15, 2, (unsigned char *)&acCAB1 }, /*262: 时*/
+ { 15, 15, 2, (unsigned char *)&acCAB5 }, /*263: 实*/
+ { 15, 15, 2, (unsigned char *)&acCAB9 }, /*264: 使*/
+ { 15, 15, 2, (unsigned char *)&acCABD }, /*265: 式*/
+ { 15, 15, 2, (unsigned char *)&acCABE }, /*266: 示*/
+ { 15, 15, 2, (unsigned char *)&acCAD4 }, /*267: 试*/
+ { 15, 15, 2, (unsigned char *)&acCAD6 }, /*268: 手*/
+ { 15, 15, 2, (unsigned char *)&acCAD7 }, /*269: 首*/
+ { 15, 15, 2, (unsigned char *)&acCAE4 }, /*270: 输*/
+ { 15, 15, 2, (unsigned char *)&acCAF5 }, /*271: 术*/
+ { 15, 15, 2, (unsigned char *)&acCAFD }, /*272: 数*/
+ { 15, 15, 2, (unsigned char *)&acCBAB }, /*273: 双*/
+ { 14, 14, 2, (unsigned char *)&acCBBE }, /*274: 司*/
+ { 15, 15, 2, (unsigned char *)&acCBC0 }, /*275: 死*/
+ { 15, 15, 2, (unsigned char *)&acCBD5 }, /*276: 苏*/
+ { 15, 15, 2, (unsigned char *)&acCBD9 }, /*277: 速*/
+ { 15, 15, 2, (unsigned char *)&acCBE3 }, /*278: 算*/
+ { 15, 15, 2, (unsigned char *)&acCBF9 }, /*279: 所*/
+ { 15, 15, 2, (unsigned char *)&acCCAC }, /*280: 态*/
+ { 15, 15, 2, (unsigned char *)&acCCF5 }, /*281: 条*/
+ { 15, 15, 2, (unsigned char *)&acCDA3 }, /*282: 停*/
+ { 15, 15, 2, (unsigned char *)&acCDA8 }, /*283: 通*/
+ { 15, 15, 2, (unsigned char *)&acCDB6 }, /*284: 投*/
+ { 15, 15, 2, (unsigned char *)&acCDBC }, /*285: 图*/
+ { 15, 15, 2, (unsigned char *)&acCDE2 }, /*286: 外*/
+ { 15, 15, 2, (unsigned char *)&acCEA2 }, /*287: 微*/
+ { 15, 15, 2, (unsigned char *)&acCEA7 }, /*288: 围*/
+ { 14, 14, 2, (unsigned char *)&acCEAA }, /*289: 为*/
+ { 15, 15, 2, (unsigned char *)&acCEB4 }, /*290: 未*/
+ { 15, 15, 2, (unsigned char *)&acCEBB }, /*291: 位*/
+ { 15, 15, 2, (unsigned char *)&acCEC2 }, /*292: 温*/
+ { 15, 15, 2, (unsigned char *)&acCEC4 }, /*293: 文*/
+ { 15, 15, 2, (unsigned char *)&acCEF1 }, /*294: 务*/
+ { 15, 15, 2, (unsigned char *)&acCFA2 }, /*295: 息*/
+ { 14, 14, 2, (unsigned char *)&acCFB5 }, /*296: 系*/
+ { 15, 15, 2, (unsigned char *)&acCFC2 }, /*297: 下*/
+ { 15, 15, 2, (unsigned char *)&acCFD4 }, /*298: 显*/
+ { 15, 15, 2, (unsigned char *)&acCFDE }, /*299: 限*/
+ { 15, 15, 2, (unsigned char *)&acCFDF }, /*300: 线*/
+ { 15, 15, 2, (unsigned char *)&acCFE0 }, /*301: 相*/
+ { 15, 15, 2, (unsigned char *)&acCFEE }, /*302: 项*/
+ { 15, 15, 2, (unsigned char *)&acCFF2 }, /*303: 向*/
+ { 14, 14, 2, (unsigned char *)&acCFFB }, /*304: 消*/
+ { 15, 15, 2, (unsigned char *)&acD0A1 }, /*305: 小*/
+ { 15, 15, 2, (unsigned char *)&acD0A3 }, /*306: 校*/
+ { 15, 15, 2, (unsigned char *)&acD0B4 }, /*307: 写*/
+ { 15, 15, 2, (unsigned char *)&acD0C2 }, /*308: 新*/
+ { 15, 15, 2, (unsigned char *)&acD0C5 }, /*309: 信*/
+ { 15, 15, 2, (unsigned char *)&acD0CD }, /*310: 型*/
+ { 15, 15, 2, (unsigned char *)&acD0D0 }, /*311: 行*/
+ { 15, 15, 2, (unsigned char *)&acD0F2 }, /*312: 序*/
+ { 15, 15, 2, (unsigned char *)&acD1A1 }, /*313: 选*/
+ { 15, 15, 2, (unsigned char *)&acD1B6 }, /*314: 讯*/
+ { 15, 15, 2, (unsigned char *)&acD1B9 }, /*315: 压*/
+ { 15, 15, 2, (unsigned char *)&acD1C0 }, /*316: 牙*/
+ { 15, 15, 2, (unsigned char *)&acD1D4 }, /*317: 言*/
+ { 15, 15, 2, (unsigned char *)&acD2AA }, /*318: 要*/
+ { 15, 15, 2, (unsigned char *)&acD2B3 }, /*319: 页*/
+ { 15, 15, 2, (unsigned char *)&acD2BB }, /*320: 一*/
+ { 15, 15, 2, (unsigned char *)&acD2C6 }, /*321: 移*/
+ { 15, 15, 2, (unsigned char *)&acD2C7 }, /*322: 仪*/
+ { 15, 15, 2, (unsigned char *)&acD2D1 }, /*323: 已*/
+ { 15, 15, 2, (unsigned char *)&acD2E6 }, /*324: 益*/
+ { 15, 15, 2, (unsigned char *)&acD3A2 }, /*325: 英*/
+ { 15, 15, 2, (unsigned char *)&acD3AD }, /*326: 迎*/
+ { 15, 15, 2, (unsigned char *)&acD3B2 }, /*327: 硬*/
+ { 15, 15, 2, (unsigned char *)&acD3C3 }, /*328: 用*/
+ { 15, 15, 2, (unsigned char *)&acD3D0 }, /*329: 有*/
+ { 15, 15, 2, (unsigned char *)&acD3EF }, /*330: 语*/
+ { 15, 15, 2, (unsigned char *)&acD3F2 }, /*331: 域*/
+ { 15, 15, 2, (unsigned char *)&acD4B4 }, /*332: 源*/
+ { 15, 15, 2, (unsigned char *)&acD4CB }, /*333: 运*/
+ { 15, 15, 2, (unsigned char *)&acD4DA }, /*334: 在*/
+ { 15, 15, 2, (unsigned char *)&acD4EC }, /*335: 造*/
+ { 15, 15, 2, (unsigned char *)&acD4F1 }, /*336: 择*/
+ { 15, 15, 2, (unsigned char *)&acD4F6 }, /*337: 增*/
+ { 15, 15, 2, (unsigned char *)&acD5CF }, /*338: 障*/
+ { 15, 15, 2, (unsigned char *)&acD5EF }, /*339: 诊*/
+ { 15, 15, 2, (unsigned char *)&acD5FB }, /*340: 整*/
+ { 15, 15, 2, (unsigned char *)&acD5FD }, /*341: 正*/
+ { 15, 15, 2, (unsigned char *)&acD6AA }, /*342: 知*/
+ { 15, 15, 2, (unsigned char *)&acD6B1 }, /*343: 直*/
+ { 15, 15, 2, (unsigned char *)&acD6B4 }, /*344: 执*/
+ { 15, 15, 2, (unsigned char *)&acD6B7 }, /*345: 址*/
+ { 15, 15, 2, (unsigned char *)&acD6B8 }, /*346: 指*/
+ { 15, 15, 2, (unsigned char *)&acD6C3 }, /*347: 置*/
+ { 14, 14, 2, (unsigned char *)&acD6C6 }, /*348: 制*/
+ { 14, 14, 2, (unsigned char *)&acD6C7 }, /*349: 智*/
+ { 14, 14, 2, (unsigned char *)&acD6D0 }, /*350: 中*/
+ { 15, 15, 2, (unsigned char *)&acD6D8 }, /*351: 重*/
+ { 15, 15, 2, (unsigned char *)&acD6F7 }, /*352: 主*/
+ { 15, 15, 2, (unsigned char *)&acD7B0 }, /*353: 装*/
+ { 15, 15, 2, (unsigned char *)&acD7B4 }, /*354: 状*/
+ { 15, 15, 2, (unsigned char *)&acD7BC }, /*355: 准*/
+ { 14, 14, 2, (unsigned char *)&acD7D4 }, /*356: 自*/
+ { 15, 15, 2, (unsigned char *)&acD7D6 }, /*357: 字*/
+ { 15, 15, 2, (unsigned char *)&acD7F7 }, /*358: 作*/
+};
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop243 = {
+ 0xD7F7, /*start :作*/
+ 0xD7F7, /*end :作, len=1*/
+ &Cinfo[ 358 ],
+ (void*)0
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop242 = {
+ 0xD7D6, /*start :字*/
+ 0xD7D6, /*end :字, len=1*/
+ &Cinfo[ 357 ],
+ &Prop243
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop241 = {
+ 0xD7D4, /*start :自*/
+ 0xD7D4, /*end :自, len=1*/
+ &Cinfo[ 356 ],
+ &Prop242
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop240 = {
+ 0xD7BC, /*start :准*/
+ 0xD7BC, /*end :准, len=1*/
+ &Cinfo[ 355 ],
+ &Prop241
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop239 = {
+ 0xD7B4, /*start :状*/
+ 0xD7B4, /*end :状, len=1*/
+ &Cinfo[ 354 ],
+ &Prop240
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop238 = {
+ 0xD7B0, /*start :装*/
+ 0xD7B0, /*end :装, len=1*/
+ &Cinfo[ 353 ],
+ &Prop239
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop237 = {
+ 0xD6F7, /*start :主*/
+ 0xD6F7, /*end :主, len=1*/
+ &Cinfo[ 352 ],
+ &Prop238
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop236 = {
+ 0xD6D8, /*start :重*/
+ 0xD6D8, /*end :重, len=1*/
+ &Cinfo[ 351 ],
+ &Prop237
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop235 = {
+ 0xD6D0, /*start :中*/
+ 0xD6D0, /*end :中, len=1*/
+ &Cinfo[ 350 ],
+ &Prop236
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop234 = {
+ 0xD6C6, /*start :制*/
+ 0xD6C7, /*end :智, len=2*/
+ &Cinfo[ 348 ],
+ &Prop235
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop233 = {
+ 0xD6C3, /*start :置*/
+ 0xD6C3, /*end :置, len=1*/
+ &Cinfo[ 347 ],
+ &Prop234
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop232 = {
+ 0xD6B7, /*start :址*/
+ 0xD6B8, /*end :指, len=2*/
+ &Cinfo[ 345 ],
+ &Prop233
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop231 = {
+ 0xD6B4, /*start :执*/
+ 0xD6B4, /*end :执, len=1*/
+ &Cinfo[ 344 ],
+ &Prop232
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop230 = {
+ 0xD6B1, /*start :直*/
+ 0xD6B1, /*end :直, len=1*/
+ &Cinfo[ 343 ],
+ &Prop231
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop229 = {
+ 0xD6AA, /*start :知*/
+ 0xD6AA, /*end :知, len=1*/
+ &Cinfo[ 342 ],
+ &Prop230
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop228 = {
+ 0xD5FD, /*start :正*/
+ 0xD5FD, /*end :正, len=1*/
+ &Cinfo[ 341 ],
+ &Prop229
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop227 = {
+ 0xD5FB, /*start :整*/
+ 0xD5FB, /*end :整, len=1*/
+ &Cinfo[ 340 ],
+ &Prop228
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop226 = {
+ 0xD5EF, /*start :诊*/
+ 0xD5EF, /*end :诊, len=1*/
+ &Cinfo[ 339 ],
+ &Prop227
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop225 = {
+ 0xD5CF, /*start :障*/
+ 0xD5CF, /*end :障, len=1*/
+ &Cinfo[ 338 ],
+ &Prop226
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop224 = {
+ 0xD4F6, /*start :增*/
+ 0xD4F6, /*end :增, len=1*/
+ &Cinfo[ 337 ],
+ &Prop225
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop223 = {
+ 0xD4F1, /*start :择*/
+ 0xD4F1, /*end :择, len=1*/
+ &Cinfo[ 336 ],
+ &Prop224
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop222 = {
+ 0xD4EC, /*start :造*/
+ 0xD4EC, /*end :造, len=1*/
+ &Cinfo[ 335 ],
+ &Prop223
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop221 = {
+ 0xD4DA, /*start :在*/
+ 0xD4DA, /*end :在, len=1*/
+ &Cinfo[ 334 ],
+ &Prop222
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop220 = {
+ 0xD4CB, /*start :运*/
+ 0xD4CB, /*end :运, len=1*/
+ &Cinfo[ 333 ],
+ &Prop221
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop219 = {
+ 0xD4B4, /*start :源*/
+ 0xD4B4, /*end :源, len=1*/
+ &Cinfo[ 332 ],
+ &Prop220
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop218 = {
+ 0xD3F2, /*start :域*/
+ 0xD3F2, /*end :域, len=1*/
+ &Cinfo[ 331 ],
+ &Prop219
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop217 = {
+ 0xD3EF, /*start :语*/
+ 0xD3EF, /*end :语, len=1*/
+ &Cinfo[ 330 ],
+ &Prop218
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop216 = {
+ 0xD3D0, /*start :有*/
+ 0xD3D0, /*end :有, len=1*/
+ &Cinfo[ 329 ],
+ &Prop217
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop215 = {
+ 0xD3C3, /*start :用*/
+ 0xD3C3, /*end :用, len=1*/
+ &Cinfo[ 328 ],
+ &Prop216
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop214 = {
+ 0xD3B2, /*start :硬*/
+ 0xD3B2, /*end :硬, len=1*/
+ &Cinfo[ 327 ],
+ &Prop215
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop213 = {
+ 0xD3AD, /*start :迎*/
+ 0xD3AD, /*end :迎, len=1*/
+ &Cinfo[ 326 ],
+ &Prop214
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop212 = {
+ 0xD3A2, /*start :英*/
+ 0xD3A2, /*end :英, len=1*/
+ &Cinfo[ 325 ],
+ &Prop213
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop211 = {
+ 0xD2E6, /*start :益*/
+ 0xD2E6, /*end :益, len=1*/
+ &Cinfo[ 324 ],
+ &Prop212
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop210 = {
+ 0xD2D1, /*start :已*/
+ 0xD2D1, /*end :已, len=1*/
+ &Cinfo[ 323 ],
+ &Prop211
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop209 = {
+ 0xD2C6, /*start :移*/
+ 0xD2C7, /*end :仪, len=2*/
+ &Cinfo[ 321 ],
+ &Prop210
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop208 = {
+ 0xD2BB, /*start :一*/
+ 0xD2BB, /*end :一, len=1*/
+ &Cinfo[ 320 ],
+ &Prop209
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop207 = {
+ 0xD2B3, /*start :页*/
+ 0xD2B3, /*end :页, len=1*/
+ &Cinfo[ 319 ],
+ &Prop208
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop206 = {
+ 0xD2AA, /*start :要*/
+ 0xD2AA, /*end :要, len=1*/
+ &Cinfo[ 318 ],
+ &Prop207
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop205 = {
+ 0xD1D4, /*start :言*/
+ 0xD1D4, /*end :言, len=1*/
+ &Cinfo[ 317 ],
+ &Prop206
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop204 = {
+ 0xD1C0, /*start :牙*/
+ 0xD1C0, /*end :牙, len=1*/
+ &Cinfo[ 316 ],
+ &Prop205
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop203 = {
+ 0xD1B9, /*start :压*/
+ 0xD1B9, /*end :压, len=1*/
+ &Cinfo[ 315 ],
+ &Prop204
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop202 = {
+ 0xD1B6, /*start :讯*/
+ 0xD1B6, /*end :讯, len=1*/
+ &Cinfo[ 314 ],
+ &Prop203
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop201 = {
+ 0xD1A1, /*start :选*/
+ 0xD1A1, /*end :选, len=1*/
+ &Cinfo[ 313 ],
+ &Prop202
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop200 = {
+ 0xD0F2, /*start :序*/
+ 0xD0F2, /*end :序, len=1*/
+ &Cinfo[ 312 ],
+ &Prop201
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop199 = {
+ 0xD0D0, /*start :行*/
+ 0xD0D0, /*end :行, len=1*/
+ &Cinfo[ 311 ],
+ &Prop200
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop198 = {
+ 0xD0CD, /*start :型*/
+ 0xD0CD, /*end :型, len=1*/
+ &Cinfo[ 310 ],
+ &Prop199
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop197 = {
+ 0xD0C5, /*start :信*/
+ 0xD0C5, /*end :信, len=1*/
+ &Cinfo[ 309 ],
+ &Prop198
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop196 = {
+ 0xD0C2, /*start :新*/
+ 0xD0C2, /*end :新, len=1*/
+ &Cinfo[ 308 ],
+ &Prop197
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop195 = {
+ 0xD0B4, /*start :写*/
+ 0xD0B4, /*end :写, len=1*/
+ &Cinfo[ 307 ],
+ &Prop196
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop194 = {
+ 0xD0A3, /*start :校*/
+ 0xD0A3, /*end :校, len=1*/
+ &Cinfo[ 306 ],
+ &Prop195
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop193 = {
+ 0xD0A1, /*start :小*/
+ 0xD0A1, /*end :小, len=1*/
+ &Cinfo[ 305 ],
+ &Prop194
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop192 = {
+ 0xCFFB, /*start :消*/
+ 0xCFFB, /*end :消, len=1*/
+ &Cinfo[ 304 ],
+ &Prop193
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop191 = {
+ 0xCFF2, /*start :向*/
+ 0xCFF2, /*end :向, len=1*/
+ &Cinfo[ 303 ],
+ &Prop192
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop190 = {
+ 0xCFEE, /*start :项*/
+ 0xCFEE, /*end :项, len=1*/
+ &Cinfo[ 302 ],
+ &Prop191
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop189 = {
+ 0xCFDE, /*start :限*/
+ 0xCFE0, /*end :相, len=3*/
+ &Cinfo[ 299 ],
+ &Prop190
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop188 = {
+ 0xCFD4, /*start :显*/
+ 0xCFD4, /*end :显, len=1*/
+ &Cinfo[ 298 ],
+ &Prop189
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop187 = {
+ 0xCFC2, /*start :下*/
+ 0xCFC2, /*end :下, len=1*/
+ &Cinfo[ 297 ],
+ &Prop188
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop186 = {
+ 0xCFB5, /*start :系*/
+ 0xCFB5, /*end :系, len=1*/
+ &Cinfo[ 296 ],
+ &Prop187
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop185 = {
+ 0xCFA2, /*start :息*/
+ 0xCFA2, /*end :息, len=1*/
+ &Cinfo[ 295 ],
+ &Prop186
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop184 = {
+ 0xCEF1, /*start :务*/
+ 0xCEF1, /*end :务, len=1*/
+ &Cinfo[ 294 ],
+ &Prop185
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop183 = {
+ 0xCEC4, /*start :文*/
+ 0xCEC4, /*end :文, len=1*/
+ &Cinfo[ 293 ],
+ &Prop184
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop182 = {
+ 0xCEC2, /*start :温*/
+ 0xCEC2, /*end :温, len=1*/
+ &Cinfo[ 292 ],
+ &Prop183
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop181 = {
+ 0xCEBB, /*start :位*/
+ 0xCEBB, /*end :位, len=1*/
+ &Cinfo[ 291 ],
+ &Prop182
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop180 = {
+ 0xCEB4, /*start :未*/
+ 0xCEB4, /*end :未, len=1*/
+ &Cinfo[ 290 ],
+ &Prop181
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop179 = {
+ 0xCEAA, /*start :为*/
+ 0xCEAA, /*end :为, len=1*/
+ &Cinfo[ 289 ],
+ &Prop180
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop178 = {
+ 0xCEA7, /*start :围*/
+ 0xCEA7, /*end :围, len=1*/
+ &Cinfo[ 288 ],
+ &Prop179
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop177 = {
+ 0xCEA2, /*start :微*/
+ 0xCEA2, /*end :微, len=1*/
+ &Cinfo[ 287 ],
+ &Prop178
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop176 = {
+ 0xCDE2, /*start :外*/
+ 0xCDE2, /*end :外, len=1*/
+ &Cinfo[ 286 ],
+ &Prop177
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop175 = {
+ 0xCDBC, /*start :图*/
+ 0xCDBC, /*end :图, len=1*/
+ &Cinfo[ 285 ],
+ &Prop176
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop174 = {
+ 0xCDB6, /*start :投*/
+ 0xCDB6, /*end :投, len=1*/
+ &Cinfo[ 284 ],
+ &Prop175
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop173 = {
+ 0xCDA8, /*start :通*/
+ 0xCDA8, /*end :通, len=1*/
+ &Cinfo[ 283 ],
+ &Prop174
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop172 = {
+ 0xCDA3, /*start :停*/
+ 0xCDA3, /*end :停, len=1*/
+ &Cinfo[ 282 ],
+ &Prop173
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop171 = {
+ 0xCCF5, /*start :条*/
+ 0xCCF5, /*end :条, len=1*/
+ &Cinfo[ 281 ],
+ &Prop172
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop170 = {
+ 0xCCAC, /*start :态*/
+ 0xCCAC, /*end :态, len=1*/
+ &Cinfo[ 280 ],
+ &Prop171
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop169 = {
+ 0xCBF9, /*start :所*/
+ 0xCBF9, /*end :所, len=1*/
+ &Cinfo[ 279 ],
+ &Prop170
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop168 = {
+ 0xCBE3, /*start :算*/
+ 0xCBE3, /*end :算, len=1*/
+ &Cinfo[ 278 ],
+ &Prop169
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop167 = {
+ 0xCBD9, /*start :速*/
+ 0xCBD9, /*end :速, len=1*/
+ &Cinfo[ 277 ],
+ &Prop168
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop166 = {
+ 0xCBD5, /*start :苏*/
+ 0xCBD5, /*end :苏, len=1*/
+ &Cinfo[ 276 ],
+ &Prop167
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop165 = {
+ 0xCBC0, /*start :死*/
+ 0xCBC0, /*end :死, len=1*/
+ &Cinfo[ 275 ],
+ &Prop166
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop164 = {
+ 0xCBBE, /*start :司*/
+ 0xCBBE, /*end :司, len=1*/
+ &Cinfo[ 274 ],
+ &Prop165
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop163 = {
+ 0xCBAB, /*start :双*/
+ 0xCBAB, /*end :双, len=1*/
+ &Cinfo[ 273 ],
+ &Prop164
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop162 = {
+ 0xCAFD, /*start :数*/
+ 0xCAFD, /*end :数, len=1*/
+ &Cinfo[ 272 ],
+ &Prop163
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop161 = {
+ 0xCAF5, /*start :术*/
+ 0xCAF5, /*end :术, len=1*/
+ &Cinfo[ 271 ],
+ &Prop162
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop160 = {
+ 0xCAE4, /*start :输*/
+ 0xCAE4, /*end :输, len=1*/
+ &Cinfo[ 270 ],
+ &Prop161
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop159 = {
+ 0xCAD6, /*start :手*/
+ 0xCAD7, /*end :首, len=2*/
+ &Cinfo[ 268 ],
+ &Prop160
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop158 = {
+ 0xCAD4, /*start :试*/
+ 0xCAD4, /*end :试, len=1*/
+ &Cinfo[ 267 ],
+ &Prop159
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop157 = {
+ 0xCABD, /*start :式*/
+ 0xCABE, /*end :示, len=2*/
+ &Cinfo[ 265 ],
+ &Prop158
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop156 = {
+ 0xCAB9, /*start :使*/
+ 0xCAB9, /*end :使, len=1*/
+ &Cinfo[ 264 ],
+ &Prop157
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop155 = {
+ 0xCAB5, /*start :实*/
+ 0xCAB5, /*end :实, len=1*/
+ &Cinfo[ 263 ],
+ &Prop156
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop154 = {
+ 0xCAB1, /*start :时*/
+ 0xCAB1, /*end :时, len=1*/
+ &Cinfo[ 262 ],
+ &Prop155
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop153 = {
+ 0xCAAF, /*start :石*/
+ 0xCAAF, /*end :石, len=1*/
+ &Cinfo[ 261 ],
+ &Prop154
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop152 = {
+ 0xCAAA, /*start :湿*/
+ 0xCAAA, /*end :湿, len=1*/
+ &Cinfo[ 260 ],
+ &Prop153
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop151 = {
+ 0xC9E8, /*start :设*/
+ 0xC9E8, /*end :设, len=1*/
+ &Cinfo[ 259 ],
+ &Prop152
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop150 = {
+ 0xC9D9, /*start :少*/
+ 0xC9D9, /*end :少, len=1*/
+ &Cinfo[ 258 ],
+ &Prop151
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop149 = {
+ 0xC9CF, /*start :上*/
+ 0xC9CF, /*end :上, len=1*/
+ &Cinfo[ 257 ],
+ &Prop150
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop148 = {
+ 0xC9CC, /*start :商*/
+ 0xC9CC, /*end :商, len=1*/
+ &Cinfo[ 256 ],
+ &Prop149
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop147 = {
+ 0xC8ED, /*start :软*/
+ 0xC8ED, /*end :软, len=1*/
+ &Cinfo[ 255 ],
+ &Prop148
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop146 = {
+ 0xC8EB, /*start :入*/
+ 0xC8EB, /*end :入, len=1*/
+ &Cinfo[ 254 ],
+ &Prop147
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop145 = {
+ 0xC8CF, /*start :认*/
+ 0xC8CF, /*end :认, len=1*/
+ &Cinfo[ 253 ],
+ &Prop146
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop144 = {
+ 0xC8B7, /*start :确*/
+ 0xC8B7, /*end :确, len=1*/
+ &Cinfo[ 252 ],
+ &Prop145
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop143 = {
+ 0xC8AB, /*start :全*/
+ 0xC8AB, /*end :全, len=1*/
+ &Cinfo[ 251 ],
+ &Prop144
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop142 = {
+ 0xC8A1, /*start :取*/
+ 0xC8A1, /*end :取, len=1*/
+ &Cinfo[ 250 ],
+ &Prop143
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop141 = {
+ 0xC7FD, /*start :驱*/
+ 0xC7FD, /*end :驱, len=1*/
+ &Cinfo[ 249 ],
+ &Prop142
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop140 = {
+ 0xC7F8, /*start :区*/
+ 0xC7F8, /*end :区, len=1*/
+ &Cinfo[ 248 ],
+ &Prop141
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop139 = {
+ 0xC7D0, /*start :切*/
+ 0xC7D0, /*end :切, len=1*/
+ &Cinfo[ 247 ],
+ &Prop140
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop138 = {
+ 0xC7B0, /*start :前*/
+ 0xC7B0, /*end :前, len=1*/
+ &Cinfo[ 246 ],
+ &Prop139
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop137 = {
+ 0xC6F7, /*start :器*/
+ 0xC6F8, /*end :气, len=2*/
+ &Cinfo[ 244 ],
+ &Prop138
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop136 = {
+ 0xC6F4, /*start :启*/
+ 0xC6F4, /*end :启, len=1*/
+ &Cinfo[ 243 ],
+ &Prop137
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop135 = {
+ 0xC6BD, /*start :平*/
+ 0xC6BD, /*end :平, len=1*/
+ &Cinfo[ 242 ],
+ &Prop136
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop134 = {
+ 0xC6B5, /*start :频*/
+ 0xC6B5, /*end :频, len=1*/
+ &Cinfo[ 241 ],
+ &Prop135
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop133 = {
+ 0xC6AB, /*start :偏*/
+ 0xC6AB, /*end :偏, len=1*/
+ &Cinfo[ 240 ],
+ &Prop134
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop132 = {
+ 0xC5E4, /*start :配*/
+ 0xC5E4, /*end :配, len=1*/
+ &Cinfo[ 239 ],
+ &Prop133
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop131 = {
+ 0xC4E2, /*start :拟*/
+ 0xC4E2, /*end :拟, len=1*/
+ &Cinfo[ 238 ],
+ &Prop132
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop130 = {
+ 0xC4DC, /*start :能*/
+ 0xC4DC, /*end :能, len=1*/
+ &Cinfo[ 237 ],
+ &Prop131
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop129 = {
+ 0xC4DA, /*start :内*/
+ 0xC4DA, /*end :内, len=1*/
+ &Cinfo[ 236 ],
+ &Prop130
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop128 = {
+ 0xC4A6, /*start :摩*/
+ 0xC4A6, /*end :摩, len=1*/
+ &Cinfo[ 235 ],
+ &Prop129
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop127 = {
+ 0xC4A3, /*start :模*/
+ 0xC4A4, /*end :膜, len=2*/
+ &Cinfo[ 233 ],
+ &Prop128
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop126 = {
+ 0xC3FB, /*start :名*/
+ 0xC3FB, /*end :名, len=1*/
+ &Cinfo[ 232 ],
+ &Prop127
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop125 = {
+ 0xC3E6, /*start :面*/
+ 0xC3E6, /*end :面, len=1*/
+ &Cinfo[ 231 ],
+ &Prop126
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop124 = {
+ 0xC3C5, /*start :门*/
+ 0xC3C5, /*end :门, len=1*/
+ &Cinfo[ 230 ],
+ &Prop125
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop123 = {
+ 0xC2FA, /*start :满*/
+ 0xC2FA, /*end :满, len=1*/
+ &Cinfo[ 229 ],
+ &Prop124
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop122 = {
+ 0xC2CA, /*start :率*/
+ 0xC2CA, /*end :率, len=1*/
+ &Cinfo[ 228 ],
+ &Prop123
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop121 = {
+ 0xC2BC, /*start :录*/
+ 0xC2BC, /*end :录, len=1*/
+ &Cinfo[ 227 ],
+ &Prop122
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop120 = {
+ 0xC2B7, /*start :路*/
+ 0xC2B7, /*end :路, len=1*/
+ &Cinfo[ 226 ],
+ &Prop121
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop119 = {
+ 0xC1F7, /*start :流*/
+ 0xC1F7, /*end :流, len=1*/
+ &Cinfo[ 225 ],
+ &Prop120
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop118 = {
+ 0xC1E3, /*start :零*/
+ 0xC1E3, /*end :零, len=1*/
+ &Cinfo[ 224 ],
+ &Prop119
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop117 = {
+ 0xC1D0, /*start :列*/
+ 0xC1D0, /*end :列, len=1*/
+ &Cinfo[ 223 ],
+ &Prop118
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop116 = {
+ 0xC1BF, /*start :量*/
+ 0xC1BF, /*end :量, len=1*/
+ &Cinfo[ 222 ],
+ &Prop117
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop115 = {
+ 0xC1A6, /*start :力*/
+ 0xC1A6, /*end :力, len=1*/
+ &Cinfo[ 221 ],
+ &Prop116
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop114 = {
+ 0xC0FD, /*start :例*/
+ 0xC0FD, /*end :例, len=1*/
+ &Cinfo[ 220 ],
+ &Prop115
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop113 = {
+ 0xC0EB, /*start :离*/
+ 0xC0EB, /*end :离, len=1*/
+ &Cinfo[ 219 ],
+ &Prop114
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop112 = {
+ 0xC0E0, /*start :类*/
+ 0xC0E0, /*end :类, len=1*/
+ &Cinfo[ 218 ],
+ &Prop113
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop111 = {
+ 0xC0DB, /*start :累*/
+ 0xC0DB, /*end :累, len=1*/
+ &Cinfo[ 217 ],
+ &Prop112
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop110 = {
+ 0xC0B6, /*start :蓝*/
+ 0xC0B6, /*end :蓝, len=1*/
+ &Cinfo[ 216 ],
+ &Prop111
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop109 = {
+ 0xBFE9, /*start :块*/
+ 0xBFE9, /*end :块, len=1*/
+ &Cinfo[ 215 ],
+ &Prop110
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop108 = {
+ 0xBFE7, /*start :跨*/
+ 0xBFE7, /*end :跨, len=1*/
+ &Cinfo[ 214 ],
+ &Prop109
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop107 = {
+ 0xBFD8, /*start :控*/
+ 0xBFD8, /*end :控, len=1*/
+ &Cinfo[ 213 ],
+ &Prop108
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop106 = {
+ 0xBFD5, /*start :空*/
+ 0xBFD5, /*end :空, len=1*/
+ &Cinfo[ 212 ],
+ &Prop107
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop105 = {
+ 0xBFC9, /*start :可*/
+ 0xBFC9, /*end :可, len=1*/
+ &Cinfo[ 211 ],
+ &Prop106
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop104 = {
+ 0xBFAA, /*start :开*/
+ 0xBFAA, /*end :开, len=1*/
+ &Cinfo[ 210 ],
+ &Prop105
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop103 = {
+ 0xBEDD, /*start :据*/
+ 0xBEDE, /*end :巨, len=2*/
+ &Cinfo[ 208 ],
+ &Prop104
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop102 = {
+ 0xBEB3, /*start :境*/
+ 0xBEB3, /*end :境, len=1*/
+ &Cinfo[ 207 ],
+ &Prop103
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop101 = {
+ 0xBEAF, /*start :警*/
+ 0xBEAF, /*end :警, len=1*/
+ &Cinfo[ 206 ],
+ &Prop102
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop100 = {
+ 0xBEA1, /*start :尽*/
+ 0xBEA1, /*end :尽, len=1*/
+ &Cinfo[ 205 ],
+ &Prop101
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop99 = {
+ 0xBDF8, /*start :进*/
+ 0xBDF8, /*end :进, len=1*/
+ &Cinfo[ 204 ],
+ &Prop100
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop98 = {
+ 0xBDC7, /*start :角*/
+ 0xBDC7, /*end :角, len=1*/
+ &Cinfo[ 203 ],
+ &Prop99
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop97 = {
+ 0xBDAD, /*start :江*/
+ 0xBDAD, /*end :江, len=1*/
+ &Cinfo[ 202 ],
+ &Prop98
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop96 = {
+ 0xBCFE, /*start :件*/
+ 0xBCFE, /*end :件, len=1*/
+ &Cinfo[ 201 ],
+ &Prop97
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop95 = {
+ 0xBCF5, /*start :减*/
+ 0xBCF5, /*end :减, len=1*/
+ &Cinfo[ 200 ],
+ &Prop96
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop94 = {
+ 0xBCE4, /*start :间*/
+ 0xBCE4, /*end :间, len=1*/
+ &Cinfo[ 199 ],
+ &Prop95
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop93 = {
+ 0xBCD3, /*start :加*/
+ 0xBCD3, /*end :加, len=1*/
+ &Cinfo[ 198 ],
+ &Prop94
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop92 = {
+ 0xBCC6, /*start :计*/
+ 0xBCC7, /*end :记, len=2*/
+ &Cinfo[ 196 ],
+ &Prop93
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop91 = {
+ 0xBCBC, /*start :技*/
+ 0xBCBC, /*end :技, len=1*/
+ &Cinfo[ 195 ],
+ &Prop92
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop90 = {
+ 0xBCAD, /*start :辑*/
+ 0xBCAD, /*end :辑, len=1*/
+ &Cinfo[ 194 ],
+ &Prop91
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop89 = {
+ 0xBBFD, /*start :积*/
+ 0xBBFD, /*end :积, len=1*/
+ &Cinfo[ 193 ],
+ &Prop90
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop88 = {
+ 0xBBF9, /*start :基*/
+ 0xBBFA, /*end :机, len=2*/
+ &Cinfo[ 191 ],
+ &Prop89
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop87 = {
+ 0xBBD8, /*start :回*/
+ 0xBBD8, /*end :回, len=1*/
+ &Cinfo[ 190 ],
+ &Prop88
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop86 = {
+ 0xBBD6, /*start :恢*/
+ 0xBBD6, /*end :恢, len=1*/
+ &Cinfo[ 189 ],
+ &Prop87
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop85 = {
+ 0xBBC9, /*start :簧*/
+ 0xBBC9, /*end :簧, len=1*/
+ &Cinfo[ 188 ],
+ &Prop86
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop84 = {
+ 0xBBBB, /*start :换*/
+ 0xBBBB, /*end :换, len=1*/
+ &Cinfo[ 187 ],
+ &Prop85
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop83 = {
+ 0xBBB6, /*start :欢*/
+ 0xBBB7, /*end :环, len=2*/
+ &Cinfo[ 185 ],
+ &Prop84
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop82 = {
+ 0xBBA4, /*start :护*/
+ 0xBBA4, /*end :护, len=1*/
+ &Cinfo[ 184 ],
+ &Prop83
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop81 = {
+ 0xBAE3, /*start :恒*/
+ 0xBAE3, /*end :恒, len=1*/
+ &Cinfo[ 183 ],
+ &Prop82
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop80 = {
+ 0xBACD, /*start :和*/
+ 0xBACD, /*end :和, len=1*/
+ &Cinfo[ 182 ],
+ &Prop81
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop79 = {
+ 0xBAC4, /*start :耗*/
+ 0xBAC5, /*end :号, len=2*/
+ &Cinfo[ 180 ],
+ &Prop80
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop78 = {
+ 0xB9FD, /*start :过*/
+ 0xB9FD, /*end :过, len=1*/
+ &Cinfo[ 179 ],
+ &Prop79
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop77 = {
+ 0xB9D8, /*start :关*/
+ 0xB9D8, /*end :关, len=1*/
+ &Cinfo[ 178 ],
+ &Prop78
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop76 = {
+ 0xB9CC, /*start :固*/
+ 0xB9CC, /*end :固, len=1*/
+ &Cinfo[ 177 ],
+ &Prop77
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop75 = {
+ 0xB9CA, /*start :故*/
+ 0xB9CA, /*end :故, len=1*/
+ &Cinfo[ 176 ],
+ &Prop76
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop74 = {
+ 0xB9B9, /*start :构*/
+ 0xB9B9, /*end :构, len=1*/
+ &Cinfo[ 175 ],
+ &Prop75
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop73 = {
+ 0xB9AB, /*start :公*/
+ 0xB9AB, /*end :公, len=1*/
+ &Cinfo[ 174 ],
+ &Prop74
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop72 = {
+ 0xB9A6, /*start :功*/
+ 0xB9A6, /*end :功, len=1*/
+ &Cinfo[ 173 ],
+ &Prop73
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop71 = {
+ 0xB9A4, /*start :工*/
+ 0xB9A4, /*end :工, len=1*/
+ &Cinfo[ 172 ],
+ &Prop72
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop70 = {
+ 0xB8FC, /*start :更*/
+ 0xB8FC, /*end :更, len=1*/
+ &Cinfo[ 171 ],
+ &Prop71
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop69 = {
+ 0xB8F6, /*start :个*/
+ 0xB8F6, /*end :个, len=1*/
+ &Cinfo[ 170 ],
+ &Prop70
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop68 = {
+ 0xB8EE, /*start :割*/
+ 0xB8EE, /*end :割, len=1*/
+ &Cinfo[ 169 ],
+ &Prop69
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop67 = {
+ 0xB8DF, /*start :高*/
+ 0xB8DF, /*end :高, len=1*/
+ &Cinfo[ 168 ],
+ &Prop68
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop66 = {
+ 0xB8D7, /*start :缸*/
+ 0xB8D7, /*end :缸, len=1*/
+ &Cinfo[ 167 ],
+ &Prop67
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop65 = {
+ 0xB8D0, /*start :感*/
+ 0xB8D0, /*end :感, len=1*/
+ &Cinfo[ 166 ],
+ &Prop66
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop64 = {
+ 0xB8B4, /*start :复*/
+ 0xB8B4, /*end :复, len=1*/
+ &Cinfo[ 165 ],
+ &Prop65
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop63 = {
+ 0xB7FE, /*start :服*/
+ 0xB7FE, /*end :服, len=1*/
+ &Cinfo[ 164 ],
+ &Prop64
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop62 = {
+ 0xB7D6, /*start :分*/
+ 0xB7D6, /*end :分, len=1*/
+ &Cinfo[ 163 ],
+ &Prop63
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop61 = {
+ 0xB7C7, /*start :非*/
+ 0xB7C7, /*end :非, len=1*/
+ &Cinfo[ 162 ],
+ &Prop62
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop60 = {
+ 0xB7C5, /*start :放*/
+ 0xB7C5, /*end :放, len=1*/
+ &Cinfo[ 161 ],
+ &Prop61
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop59 = {
+ 0xB7BD, /*start :方*/
+ 0xB7BD, /*end :方, len=1*/
+ &Cinfo[ 160 ],
+ &Prop60
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop58 = {
+ 0xB7B4, /*start :反*/
+ 0xB7B6, /*end :范, len=3*/
+ &Cinfo[ 157 ],
+ &Prop59
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop57 = {
+ 0xB7A7, /*start :阀*/
+ 0xB7A8, /*end :法, len=2*/
+ &Cinfo[ 155 ],
+ &Prop58
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop56 = {
+ 0xB6CF, /*start :断*/
+ 0xB6CF, /*end :断, len=1*/
+ &Cinfo[ 154 ],
+ &Prop57
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop55 = {
+ 0xB6CC, /*start :短*/
+ 0xB6CC, /*end :短, len=1*/
+ &Cinfo[ 153 ],
+ &Prop56
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop54 = {
+ 0xB6C8, /*start :度*/
+ 0xB6C8, /*end :度, len=1*/
+ &Cinfo[ 152 ],
+ &Prop55
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop53 = {
+ 0xB6AF, /*start :动*/
+ 0xB6AF, /*end :动, len=1*/
+ &Cinfo[ 151 ],
+ &Prop54
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop52 = {
+ 0xB6A8, /*start :定*/
+ 0xB6A8, /*end :定, len=1*/
+ &Cinfo[ 150 ],
+ &Prop53
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop51 = {
+ 0xB5E7, /*start :电*/
+ 0xB5E7, /*end :电, len=1*/
+ &Cinfo[ 149 ],
+ &Prop52
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop50 = {
+ 0xB5E3, /*start :点*/
+ 0xB5E3, /*end :点, len=1*/
+ &Cinfo[ 148 ],
+ &Prop51
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop49 = {
+ 0xB5D8, /*start :地*/
+ 0xB5D8, /*end :地, len=1*/
+ &Cinfo[ 147 ],
+ &Prop50
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop48 = {
+ 0xB5CD, /*start :低*/
+ 0xB5CD, /*end :低, len=1*/
+ &Cinfo[ 146 ],
+ &Prop49
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop47 = {
+ 0xB5C4, /*start :的*/
+ 0xB5C4, /*end :的, len=1*/
+ &Cinfo[ 145 ],
+ &Prop48
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop46 = {
+ 0xB5B1, /*start :当*/
+ 0xB5B1, /*end :当, len=1*/
+ &Cinfo[ 144 ],
+ &Prop47
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop45 = {
+ 0xB5AF, /*start :弹*/
+ 0xB5AF, /*end :弹, len=1*/
+ &Cinfo[ 143 ],
+ &Prop46
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop44 = {
+ 0xB5A5, /*start :单*/
+ 0xB5A5, /*end :单, len=1*/
+ &Cinfo[ 142 ],
+ &Prop45
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop43 = {
+ 0xB4FD, /*start :待*/
+ 0xB4FD, /*end :待, len=1*/
+ &Cinfo[ 141 ],
+ &Prop44
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop42 = {
+ 0xB4F8, /*start :带*/
+ 0xB4F8, /*end :带, len=1*/
+ &Cinfo[ 140 ],
+ &Prop43
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop41 = {
+ 0xB4F3, /*start :大*/
+ 0xB4F3, /*end :大, len=1*/
+ &Cinfo[ 139 ],
+ &Prop42
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop40 = {
+ 0xB4E6, /*start :存*/
+ 0xB4E6, /*end :存, len=1*/
+ &Cinfo[ 138 ],
+ &Prop41
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop39 = {
+ 0xB4CE, /*start :次*/
+ 0xB4CE, /*end :次, len=1*/
+ &Cinfo[ 137 ],
+ &Prop40
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop38 = {
+ 0xB4C5, /*start :磁*/
+ 0xB4C5, /*end :磁, len=1*/
+ &Cinfo[ 136 ],
+ &Prop39
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop37 = {
+ 0xB4AB, /*start :传*/
+ 0xB4AB, /*end :传, len=1*/
+ &Cinfo[ 135 ],
+ &Prop38
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop36 = {
+ 0xB4A2, /*start :储*/
+ 0xB4A2, /*end :储, len=1*/
+ &Cinfo[ 134 ],
+ &Prop37
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop35 = {
+ 0xB3F6, /*start :出*/
+ 0xB3F6, /*end :出, len=1*/
+ &Cinfo[ 133 ],
+ &Prop36
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop34 = {
+ 0xB3CC, /*start :程*/
+ 0xB3CC, /*end :程, len=1*/
+ &Cinfo[ 132 ],
+ &Prop35
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop33 = {
+ 0xB3C9, /*start :成*/
+ 0xB3C9, /*end :成, len=1*/
+ &Cinfo[ 131 ],
+ &Prop34
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop32 = {
+ 0xB3C6, /*start :称*/
+ 0xB3C6, /*end :称, len=1*/
+ &Cinfo[ 130 ],
+ &Prop33
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop31 = {
+ 0xB3A7, /*start :厂*/
+ 0xB3A7, /*end :厂, len=1*/
+ &Cinfo[ 129 ],
+ &Prop32
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop30 = {
+ 0xB3A3, /*start :常*/
+ 0xB3A4, /*end :长, len=2*/
+ &Cinfo[ 127 ],
+ &Prop31
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop29 = {
+ 0xB2EE, /*start :差*/
+ 0xB2EE, /*end :差, len=1*/
+ &Cinfo[ 126 ],
+ &Prop30
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop28 = {
+ 0xB2E2, /*start :测*/
+ 0xB2E2, /*end :测, len=1*/
+ &Cinfo[ 125 ],
+ &Prop29
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop27 = {
+ 0xB2D9, /*start :操*/
+ 0xB2D9, /*end :操, len=1*/
+ &Cinfo[ 124 ],
+ &Prop28
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop26 = {
+ 0xB2CE, /*start :参*/
+ 0xB2CE, /*end :参, len=1*/
+ &Cinfo[ 123 ],
+ &Prop27
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop25 = {
+ 0xB2C1, /*start :擦*/
+ 0xB2C1, /*end :擦, len=1*/
+ &Cinfo[ 122 ],
+ &Prop26
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop24 = {
+ 0xB2BB, /*start :不*/
+ 0xB2BB, /*end :不, len=1*/
+ &Cinfo[ 121 ],
+ &Prop25
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop23 = {
+ 0xB1ED, /*start :表*/
+ 0xB1ED, /*end :表, len=1*/
+ &Cinfo[ 120 ],
+ &Prop24
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop22 = {
+ 0xB1E4, /*start :变*/
+ 0xB1E4, /*end :变, len=1*/
+ &Cinfo[ 119 ],
+ &Prop23
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop21 = {
+ 0xB1E0, /*start :编*/
+ 0xB1E0, /*end :编, len=1*/
+ &Cinfo[ 118 ],
+ &Prop22
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop20 = {
+ 0xB1D5, /*start :闭*/
+ 0xB1D5, /*end :闭, len=1*/
+ &Cinfo[ 117 ],
+ &Prop21
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop19 = {
+ 0xB1C8, /*start :比*/
+ 0xB1C8, /*end :比, len=1*/
+ &Cinfo[ 116 ],
+ &Prop20
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop18 = {
+ 0xB1BE, /*start :本*/
+ 0xB1BE, /*end :本, len=1*/
+ &Cinfo[ 115 ],
+ &Prop19
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop17 = {
+ 0xB1B8, /*start :备*/
+ 0xB1B8, /*end :备, len=1*/
+ &Cinfo[ 114 ],
+ &Prop18
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop16 = {
+ 0xB1A8, /*start :报*/
+ 0xB1A8, /*end :报, len=1*/
+ &Cinfo[ 113 ],
+ &Prop17
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop15 = {
+ 0xB1A5, /*start :饱*/
+ 0xB1A5, /*end :饱, len=1*/
+ &Cinfo[ 112 ],
+ &Prop16
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop14 = {
+ 0xB1A3, /*start :保*/
+ 0xB1A3, /*end :保, len=1*/
+ &Cinfo[ 111 ],
+ &Prop15
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop13 = {
+ 0xB1A1, /*start :薄*/
+ 0xB1A1, /*end :薄, len=1*/
+ &Cinfo[ 110 ],
+ &Prop14
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop12 = {
+ 0xB0E6, /*start :版*/
+ 0xB0E6, /*end :版, len=1*/
+ &Cinfo[ 109 ],
+ &Prop13
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop11 = {
+ 0xB0B4, /*start :按*/
+ 0xB0B4, /*end :按, len=1*/
+ &Cinfo[ 108 ],
+ &Prop12
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop10 = {
+ 0xB0B2, /*start :安*/
+ 0xB0B2, /*end :安, len=1*/
+ &Cinfo[ 107 ],
+ &Prop11
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop9 = {
+ 0xA848, /*start :℉*/
+ 0xA848, /*end :℉, len=1*/
+ &Cinfo[ 106 ],
+ &Prop10
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop8 = {
+ 0xA1FA, /*start :→*/
+ 0xA1FD, /*end :↓, len=4*/
+ &Cinfo[ 102 ],
+ &Prop9
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop7 = {
+ 0xA1F0, /*start :○*/
+ 0xA1F0, /*end :○, len=1*/
+ &Cinfo[ 101 ],
+ &Prop8
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop6 = {
+ 0xA1E6, /*start :℃*/
+ 0xA1E6, /*end :℃, len=1*/
+ &Cinfo[ 100 ],
+ &Prop7
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop5 = {
+ 0xA1E3, /*start :°*/
+ 0xA1E3, /*end :°, len=1*/
+ &Cinfo[ 99 ],
+ &Prop6
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop4 = {
+ 0xA1CC, /*start :√*/
+ 0xA1CC, /*end :√, len=1*/
+ &Cinfo[ 98 ],
+ &Prop5
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop3 = {
+ 0xA1C1, /*start :×*/
+ 0xA1C1, /*end :×, len=1*/
+ &Cinfo[ 97 ],
+ &Prop4
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop2 = {
+ 0xA1AB, /*start :~*/
+ 0xA1AB, /*end :~, len=1*/
+ &Cinfo[ 96 ],
+ &Prop3
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop1 = {
+ 0x0020, /*start : */
+ 0x007F, /*end :, len=96*/
+ &Cinfo[ 0 ],
+ &Prop2
+};
+
+
+GUI_CONST_STORAGE GUI_FONT GUI_FontHZ16x16 = {
+ GUI_FONTTYPE_PROP_SJIS,
+ 16, /* height of font */
+ 16, /* space of font y */
+ 1,
+ 1,
+ &Prop1
+};
+
diff --git a/User/lib/lcd/font/HZ18x18.c b/User/lib/lcd/font/HZ18x18.c
new file mode 100644
index 0000000..a7e0b6c
--- /dev/null
+++ b/User/lib/lcd/font/HZ18x18.c
@@ -0,0 +1,374 @@
+/*
+**********************************************************************
+* UcGUI Font
+* Chinese GB2312 library
+* (c) Copyright 19xx-20xx, company name
+*
+*
+* 注:本字体文件由 ucGUI字体生成器v9.0 生成,作者:馋嘴猫(qq:602426967)
+*
+**********************************************************************
+*/
+
+#include "GUI.H"
+
+
+/* char: code:0x0031 */
+static GUI_CONST_STORAGE unsigned char ac0031[54] = {
+ _____XX_,_____X__,________,
+ _____XX_,___XXXXX,________,
+ _XXX_XX_,__XX___X,X_______,
+ __XX____,_XX_____,X_______,
+ ___X____,XX______,XX______,
+ XXX_____,X_______,X_______,
+ XXX_____,_______X,X_______,
+ ________,______XX,________,
+ ____XX__,_____XX_,________,
+ ___XX___,____XX__,________,
+ __XX____,________,________,
+ _XX_____,_______X,XX______,
+ XX______,_X_____X,XX______,
+ XX______,XX____X_,________,
+ XX_____X,X_____XX,________,
+ _XX___XX,___XX_XX,X_______,
+ __XXXXX_,___XX___,________,
+ ___XXX__,___XX___,________
+};
+
+/* char: code:0x0032 */
+static GUI_CONST_STORAGE unsigned char ac0032[54] = {
+ ________,____XXX_,________,
+ ________,___XXXXX,________,
+ ________,__XX___X,X_______,
+ ________,_XX_____,XX______,
+ _______X,XX______,XX______,
+ _______X,X_______,XX______,
+ ______XX,______XX,X_______,
+ ______XX,_XX__XXX,________,
+ ____X_XX,_XXXXXX_,________,
+ ___XXXXX,X_XX_X__,________,
+ __XXX__X,X_XX____,________,
+ _XXX____,__XX____,________,
+ XX______,_XX_____,________,
+ XX______,XXX_____,________,
+ XX_____X,X_______,________,
+ _XX___XX,________,________,
+ __XXXXX_,________,________,
+ ___XXX__,________,________
+};
+
+/* char: code:0x0033 */
+static GUI_CONST_STORAGE unsigned char ac0033[54] = {
+ ________,___XXXX_,________,
+ ________,__XXXXXX,X_______,
+ ________,_XXX__XX,XX______,
+ ________,_XXX____,XX______,
+ ________,_XX_____,XX______,
+ ________,_XX_____,XX______,
+ ________,_XX_____,XX______,
+ ________,________,________,
+ XXXXXXXX,XXXXX___,________,
+ XXXXXXXX,XXXXX___,________,
+ XXXXXXXX,XXXXX___,________,
+ XXXXXXXX,XXXXX___,________,
+ XXXXXXXX,XXXXX___,________,
+ XXXXXXXX,XXXXX___,________,
+ XXXXXXXX,XXXXX___,________,
+ XXXXXXXX,XXXXX___,________,
+ _XXXXXXX,XXXX____,________,
+ ________,________,________
+};
+
+/* char: code:0x0034 */
+static GUI_CONST_STORAGE unsigned char ac0034[54] = {
+ _______X,XXX_____,________,
+ ______XX,XXXX____,________,
+ _____XXX,__XXX___,________,
+ _____XX_,___XX___,________,
+ ____XXX_,___XX___,________,
+ ____XXX_,___XX___,________,
+ ____XXX_,___XX___,________,
+ ________,________,________,
+ __XXXXXX,XXXXXXXX,________,
+ __XXXXXX,XXXXXXXX,________,
+ __XXXXXX,XXXXXXXX,________,
+ __XXXXXX,XXXXXXXX,________,
+ __XXXXXX,XXXXXXXX,________,
+ __XXXXXX,XXXXXXXX,________,
+ __XXXXXX,XXXXXXXX,________,
+ __XXXXXX,XXXXXXXX,________,
+ ___XXXXX,XXXXXXX_,________,
+ ________,________,________
+};
+
+/* char: code:0x0035 */
+static GUI_CONST_STORAGE unsigned char ac0035[54] = {
+ ________,________,________,
+ ________,________,________,
+ _____XXX,XXXXX___,________,
+ ____XX__,____XX__,________,
+ ___XX___,____XXX_,________,
+ __XX____,___XX_XX,________,
+ __X_____,__XXX__X,________,
+ __X_____,_XXX___X,________,
+ __X_____,XXX____X,________,
+ __X____X,XX_____X,________,
+ __X___XX,X______X,________,
+ __X__XXX,_______X,________,
+ ___XXXX_,______XX,________,
+ ___XX___,_____XX_,________,
+ ____XX__,____XX__,________,
+ ______XX,XXXXX___,________,
+ ________,________,________,
+ ________,________,________
+};
+
+/* char: code:0x0036 */
+static GUI_CONST_STORAGE unsigned char ac0036[54] = {
+ ________,XX______,________,
+ ________,XXX_____,________,
+ ________,XXXX____,________,
+ ________,XXXXX___,________,
+ ____XX__,XX_XXX__,________,
+ _____XX_,XX_XXX__,________,
+ _____XXX,XXXXX___,________,
+ ______XX,XXXX____,________,
+ ________,XXX_____,________,
+ ________,XXX_____,________,
+ _______X,XXXX____,________,
+ _____XXX,XX_XX___,________,
+ _____XX_,XX__XX__,________,
+ ____XX__,XX_XXX__,________,
+ ________,XXXXX___,________,
+ ________,XXXX____,________,
+ ________,XXX_____,________,
+ ________,XX______,________
+};
+
+/* char: code:0x0037 */
+static GUI_CONST_STORAGE unsigned char ac0037[54] = {
+ ________,_______X,________,
+ ________,______XX,________,
+ ________,____XXXX,________,
+ ________,__XXXXXX,________,
+ ________,_XXXXXXX,________,
+ _______X,XXXXXXXX,________,
+ ______XX,XXXXXXXX,________,
+ ____XXXX,XXXXXXXX,________,
+ ___XXXXX,XXXXXXXX,________,
+ ___XXXXX,XXXXXXXX,________,
+ _____XXX,XXXXXXXX,________,
+ ______XX,XXXXXXXX,________,
+ _______X,XXXXXXXX,________,
+ ________,_XXXXXXX,________,
+ ________,___XXXXX,________,
+ ________,____XXXX,________,
+ ________,______XX,________,
+ ________,_______X,________
+};
+
+/* char: code:0x0061 */
+static GUI_CONST_STORAGE unsigned char ac0061[54] = {
+ ________,________,________,
+ _______X,XXX_____,________,
+ ______XX,XXX_____,________,
+ ______XX,XXXX____,________,
+ ______XX,_XXX____,________,
+ _____XXX,__XX____,________,
+ _____XXX,__XXX___,________,
+ ____XXX_,__XXX___,________,
+ ____XXX_,___XXX__,________,
+ ____XX__,___XXX__,________,
+ ___XXX__,____XX__,________,
+ ___XXXXX,XXXXXXX_,________,
+ __XXXXXX,XXXXXXX_,________,
+ __XXX___,_____XX_,________,
+ __XXX___,_____XXX,________,
+ _XXX____,_____XXX,________,
+ _XXX____,______XX,X_______,
+ ________,________,________
+};
+
+/* char: code:0x0066 */
+static GUI_CONST_STORAGE unsigned char ac0066[54] = {
+ ________,________,________,
+ __XXXXXX,XXXXXXXX,X_______,
+ __XXXXXX,XXXXXXXX,X_______,
+ __XXXX__,________,________,
+ __XXXX__,________,________,
+ __XXXX__,________,________,
+ __XXXX__,________,________,
+ __XXXX__,________,________,
+ __XXXXXX,XXXXXXXX,________,
+ __XXXXXX,XXXXXXXX,________,
+ __XXXX__,________,________,
+ __XXXX__,________,________,
+ __XXXX__,________,________,
+ __XXXX__,________,________,
+ __XXXX__,________,________,
+ __XXXX__,________,________,
+ __XXXX__,________,________,
+ ________,________,________
+};
+
+/* char: code:0x006D */
+static GUI_CONST_STORAGE unsigned char ac006D[54] = {
+ ________,________,________,
+ _XXXX___,______XX,X_______,
+ _XXXX___,_____XXX,X_______,
+ _XXXXX__,_____XXX,X_______,
+ _XX_XX__,____XXXX,X_______,
+ _XXXXX__,____XX_X,X_______,
+ _XXXXXX_,____XX_X,X_______,
+ _XXX_XX_,___XX__X,X_______,
+ _XXX_XX_,___XX__X,X_______,
+ _XXX__XX,___XX__X,X_______,
+ _XXX__XX,__XX___X,X_______,
+ _XXX__XX,__XX___X,X_______,
+ _XXX___X,X_XX___X,X_______,
+ _XXX___X,XXX____X,X_______,
+ _XXX___X,XXX____X,X_______,
+ _XXX____,XXX____X,X_______,
+ _XXX____,XX_____X,X_______,
+ ________,________,________
+};
+
+/* char: code:0x0073 */
+static GUI_CONST_STORAGE unsigned char ac0073[54] = {
+ ________,________,________,
+ _____XXX,XXXXX___,________,
+ ___XXXXX,XXXXXXX_,________,
+ __XXXX__,___XXXXX,________,
+ __XXXX__,____XXXX,________,
+ __XXXX__,________,________,
+ __XXXX__,________,________,
+ ___XXXXX,X_______,________,
+ ____XXXX,XXXXX___,________,
+ _______X,XXXXXXX_,________,
+ ________,___XXXXX,________,
+ ________,_____XXX,X_______,
+ ____X___,_____XXX,X_______,
+ _XXXX___,_____XXX,X_______,
+ __XXXX__,____XXXX,________,
+ ___XXXXX,XXXXXXX_,________,
+ _____XXX,XXXXX___,________,
+ ________,________,________
+};
+
+/* char: code:0x0074 */
+static GUI_CONST_STORAGE unsigned char ac0074[54] = {
+ ________,________,________,
+ _XXXXXXX,XXXXXXXX,X_______,
+ _XXXXXXX,XXXXXXXX,X_______,
+ _______X,XXX_____,________,
+ _______X,XXX_____,________,
+ _______X,XXX_____,________,
+ _______X,XXX_____,________,
+ _______X,XXX_____,________,
+ _______X,XXX_____,________,
+ _______X,XXX_____,________,
+ _______X,XXX_____,________,
+ _______X,XXX_____,________,
+ _______X,XXX_____,________,
+ _______X,XXX_____,________,
+ _______X,XXX_____,________,
+ _______X,XXX_____,________,
+ _______X,XXX_____,________,
+ ________,________,________
+};
+
+/* char: code:0x0077 */
+static GUI_CONST_STORAGE unsigned char ac0077[54] = {
+ ________,________,________,
+ _XX_____,XX_____X,X_______,
+ _XX_____,XX_____X,X_______,
+ _XX____X,XX_____X,X_______,
+ _XX____X,XXX___XX,X_______,
+ _XX____X,XXX___XX,________,
+ __XX___X,_XX___XX,________,
+ __XX__XX,__X___XX,________,
+ __XX__XX,__X___XX,________,
+ __XX__XX,__XX__XX,________,
+ __XX__XX,__XX_XX_,________,
+ ___XX_X_,__XX_XX_,________,
+ ___XXXX_,___X_XX_,________,
+ ___XXXX_,___X_XX_,________,
+ ___XXXX_,___XXX__,________,
+ ___XXX__,___XXX__,________,
+ ____XX__,___XXX__,________,
+ ________,________,________
+};
+
+static GUI_CONST_STORAGE GUI_CHARINFO Cinfo[13] = {
+ { 18, 18, 3, (unsigned char *)&ac0031 }, /*0: */
+ { 18, 18, 3, (unsigned char *)&ac0032 }, /*1: */
+ { 18, 18, 3, (unsigned char *)&ac0033 }, /*2: */
+ { 16, 16, 3, (unsigned char *)&ac0034 }, /*3: */
+ { 16, 16, 3, (unsigned char *)&ac0035 }, /*4: */
+ { 14, 14, 3, (unsigned char *)&ac0036 }, /*5: */
+ { 16, 16, 3, (unsigned char *)&ac0037 }, /*6: */
+ { 17, 17, 3, (unsigned char *)&ac0061 }, /*7: */
+ { 17, 17, 3, (unsigned char *)&ac0066 }, /*8: */
+ { 17, 17, 3, (unsigned char *)&ac006D }, /*9: */
+ { 17, 17, 3, (unsigned char *)&ac0073 }, /*10: */
+ { 17, 17, 3, (unsigned char *)&ac0074 }, /*11: */
+ { 17, 17, 3, (unsigned char *)&ac0077 }, /*12: */
+};
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop6 = {
+ 0x0077, /*start :*/
+ 0x0077, /*end :, len=1*/
+ &Cinfo[ 12 ],
+ (void*)0
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop5 = {
+ 0x0073, /*start :*/
+ 0x0074, /*end :, len=2*/
+ &Cinfo[ 10 ],
+ &Prop6
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop4 = {
+ 0x006D, /*start :*/
+ 0x006D, /*end :, len=1*/
+ &Cinfo[ 9 ],
+ &Prop5
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop3 = {
+ 0x0066, /*start :*/
+ 0x0066, /*end :, len=1*/
+ &Cinfo[ 8 ],
+ &Prop4
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop2 = {
+ 0x0061, /*start :*/
+ 0x0061, /*end :, len=1*/
+ &Cinfo[ 7 ],
+ &Prop3
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop1 = {
+ 0x0031, /*start :*/
+ 0x0037, /*end :, len=7*/
+ &Cinfo[ 0 ],
+ &Prop2
+};
+
+
+GUI_CONST_STORAGE GUI_FONT GUI_FontHZ18x18 = {
+ GUI_FONTTYPE_PROP_SJIS,
+ 18, /* height of font */
+ 18, /* space of font y */
+ 1,
+ 1,
+ &Prop1
+};
+
diff --git a/User/lib/lcd/font/HZ20x20.c b/User/lib/lcd/font/HZ20x20.c
new file mode 100644
index 0000000..12ed338
--- /dev/null
+++ b/User/lib/lcd/font/HZ20x20.c
@@ -0,0 +1,198 @@
+/*
+**********************************************************************
+* UcGUI Font
+* Chinese GB2312 library
+* (c) Copyright 19xx-20xx, company name
+*
+*
+* 注:本字体文件由 ucGUI字体生成器v9.0 生成,作者:馋嘴猫(qq:602426967)
+*
+**********************************************************************
+*/
+
+#include "GUI.H"
+
+/* char: code:0x0030 */
+static GUI_CONST_STORAGE unsigned char ac0030[60] = {
+ ________, ________, ________,
+ _______X, XXXXX___, ________,
+ _____XXX, ____XXX_, ________,
+ ____XX__, ______XX, ________,
+ ___XX___, _______X, X_______,
+ __XX__X_, _____X__, XX______,
+ __X__XXX, ____XXX_, _X______,
+ _XX___XX, X__XXX__, _XX_____,
+ _X_____X, XXXXX___, _XX_____,
+ _X______, XXXX____, __X_____,
+ _X______, XXXX____, __X_____,
+ _X_____X, XXXXX___, _XX_____,
+ _XX___XX, X__XXX__, _XX_____,
+ __X__XXX, ____XXX_, _X______,
+ __XX__X_, _____X__, XX______,
+ ___XX___, _______X, X_______,
+ ____XX__, ______XX, ________,
+ _____XXX, X__XXXX_, ________,
+ _______X, XXXXX___, ________,
+ ________, ________, ________};
+
+/* char: code:0x0031 */
+static GUI_CONST_STORAGE unsigned char ac0031[60] = {
+ _______X, XXXXX___, ________,
+ _____XXX, XXXXXXX_, ________,
+ ___XXX__, ______XX, X_______,
+ __XXX___, _______X, XX______,
+ __XX____, ________, XX______,
+ _XX____X, XXXXX___, _XX_____,
+ _X_____X, X__XX___, __X_____,
+ XX____XX, ____XX__, __XX____,
+ XX______, ____XX__, __XX____,
+ XX______, ___XX___, __XX____,
+ XX______, __XX____, __XX____,
+ XX______, _XX_____, __XX____,
+ XX______, _XX_____, __XX____,
+ _X______, ________, _XX_____,
+ _XX_____, _XX_____, _XX_____,
+ __XX____, _XX_____, XX______,
+ __XXX___, _X_____X, X_______,
+ ___XXX__, ______XX, ________,
+ _____XXX, XXXXXXX_, ________,
+ _______X, XXXXX___, ________};
+
+/* char: code:0x0032 */
+static GUI_CONST_STORAGE unsigned char ac0032[60] = {
+ _____XXX, XX______, ________,
+ ____XXXX, XXX_____, ________,
+ _____XX_, __XX____, ________,
+ ______XX, ___XX___, ________,
+ _X_____X, ____XX__, ________,
+ XXX____X, X___XX__, ________,
+ XXXX___X, X____X__, ________,
+ XX_XXXXX, _____X__, ________,
+ XX___X__, ____XX__, ________,
+ XX______, ____XX__, ________,
+ _XX_____, _____XX_, ________,
+ __XX____, ______XX, ________,
+ ___XXX__, XX_____X, X_______,
+ ____XXXX, XXX_____, XX______,
+ ________, __XX____, _XX_____,
+ ________, ___XX___, __XX____,
+ ________, ____XX__, __XX____,
+ ________, _____XX_, __XX____,
+ ________, ______XX, XXX_____,
+ ________, _______X, XX______};
+
+/* char: code:0x0033 */
+static GUI_CONST_STORAGE unsigned char ac0033[60] = {
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, XX______,
+ ________, _______X, XXX_____,
+ ________, ______XX, XX______,
+ ________, _____XXX, X_______,
+ __XX____, ____XXXX, ________,
+ __XXX___, ___XXXX_, ________,
+ ___XXX__, __XXXX__, ________,
+ ____XXX_, _XXXX___, ________,
+ _____XXX, XXXX____, ________,
+ ______XX, XXX_____, ________,
+ _______X, XX______, ________,
+ ________, X_______, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________};
+
+/* char: code:0x0034 */
+static GUI_CONST_STORAGE unsigned char ac0034[60] = {
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, _______X, ________,
+ ___X____, _X____X_, X_______,
+ __X_X___, X_X__X__, ________,
+ ___X____, _X____X_, X_______,
+ ________, _______X, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________};
+
+/* char: code:0x0035 */
+static GUI_CONST_STORAGE unsigned char ac0035[60] = {
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ___X____, ________, ________,
+ __X_XX__, _X_____X, ________,
+ _____X__, X_X___X_, X_______,
+ __X_XX__, _X_____X, ________,
+ ___X____, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________};
+
+/* char: code:0x0036 */
+static GUI_CONST_STORAGE unsigned char ac0036[60] = {
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, _X______, ________,
+ ___X____, X_X____X, ________,
+ __X_X__X, ___X__X_, X_______,
+ ___X____, X_X____X, ________,
+ ________, _X______, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________};
+
+static GUI_CONST_STORAGE GUI_CHARINFO Cinfo[7] = {
+ {19, 19, 3, (unsigned char *)&ac0030}, /*0: */
+ {20, 20, 3, (unsigned char *)&ac0031}, /*1: */
+ {20, 20, 3, (unsigned char *)&ac0032}, /*2: */
+ {19, 19, 3, (unsigned char *)&ac0033}, /*3: */
+ {17, 17, 3, (unsigned char *)&ac0034}, /*4: */
+ {17, 17, 3, (unsigned char *)&ac0035}, /*5: */
+ {17, 17, 3, (unsigned char *)&ac0036}, /*6: */
+};
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop1 = {
+ 0x0030, /*start :*/
+ 0x0036, /*end :, len=7*/
+ &Cinfo[0],
+ (void *)0};
+
+GUI_CONST_STORAGE GUI_FONT GUI_FontHZ20x20 = {
+ GUI_FONTTYPE_PROP_SJIS,
+ 20, /* height of font */
+ 20, /* space of font y */
+ 1,
+ 1,
+ &Prop1};
diff --git a/User/lib/lcd/font/HZ24x24.c b/User/lib/lcd/font/HZ24x24.c
new file mode 100644
index 0000000..34e92e5
--- /dev/null
+++ b/User/lib/lcd/font/HZ24x24.c
@@ -0,0 +1,8317 @@
+/*
+**********************************************************************
+* UcGUI Font
+* Chinese GB2312 library
+* (c) Copyright 19xx-20xx, company name
+*
+*
+* 注:本字体文件由 ucGUI字体生成器v9.0 生成,作者:馋嘴猫(qq:602426967)
+* 字体:宋体,字形:粗体,大小:18,宽:24,高:24,水平偏移:0,垂直偏移:0
+*
+**********************************************************************
+*/
+
+#include "GUI.H"
+
+
+/* char: code:0x0020 */
+static GUI_CONST_STORAGE unsigned char ac0020[48] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: ! code:0x0021 */
+static GUI_CONST_STORAGE unsigned char ac0021[48] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ _____XXX,________,
+ _____XXX,________,
+ _____XXX,________,
+ _____XXX,________,
+ _____XXX,________,
+ _____XXX,________,
+ _____XXX,________,
+ ______XX,________,
+ _____XX_,________,
+ _____XX_,________,
+ _____XX_,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ _____XXX,________,
+ _____XXX,________,
+ _____XXX,________,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: " code:0x0022 */
+static GUI_CONST_STORAGE unsigned char ac0022[48] = {
+ ________,________,
+ ________,________,
+ _____XXX,_XXX____,
+ _____XXX,_XXX____,
+ ____XXX_,XXX_____,
+ ___XXX_X,XX______,
+ ___XX__X,X_______,
+ __XX__XX,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: # code:0x0023 */
+static GUI_CONST_STORAGE unsigned char ac0023[48] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ____XX__,_XX_____,
+ ____XX__,_XX_____,
+ ____XX__,_XX_____,
+ ____XX__,_XX_____,
+ _XXXXXXX,XXXX____,
+ _XXXXXXX,XXXX____,
+ ___XX___,_XX_____,
+ ___XX___,XX______,
+ ___XX___,XX______,
+ ___XX___,XX______,
+ ___XX___,XX______,
+ _XXXXXXX,XXXX____,
+ _XXXXXXX,XXXX____,
+ __XX____,XX______,
+ __XX____,XX______,
+ __XX____,XX______,
+ __XX____,XX______,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: $ code:0x0024 */
+static GUI_CONST_STORAGE unsigned char ac0024[48] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ______XX,________,
+ ______XX,________,
+ ____XXXX,XX______,
+ ___XXXXX,XXX_____,
+ __XXX_XX,XXX_____,
+ __XXX_XX,XXX_____,
+ __XXX_XX,________,
+ ___XXXXX,________,
+ ____XXXX,________,
+ _____XXX,X_______,
+ ______XX,XX______,
+ ______XX,XX______,
+ ______XX,XXX_____,
+ __XXX_XX,XXX_____,
+ __XXXXXX,XXX_____,
+ __XXX_XX,XXX_____,
+ ___XX_XX,XX______,
+ ____XXXX,X_______,
+ ______XX,________,
+ ______XX,________,
+ ________,________
+};
+
+/* char: % code:0x0025 */
+static GUI_CONST_STORAGE unsigned char ac0025[48] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ _XXXX___,XX______,
+ _XXXX___,XX______,
+ XX__XX_X,X_______,
+ XX__XX_X,X_______,
+ XX__XX_X,X_______,
+ XX__XXXX,________,
+ XX__XXXX,________,
+ _XXXXXX_,________,
+ _XXXXXXX,XXX_____,
+ _____XXX,XXX_____,
+ ____XXXX,__XX____,
+ ____XXXX,__XX____,
+ ___XX_XX,__XX____,
+ ___XX_XX,__XX____,
+ ___XX_XX,__XX____,
+ __XX___X,XXX_____,
+ __XX___X,XXX_____,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: & code:0x0026 */
+static GUI_CONST_STORAGE unsigned char ac0026[48] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ___XXXX_,________,
+ __XXXXXX,________,
+ __XXXXXX,________,
+ __XXXXXX,________,
+ __XXXXXX,________,
+ __XXXXXX,________,
+ __XXXXX_,________,
+ ___XXX_X,XXXX____,
+ __XXXX__,XX______,
+ _XXXXX__,XX______,
+ XXX_XXX_,XX______,
+ XXX_XXX_,XX______,
+ XXX__XXX,XX______,
+ XXX__XXX,X_______,
+ XXX___XX,X__XX___,
+ _XXX__XX,XX_XX___,
+ __XXXXX_,XXXX____,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: ' code:0x0027 */
+static GUI_CONST_STORAGE unsigned char ac0027[48] = {
+ ________,________,
+ ________,________,
+ __XXX___,________,
+ __XXXX__,________,
+ ____XX__,________,
+ ____XX__,________,
+ ___XX___,________,
+ __XX____,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: ( code:0x0028 */
+static GUI_CONST_STORAGE unsigned char ac0028[48] = {
+ ________,________,
+ ________,________,
+ ________,__XX____,
+ ________,_XX_____,
+ ________,XX______,
+ _______X,X_______,
+ _______X,X_______,
+ ______XX,________,
+ ______XX,________,
+ _____XX_,________,
+ _____XX_,________,
+ _____XX_,________,
+ _____XX_,________,
+ _____XX_,________,
+ _____XX_,________,
+ _____XX_,________,
+ ______XX,________,
+ ______XX,________,
+ _______X,X_______,
+ _______X,X_______,
+ ________,XX______,
+ ________,_XX_____,
+ ________,__XX____,
+ ________,________
+};
+
+/* char: ) code:0x0029 */
+static GUI_CONST_STORAGE unsigned char ac0029[48] = {
+ ________,________,
+ ________,________,
+ _XX_____,________,
+ __XX____,________,
+ ___XX___,________,
+ ____XX__,________,
+ ____XX__,________,
+ _____XX_,________,
+ _____XX_,________,
+ ______XX,________,
+ ______XX,________,
+ ______XX,________,
+ ______XX,________,
+ ______XX,________,
+ ______XX,________,
+ ______XX,________,
+ _____XX_,________,
+ _____XX_,________,
+ ____XX__,________,
+ ____XX__,________,
+ ___XX___,________,
+ __XX____,________,
+ _XX_____,________,
+ ________,________
+};
+
+/* char: * code:0x002A */
+static GUI_CONST_STORAGE unsigned char ac002A[48] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ______XX,________,
+ ______XX,X_______,
+ ______XX,________,
+ _XXX__XX,__XXX___,
+ _XXXX_XX,XXXXX___,
+ ____XXXX,XX______,
+ ____XXXX,XX______,
+ _XXXXXXX,XXXXX___,
+ _XXX__XX,__XXX___,
+ ______XX,________,
+ ______XX,________,
+ ______XX,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: + code:0x002B */
+static GUI_CONST_STORAGE unsigned char ac002B[48] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ______XX,________,
+ ______XX,________,
+ ______XX,________,
+ ______XX,________,
+ ______XX,________,
+ _XXXXXXX,XXXXX___,
+ ______XX,________,
+ ______XX,________,
+ ______XX,________,
+ ______XX,________,
+ ______XX,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: , code:0x002C */
+static GUI_CONST_STORAGE unsigned char ac002C[48] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ __XXX___,________,
+ __XXXX__,________,
+ ____XX__,________,
+ ____XX__,________,
+ ___XX___,________,
+ __XX____,________
+};
+
+/* char: - code:0x002D */
+static GUI_CONST_STORAGE unsigned char ac002D[48] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ _XXXXXXX,XXXX____,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: . code:0x002E */
+static GUI_CONST_STORAGE unsigned char ac002E[48] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ __XXXX__,________,
+ __XXXX__,________,
+ __XXXX__,________,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: / code:0x002F */
+static GUI_CONST_STORAGE unsigned char ac002F[48] = {
+ ________,________,
+ ________,________,
+ ________,__XX____,
+ ________,_XXX____,
+ ________,_XX_____,
+ ________,XXX_____,
+ ________,XX______,
+ ________,XX______,
+ _______X,X_______,
+ _______X,X_______,
+ ______XX,________,
+ ______XX,________,
+ _____XXX,________,
+ _____XX_,________,
+ _____XX_,________,
+ ____XX__,________,
+ ____XX__,________,
+ ___XX___,________,
+ ___XX___,________,
+ __XXX___,________,
+ __XX____,________,
+ _XXX____,________,
+ _XX_____,________,
+ ________,________
+};
+
+/* char: 0 code:0x0030 */
+static GUI_CONST_STORAGE unsigned char ac0030[48] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ____XXXX,X_______,
+ ___XXX_X,XX______,
+ __XXX___,XXX_____,
+ __XXX___,XXX_____,
+ _XXX____,_XXX____,
+ _XXX____,_XXX____,
+ _XXX____,_XXX____,
+ _XXX____,_XXX____,
+ _XXX____,_XXX____,
+ _XXX____,_XXX____,
+ _XXX____,_XXX____,
+ _XXX____,_XXX____,
+ __XXX___,XXX_____,
+ __XXX___,XXX_____,
+ ___XXX_X,XX______,
+ ____XXXX,X_______,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: 1 code:0x0031 */
+static GUI_CONST_STORAGE unsigned char ac0031[48] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ______XX,________,
+ __XXXXXX,________,
+ _____XXX,________,
+ _____XXX,________,
+ _____XXX,________,
+ _____XXX,________,
+ _____XXX,________,
+ _____XXX,________,
+ _____XXX,________,
+ _____XXX,________,
+ _____XXX,________,
+ _____XXX,________,
+ _____XXX,________,
+ _____XXX,________,
+ _____XXX,________,
+ __XXXXXX,XXX_____,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: 2 code:0x0032 */
+static GUI_CONST_STORAGE unsigned char ac0032[48] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ___XXXXX,X_______,
+ __XX___X,XX______,
+ _XX_____,XXX_____,
+ _XXX____,XXX_____,
+ _XXX____,XXX_____,
+ ________,XXX_____,
+ ________,XX______,
+ _______X,XX______,
+ ______XX,X_______,
+ _____XXX,________,
+ _____XX_,________,
+ ____XX__,________,
+ ___XX___,_XX_____,
+ __XX____,_XX_____,
+ _XXX____,_XX_____,
+ _XXXXXXX,XXX_____,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: 3 code:0x0033 */
+static GUI_CONST_STORAGE unsigned char ac0033[48] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ___XXXXX,________,
+ _XXX__XX,X_______,
+ _XXX___X,XX______,
+ _XXX___X,XX______,
+ _______X,XX______,
+ _______X,XX______,
+ ______XX,X_______,
+ ____XXXX,________,
+ _______X,XX______,
+ ________,XX______,
+ ________,XXX_____,
+ ________,XXX_____,
+ _XXX____,XXX_____,
+ _XXX____,XXX_____,
+ _XXX___X,XX______,
+ ___XXXXX,X_______,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: 4 code:0x0034 */
+static GUI_CONST_STORAGE unsigned char ac0034[48] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ _______X,XX______,
+ _______X,XX______,
+ ______XX,XX______,
+ _____XXX,XX______,
+ _____XXX,XX______,
+ ____XX_X,XX______,
+ ___XX__X,XX______,
+ ___XX__X,XX______,
+ __XX___X,XX______,
+ _XX____X,XX______,
+ _XXXXXXX,XXXXX___,
+ _______X,XX______,
+ _______X,XX______,
+ _______X,XX______,
+ _______X,XX______,
+ _____XXX,XXXX____,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: 5 code:0x0035 */
+static GUI_CONST_STORAGE unsigned char ac0035[48] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ __XXXXXX,XXX_____,
+ __XX____,________,
+ __XX____,________,
+ __XX____,________,
+ __XX____,________,
+ __XX____,________,
+ __XXXXXX,X_______,
+ __XXX__X,XX______,
+ __XX____,XXX_____,
+ ________,XXX_____,
+ ________,XXX_____,
+ _XXX____,XXX_____,
+ _XXX____,XXX_____,
+ _XX____X,XX______,
+ __XX___X,XX______,
+ ___XXXXX,X_______,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: 6 code:0x0036 */
+static GUI_CONST_STORAGE unsigned char ac0036[48] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ _____XXX,XX______,
+ ___XXX__,XXX_____,
+ __XXX___,XXX_____,
+ __XXX___,________,
+ __XX____,________,
+ _XXX____,________,
+ _XXX_XXX,XX______,
+ _XXXXX__,XXX_____,
+ _XXXX___,_XXX____,
+ _XXX____,_XXX____,
+ _XXX____,_XXX____,
+ _XXX____,_XXX____,
+ __XX____,_XXX____,
+ __XXX___,_XX_____,
+ ___XXX__,XXX_____,
+ ____XXXX,X_______,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: 7 code:0x0037 */
+static GUI_CONST_STORAGE unsigned char ac0037[48] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ___XXXXX,XXXX____,
+ __XXX___,_XXX____,
+ __XX____,_XX_____,
+ __XX____,XX______,
+ ________,XX______,
+ ________,XX______,
+ _______X,X_______,
+ _______X,X_______,
+ ______XX,________,
+ ______XX,________,
+ ______XX,________,
+ _____XXX,________,
+ _____XXX,________,
+ _____XXX,________,
+ _____XXX,________,
+ _____XXX,________,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: 8 code:0x0038 */
+static GUI_CONST_STORAGE unsigned char ac0038[48] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ___XXXXX,XX______,
+ __XXX___,XXX_____,
+ _XXX____,_XXX____,
+ _XXX____,_XXX____,
+ _XXX____,_XXX____,
+ __XXX___,_XX_____,
+ __XXXX__,XXX_____,
+ ____XXXX,X_______,
+ ___XX_XX,XX______,
+ __XXX___,XXX_____,
+ _XXX____,_XXX____,
+ _XXX____,_XXX____,
+ _XXX____,_XXX____,
+ _XXX____,_XXX____,
+ __XXX___,XXX_____,
+ ____XXXX,XX______,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: 9 code:0x0039 */
+static GUI_CONST_STORAGE unsigned char ac0039[48] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ____XXXX,X_______,
+ __XXX___,XX______,
+ __XXX___,XXX_____,
+ _XXX____,_XX_____,
+ _XXX____,_XXX____,
+ _XXX____,_XXX____,
+ _XXX____,_XXX____,
+ _XXX____,XXXX____,
+ __XXX__X,XXXX____,
+ ___XXXXX,_XXX____,
+ ________,_XXX____,
+ ________,XXX_____,
+ ________,XXX_____,
+ __XXX___,XX______,
+ __XXX__X,XX______,
+ ___XXXXX,________,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: : code:0x003A */
+static GUI_CONST_STORAGE unsigned char ac003A[48] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ _____XXX,X_______,
+ _____XXX,X_______,
+ _____XXX,X_______,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ _____XXX,X_______,
+ _____XXX,X_______,
+ _____XXX,X_______,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: ; code:0x003B */
+static GUI_CONST_STORAGE unsigned char ac003B[48] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ _____XXX,________,
+ _____XXX,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ _____XXX,________,
+ _____XXX,________,
+ ______XX,________,
+ _____XX_,________,
+ _____XX_,________
+};
+
+/* char: < code:0x003C */
+static GUI_CONST_STORAGE unsigned char ac003C[48] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,__XX____,
+ ________,_XX_____,
+ ________,XX______,
+ _______X,X_______,
+ ______XX,________,
+ _____XX_,________,
+ ____XX__,________,
+ ___XX___,________,
+ __XX____,________,
+ ___XX___,________,
+ ____XX__,________,
+ _____XX_,________,
+ ______XX,________,
+ _______X,X_______,
+ ________,XX______,
+ ________,_XX_____,
+ ________,__XX____,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: = code:0x003D */
+static GUI_CONST_STORAGE unsigned char ac003D[48] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ _XXXXXXX,XXXX____,
+ ________,________,
+ ________,________,
+ ________,________,
+ _XXXXXXX,XXXX____,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: > code:0x003E */
+static GUI_CONST_STORAGE unsigned char ac003E[48] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ __XX____,________,
+ ___XX___,________,
+ ____XX__,________,
+ _____XX_,________,
+ ______XX,________,
+ _______X,X_______,
+ ________,XX______,
+ ________,_XX_____,
+ ________,__XX____,
+ ________,_XX_____,
+ ________,XX______,
+ _______X,X_______,
+ ______XX,________,
+ _____XX_,________,
+ ____XX__,________,
+ ___XX___,________,
+ __XX____,________,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: ? code:0x003F */
+static GUI_CONST_STORAGE unsigned char ac003F[48] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ _____XXX,XXX_____,
+ ___XXX__,_XXX____,
+ __XX____,__XXX___,
+ __XX____,__XXX___,
+ __XXX___,__XXX___,
+ __XXX___,__XXX___,
+ ________,XXXX____,
+ _______X,XX______,
+ ______XX,________,
+ ______XX,________,
+ ______XX,________,
+ ________,________,
+ ________,________,
+ _____XXX,X_______,
+ _____XXX,X_______,
+ _____XXX,X_______,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: @ code:0x0040 */
+static GUI_CONST_STORAGE unsigned char ac0040[48] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ _____XXX,X_______,
+ ___XXX__,XXX_____,
+ __XXX___,_XX_____,
+ __XXX_XX,XXXX____,
+ __XX_XXX,XXXX____,
+ _XXX_XXX,XXXX____,
+ _XXX_XXX,XXXX____,
+ _XXXXXXX,X_XX____,
+ _XXXXXXX,X_XX____,
+ _XXXXXXX,X_XX____,
+ _XXXXXXX,X_XX____,
+ _XXXXXXX,XXX_____,
+ __XX_XXX,XX______,
+ __XXX___,__XX____,
+ __XXX___,_XX_____,
+ ___XXX__,XXX_____,
+ ____XXXX,X_______,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: A code:0x0041 */
+static GUI_CONST_STORAGE unsigned char ac0041[48] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ _____XXX,________,
+ _____XXX,________,
+ ____XXXX,________,
+ ____XXXX,X_______,
+ ____XX_X,X_______,
+ ____XX_X,X_______,
+ ___XX__X,X_______,
+ ___XX__X,XX______,
+ ___XX___,XX______,
+ ___XXXXX,XX______,
+ __XX____,XXX_____,
+ __XX____,XXX_____,
+ __XX____,_XX_____,
+ _XX_____,_XX_____,
+ _XX_____,_XXX____,
+ XXXXX___,XXXXX___,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: B code:0x0042 */
+static GUI_CONST_STORAGE unsigned char ac0042[48] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ _XXXXXXX,X_______,
+ __XXX__X,XXX_____,
+ __XXX___,XXX_____,
+ __XXX___,XXX_____,
+ __XXX___,XXX_____,
+ __XXX___,XXX_____,
+ __XXX__X,XX______,
+ __XXXXXX,X_______,
+ __XXX___,XXX_____,
+ __XXX___,_XX_____,
+ __XXX___,_XXX____,
+ __XXX___,_XXX____,
+ __XXX___,_XXX____,
+ __XXX___,_XXX____,
+ __XXX___,XXX_____,
+ _XXXXXXX,XX______,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: C code:0x0043 */
+static GUI_CONST_STORAGE unsigned char ac0043[48] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ _____XXX,XXX_____,
+ ___XXX__,XXX_____,
+ __XXX___,_XXX____,
+ __XXX___,__XX____,
+ __XX____,__XX____,
+ _XXX____,________,
+ _XXX____,________,
+ _XXX____,________,
+ _XXX____,________,
+ _XXX____,________,
+ _XXX____,________,
+ _XXX____,__XX____,
+ __XXX___,__XX____,
+ __XXX___,_XX_____,
+ ___XXX__,XXX_____,
+ ____XXXX,X_______,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: D code:0x0044 */
+static GUI_CONST_STORAGE unsigned char ac0044[48] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ XXXXXXXX,________,
+ __XXX__X,XX______,
+ __XXX___,XXX_____,
+ __XXX___,XXX_____,
+ __XXX___,_XXX____,
+ __XXX___,_XXX____,
+ __XXX___,_XXX____,
+ __XXX___,_XXX____,
+ __XXX___,_XXX____,
+ __XXX___,_XXX____,
+ __XXX___,_XXX____,
+ __XXX___,_XXX____,
+ __XXX___,XXX_____,
+ __XXX___,XXX_____,
+ __XXX__X,XX______,
+ XXXXXXXX,________,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: E code:0x0045 */
+static GUI_CONST_STORAGE unsigned char ac0045[48] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ XXXXXXXX,XXX_____,
+ _XXX____,XXX_____,
+ _XXX____,__XX____,
+ _XXX____,__XX____,
+ _XXX____,________,
+ _XXX___X,X_______,
+ _XXX___X,X_______,
+ _XXXXXXX,X_______,
+ _XXX___X,X_______,
+ _XXX___X,X_______,
+ _XXX___X,X_______,
+ _XXX____,________,
+ _XXX____,__XX____,
+ _XXX____,__XX____,
+ _XXX____,_XX_____,
+ XXXXXXXX,XXX_____,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: F code:0x0046 */
+static GUI_CONST_STORAGE unsigned char ac0046[48] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ XXXXXXXX,XXX_____,
+ _XXX____,XXX_____,
+ _XXX____,__XX____,
+ _XXX____,__XX____,
+ _XXX____,________,
+ _XXX___X,X_______,
+ _XXX___X,X_______,
+ _XXXXXXX,X_______,
+ _XXX___X,X_______,
+ _XXX___X,X_______,
+ _XXX___X,X_______,
+ _XXX____,________,
+ _XXX____,________,
+ _XXX____,________,
+ _XXX____,________,
+ XXXXXX__,________,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: G code:0x0047 */
+static GUI_CONST_STORAGE unsigned char ac0047[48] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ____XXXX,X_______,
+ ___XXX__,XX______,
+ __XXX___,_XX_____,
+ __XXX___,_XX_____,
+ __XX____,_XX_____,
+ _XXX____,________,
+ _XXX____,________,
+ _XXX____,________,
+ _XXX____,________,
+ _XXX__XX,XXXXX___,
+ _XXX____,XXX_____,
+ _XXX____,XXX_____,
+ __XXX___,XXX_____,
+ __XXX___,XXX_____,
+ ___XXX__,XXX_____,
+ ____XXXX,X_______,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: H code:0x0048 */
+static GUI_CONST_STORAGE unsigned char ac0048[48] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ XXXXX___,XXXXX___,
+ _XXX____,_XXX____,
+ _XXX____,_XXX____,
+ _XXX____,_XXX____,
+ _XXX____,_XXX____,
+ _XXX____,_XXX____,
+ _XXX____,_XXX____,
+ _XXXXXXX,XXXX____,
+ _XXX____,_XXX____,
+ _XXX____,_XXX____,
+ _XXX____,_XXX____,
+ _XXX____,_XXX____,
+ _XXX____,_XXX____,
+ _XXX____,_XXX____,
+ _XXX____,_XXX____,
+ XXXXX___,XXXXX___,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: I code:0x0049 */
+static GUI_CONST_STORAGE unsigned char ac0049[48] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ __XXXXXX,XXX_____,
+ _____XXX,________,
+ _____XXX,________,
+ _____XXX,________,
+ _____XXX,________,
+ _____XXX,________,
+ _____XXX,________,
+ _____XXX,________,
+ _____XXX,________,
+ _____XXX,________,
+ _____XXX,________,
+ _____XXX,________,
+ _____XXX,________,
+ _____XXX,________,
+ _____XXX,________,
+ __XXXXXX,XXX_____,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: J code:0x004A */
+static GUI_CONST_STORAGE unsigned char ac004A[48] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ___XXXXX,XXXX____,
+ ______XX,X_______,
+ ______XX,X_______,
+ ______XX,X_______,
+ ______XX,X_______,
+ ______XX,X_______,
+ ______XX,X_______,
+ ______XX,X_______,
+ ______XX,X_______,
+ ______XX,X_______,
+ ______XX,X_______,
+ ______XX,X_______,
+ ______XX,X_______,
+ ______XX,X_______,
+ ______XX,X_______,
+ ______XX,X_______,
+ _XXX__XX,X_______,
+ _XXX_XXX,________,
+ __XXXXX_,________
+};
+
+/* char: K code:0x004B */
+static GUI_CONST_STORAGE unsigned char ac004B[48] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ XXXXX_XX,XXX_____,
+ _XXX___X,XX______,
+ _XXX__XX,X_______,
+ _XXX__XX,________,
+ _XXX_XX_,________,
+ _XXXXX__,________,
+ _XXXXXX_,________,
+ _XXXXXX_,________,
+ _XXXXXXX,________,
+ _XXX__XX,________,
+ _XXX__XX,X_______,
+ _XXX___X,X_______,
+ _XXX___X,XX______,
+ _XXX____,XX______,
+ _XXX____,XXX_____,
+ XXXXX__X,XXXX____,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: L code:0x004C */
+static GUI_CONST_STORAGE unsigned char ac004C[48] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ XXXXXX__,________,
+ _XXX____,________,
+ _XXX____,________,
+ _XXX____,________,
+ _XXX____,________,
+ _XXX____,________,
+ _XXX____,________,
+ _XXX____,________,
+ _XXX____,________,
+ _XXX____,________,
+ _XXX____,________,
+ _XXX____,________,
+ _XXX____,__XX____,
+ _XXX____,__XX____,
+ _XXX____,_XX_____,
+ XXXXXXXX,XXX_____,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: M code:0x004D */
+static GUI_CONST_STORAGE unsigned char ac004D[48] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ XXXX____,XXXX____,
+ _XXX___X,XXX_____,
+ _XXX___X,XXX_____,
+ _XXXX__X,XXX_____,
+ _XXXX__X,XXX_____,
+ _XXXX_XX,XXX_____,
+ _XXXX_XX,XXX_____,
+ _XXXX_XX,XXX_____,
+ _XXXXXXX,XXX_____,
+ _XXXXXXX,XXX_____,
+ _XXXXXX_,XXX_____,
+ _XX_XXX_,XXX_____,
+ _XX_XXX_,XXX_____,
+ _XX_XXX_,XXX_____,
+ _XX_XX__,XXX_____,
+ XXXX___X,XXXX____,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: N code:0x004E */
+static GUI_CONST_STORAGE unsigned char ac004E[48] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ _XXXX__X,XXXXX___,
+ __XXX___,_XX_____,
+ __XXXX__,_XX_____,
+ __XXXX__,_XX_____,
+ __XXXXX_,_XX_____,
+ __XXXXX_,_XX_____,
+ __XX_XXX,_XX_____,
+ __XX_XXX,_XX_____,
+ __XX__XX,_XX_____,
+ __XX__XX,XXX_____,
+ __XX___X,XXX_____,
+ __XX___X,XXX_____,
+ __XX___X,XXX_____,
+ __XX____,XXX_____,
+ __XX____,XXX_____,
+ XXXXXX__,_XX_____,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: O code:0x004F */
+static GUI_CONST_STORAGE unsigned char ac004F[48] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ____XXXX,X_______,
+ ___XXX_X,XX______,
+ __XXX___,XXX_____,
+ __XXX___,_XX_____,
+ _XXX____,_XXX____,
+ _XXX____,_XXX____,
+ _XXX____,_XXX____,
+ _XXX____,_XXX____,
+ _XXX____,_XXX____,
+ _XXX____,_XXX____,
+ _XXX____,_XXX____,
+ _XXX____,_XXX____,
+ __XXX___,_XX_____,
+ __XXX___,XXX_____,
+ ___XXX_X,XX______,
+ ____XXXX,X_______,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: P code:0x0050 */
+static GUI_CONST_STORAGE unsigned char ac0050[48] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ XXXXXXXX,X_______,
+ _XXX____,XXX_____,
+ _XXX____,_XXX____,
+ _XXX____,_XXX____,
+ _XXX____,_XXX____,
+ _XXX____,_XXX____,
+ _XXX____,_XXX____,
+ _XXX___X,XXX_____,
+ _XXXXXXX,X_______,
+ _XXX____,________,
+ _XXX____,________,
+ _XXX____,________,
+ _XXX____,________,
+ _XXX____,________,
+ _XXX____,________,
+ XXXXXX__,________,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: Q code:0x0051 */
+static GUI_CONST_STORAGE unsigned char ac0051[48] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ____XXXX,X_______,
+ ___XXX_X,XX______,
+ __XXX___,XXX_____,
+ __XXX___,_XX_____,
+ _XXX____,_XXX____,
+ _XXX____,_XXX____,
+ _XXX____,_XXX____,
+ _XXX____,_XXX____,
+ _XXX____,_XXX____,
+ _XXX____,_XXX____,
+ _XXX____,_XXX____,
+ _XXXXXXX,_XXX____,
+ __XXX_XX,_XX_____,
+ __XXX_XX,XXX_____,
+ ___XXX_X,XX______,
+ ____XXXX,X_______,
+ _______X,XXXX____,
+ ________,XXX_____,
+ ________,________
+};
+
+/* char: R code:0x0052 */
+static GUI_CONST_STORAGE unsigned char ac0052[48] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ XXXXXXXX,XX______,
+ _XXX____,XXX_____,
+ _XXX____,_XXX____,
+ _XXX____,_XXX____,
+ _XXX____,_XXX____,
+ _XXX____,_XXX____,
+ _XXX____,XXX_____,
+ _XXXXXXX,X_______,
+ _XXX__XX,________,
+ _XXX__XX,X_______,
+ _XXX___X,X_______,
+ _XXX___X,XX______,
+ _XXX____,XXX_____,
+ _XXX____,XXX_____,
+ _XXX____,_XXX____,
+ XXXXX___,_XXXX___,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: S code:0x0053 */
+static GUI_CONST_STORAGE unsigned char ac0053[48] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ___XXXXX,XXX_____,
+ __XXX___,XXX_____,
+ _XXX____,_XX_____,
+ _XXX____,_XX_____,
+ _XXX____,________,
+ _XXXX___,________,
+ __XXXXX_,________,
+ ___XXXXX,X_______,
+ _____XXX,XXX_____,
+ _______X,XXX_____,
+ ________,XXXX____,
+ _XX_____,_XXX____,
+ _XX_____,_XXX____,
+ _XXX____,_XXX____,
+ __XXX___,XXX_____,
+ ____XXXX,XX______,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: T code:0x0054 */
+static GUI_CONST_STORAGE unsigned char ac0054[48] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ _XXXXXXX,XXXX____,
+ _XX__XXX,__XX____,
+ XX___XXX,___XX___,
+ XX___XXX,___XX___,
+ _____XXX,________,
+ _____XXX,________,
+ _____XXX,________,
+ _____XXX,________,
+ _____XXX,________,
+ _____XXX,________,
+ _____XXX,________,
+ _____XXX,________,
+ _____XXX,________,
+ _____XXX,________,
+ _____XXX,________,
+ ___XXXXX,XX______,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: U code:0x0055 */
+static GUI_CONST_STORAGE unsigned char ac0055[48] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ _XXXXX__,XXXX____,
+ __XXX___,_XX_____,
+ __XXX___,_XX_____,
+ __XXX___,_XX_____,
+ __XXX___,_XX_____,
+ __XXX___,_XX_____,
+ __XXX___,_XX_____,
+ __XXX___,_XX_____,
+ __XXX___,_XX_____,
+ __XXX___,_XX_____,
+ __XXX___,_XX_____,
+ __XXX___,_XX_____,
+ __XXX___,_XX_____,
+ __XXX___,_XX_____,
+ ___XXX__,XX______,
+ ____XXXX,X_______,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: V code:0x0056 */
+static GUI_CONST_STORAGE unsigned char ac0056[48] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ XXXXX___,XXXX____,
+ _XXX____,_XX_____,
+ __XX____,XX______,
+ __XX____,XX______,
+ __XXX___,XX______,
+ __XXX___,XX______,
+ ___XX__X,X_______,
+ ___XX__X,X_______,
+ ___XXX_X,X_______,
+ ___XXX_X,X_______,
+ ____XXXX,________,
+ ____XXXX,________,
+ ____XXXX,________,
+ ____XXX_,________,
+ _____XX_,________,
+ _____XX_,________,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: W code:0x0057 */
+static GUI_CONST_STORAGE unsigned char ac0057[48] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ XXXXXXXX,XXXXX___,
+ _XX__XXX,__XX____,
+ _XX___XX,__XX____,
+ _XXX__XX,__XX____,
+ _XXX__XX,__XX____,
+ __XX_XXX,_XX_____,
+ __XX_XXX,_XX_____,
+ __XX_XXX,XXX_____,
+ __XX_XXX,XXX_____,
+ __XXXX_X,XXX_____,
+ __XXXX_X,XX______,
+ ___XXX_X,XX______,
+ ___XXX_X,XX______,
+ ___XX__X,XX______,
+ ___XX__X,X_______,
+ ___XX__X,X_______,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: X code:0x0058 */
+static GUI_CONST_STORAGE unsigned char ac0058[48] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ _XXXXX_X,XXXX____,
+ __XXX___,XX______,
+ ___XX___,XX______,
+ ___XXX__,XX______,
+ ____XX_X,X_______,
+ ____XXXX,X_______,
+ _____XXX,________,
+ _____XX_,________,
+ _____XXX,________,
+ _____XXX,________,
+ ____XXXX,X_______,
+ ____XX_X,X_______,
+ ___XX__X,XX______,
+ ___XX___,XX______,
+ __XX____,XXX_____,
+ _XXXX__X,XXXX____,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: Y code:0x0059 */
+static GUI_CONST_STORAGE unsigned char ac0059[48] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ XXXXX___,XXXXX___,
+ _XXX____,__XX____,
+ __XX____,_XX_____,
+ __XXX___,_XX_____,
+ ___XX___,XX______,
+ ___XXX__,XX______,
+ ___XXXXX,X_______,
+ ____XXXX,X_______,
+ ____XXXX,________,
+ _____XXX,________,
+ _____XXX,________,
+ _____XXX,________,
+ _____XXX,________,
+ _____XXX,________,
+ _____XXX,________,
+ ___XXXXX,XX______,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: Z code:0x005A */
+static GUI_CONST_STORAGE unsigned char ac005A[48] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ __XXXXXX,XXXX____,
+ __XXX___,_XX_____,
+ _XXX____,XXX_____,
+ _XX_____,XX______,
+ _______X,XX______,
+ _______X,X_______,
+ ______XX,________,
+ ______XX,________,
+ _____XX_,________,
+ _____XX_,________,
+ ____XX__,________,
+ ___XXX__,________,
+ ___XX___,__XX____,
+ __XXX___,__XX____,
+ __XX____,_XX_____,
+ _XXXXXXX,XXX_____,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: [ code:0x005B */
+static GUI_CONST_STORAGE unsigned char ac005B[48] = {
+ ________,________,
+ ________,________,
+ _____XXX,XXX_____,
+ _____XX_,________,
+ _____XX_,________,
+ _____XX_,________,
+ _____XX_,________,
+ _____XX_,________,
+ _____XX_,________,
+ _____XX_,________,
+ _____XX_,________,
+ _____XX_,________,
+ _____XX_,________,
+ _____XX_,________,
+ _____XX_,________,
+ _____XX_,________,
+ _____XX_,________,
+ _____XX_,________,
+ _____XX_,________,
+ _____XX_,________,
+ _____XX_,________,
+ _____XX_,________,
+ _____XXX,XXX_____,
+ ________,________
+};
+
+/* char: \ code:0x005C */
+static GUI_CONST_STORAGE unsigned char ac005C[48] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ __XX____,________,
+ __XX____,________,
+ ___XX___,________,
+ ___XX___,________,
+ ____XX__,________,
+ ____XX__,________,
+ ____XX__,________,
+ _____XX_,________,
+ _____XX_,________,
+ ______XX,________,
+ ______XX,________,
+ ______XX,X_______,
+ _______X,X_______,
+ _______X,X_______,
+ ________,XX______,
+ ________,XX______,
+ ________,_XX_____,
+ ________,_XX_____,
+ ________,_XX_____,
+ ________,__XX____
+};
+
+/* char: ] code:0x005D */
+static GUI_CONST_STORAGE unsigned char ac005D[48] = {
+ ________,________,
+ ________,________,
+ __XXXXXX,________,
+ ______XX,________,
+ ______XX,________,
+ ______XX,________,
+ ______XX,________,
+ ______XX,________,
+ ______XX,________,
+ ______XX,________,
+ ______XX,________,
+ ______XX,________,
+ ______XX,________,
+ ______XX,________,
+ ______XX,________,
+ ______XX,________,
+ ______XX,________,
+ ______XX,________,
+ ______XX,________,
+ ______XX,________,
+ ______XX,________,
+ ______XX,________,
+ __XXXXXX,________,
+ ________,________
+};
+
+/* char: ^ code:0x005E */
+static GUI_CONST_STORAGE unsigned char ac005E[48] = {
+ ________,________,
+ _____XXX,________,
+ ____XX_X,X_______,
+ ___XX___,XX______,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: _ code:0x005F */
+static GUI_CONST_STORAGE unsigned char ac005F[48] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ XXXXXXXX,XXXXX___
+};
+
+/* char: ` code:0x0060 */
+static GUI_CONST_STORAGE unsigned char ac0060[48] = {
+ ________,________,
+ ________,________,
+ ___XXX__,________,
+ _____XXX,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: a code:0x0061 */
+static GUI_CONST_STORAGE unsigned char ac0061[48] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ____XXXX,XX______,
+ __XXX___,XXX_____,
+ __XXX___,XXX_____,
+ ________,XXX_____,
+ _____XXX,XXX_____,
+ __XXXX__,XXX_____,
+ _XXXX___,XXX_____,
+ _XXX____,XXX_____,
+ _XXX____,XXX_____,
+ _XXXX__X,XXXXX___,
+ __XXXXXX,_XXXX___,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: b code:0x0062 */
+static GUI_CONST_STORAGE unsigned char ac0062[48] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ___XX___,________,
+ _XXXX___,________,
+ __XXX___,________,
+ __XXX___,________,
+ __XXX___,________,
+ __XXX___,________,
+ __XXX_XX,XX______,
+ __XXXXX_,XXX_____,
+ __XXXX__,_XXX____,
+ __XXX___,_XXX____,
+ __XXX___,_XXX____,
+ __XXX___,_XXX____,
+ __XXX___,_XXX____,
+ __XXX___,_XXX____,
+ __XXX___,_XX_____,
+ __XXXX__,XXX_____,
+ __XX_XXX,XX______,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: c code:0x0063 */
+static GUI_CONST_STORAGE unsigned char ac0063[48] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ____XXXX,X_______,
+ __XXX__X,XX______,
+ __XXX__X,XX______,
+ _XXX___X,XX______,
+ _XXX____,________,
+ _XXX____,________,
+ _XXX____,________,
+ _XXX____,_XX_____,
+ __XXX___,_XX_____,
+ __XXX___,XX______,
+ ____XXXX,X_______,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: d code:0x0064 */
+static GUI_CONST_STORAGE unsigned char ac0064[48] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,_XX_____,
+ ______XX,XXX_____,
+ ________,XXX_____,
+ ________,XXX_____,
+ ________,XXX_____,
+ ________,XXX_____,
+ ___XXXXX,XXX_____,
+ __XXX__X,XXX_____,
+ __XXX___,XXX_____,
+ _XXX____,XXX_____,
+ _XXX____,XXX_____,
+ _XXX____,XXX_____,
+ _XXX____,XXX_____,
+ _XXX____,XXX_____,
+ __XX____,XXX_____,
+ __XXX__X,XXXX____,
+ ___XXXXX,XX______,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: e code:0x0065 */
+static GUI_CONST_STORAGE unsigned char ac0065[48] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ _____XXX,XX______,
+ ___XXX__,XXX_____,
+ ___XX___,_XX_____,
+ __XXX___,_XXX____,
+ __XXX___,_XXX____,
+ __XXXXXX,XXXX____,
+ __XXX___,________,
+ __XXX___,________,
+ ___XXX__,__XX____,
+ ___XXX__,_XX_____,
+ _____XXX,XX______,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: f code:0x0066 */
+static GUI_CONST_STORAGE unsigned char ac0066[48] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ______XX,XXX_____,
+ _____XXX,_XXX____,
+ ____XXX_,_XXX____,
+ ____XXX_,________,
+ ____XXX_,________,
+ _XXXXXXX,XX______,
+ ____XXX_,________,
+ ____XXX_,________,
+ ____XXX_,________,
+ ____XXX_,________,
+ ____XXX_,________,
+ ____XXX_,________,
+ ____XXX_,________,
+ ____XXX_,________,
+ ____XXX_,________,
+ __XXXXXX,XX______,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: g code:0x0067 */
+static GUI_CONST_STORAGE unsigned char ac0067[48] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ____XXXX,XXXX____,
+ ___XXXXX,XXXX____,
+ __XXX__X,XX______,
+ __XXX__X,XX______,
+ __XXX__X,XX______,
+ ___XXX_X,XX______,
+ ___XXXXX,X_______,
+ __XXX___,________,
+ __XXXXXX,X_______,
+ __XXX_XX,XXX_____,
+ _XXX____,XXX_____,
+ _XXX____,XXX_____,
+ _XXXX__X,XXX_____,
+ ___XXXXX,X_______
+};
+
+/* char: h code:0x0068 */
+static GUI_CONST_STORAGE unsigned char ac0068[48] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ___XX___,________,
+ _XXXX___,________,
+ __XXX___,________,
+ __XXX___,________,
+ __XXX___,________,
+ __XXX___,________,
+ __XXXXXX,XX______,
+ __XXXX__,XXX_____,
+ __XXX___,XXX_____,
+ __XXX___,XXX_____,
+ __XXX___,XXX_____,
+ __XXX___,XXX_____,
+ __XXX___,XXX_____,
+ __XXX___,XXX_____,
+ __XXX___,XXX_____,
+ __XXX___,XXX_____,
+ _XXXXX_X,XXXX____,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: i code:0x0069 */
+static GUI_CONST_STORAGE unsigned char ac0069[48] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ _____XXX,________,
+ _____XXX,________,
+ ________,________,
+ ________,________,
+ ______XX,________,
+ __XXXXXX,________,
+ _____XXX,________,
+ _____XXX,________,
+ _____XXX,________,
+ _____XXX,________,
+ _____XXX,________,
+ _____XXX,________,
+ _____XXX,________,
+ _____XXX,________,
+ _____XXX,________,
+ __XXXXXX,XXX_____,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: j code:0x006A */
+static GUI_CONST_STORAGE unsigned char ac006A[48] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ______XX,XX______,
+ ______XX,XX______,
+ ________,________,
+ ________,________,
+ ________,XX______,
+ ____XXXX,XX______,
+ _______X,XX______,
+ _______X,XX______,
+ _______X,XX______,
+ _______X,XX______,
+ _______X,XX______,
+ _______X,XX______,
+ _______X,XX______,
+ _______X,XX______,
+ _______X,XX______,
+ _______X,XX______,
+ _______X,XX______,
+ __XXX_XX,X_______,
+ __XXXXXX,________
+};
+
+/* char: k code:0x006B */
+static GUI_CONST_STORAGE unsigned char ac006B[48] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ___XX___,________,
+ _XXXX___,________,
+ __XXX___,________,
+ __XXX___,________,
+ __XXX___,________,
+ __XXX___,________,
+ __XXX__X,XXX_____,
+ __XXX__X,X_______,
+ __XXX__X,X_______,
+ __XXX_XX,________,
+ __XXXXXX,________,
+ __XXXXXX,________,
+ __XXX__X,X_______,
+ __XXX__X,XX______,
+ __XXX___,XX______,
+ __XXX___,XXX_____,
+ _XXXXX_X,XXXX____,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: l code:0x006C */
+static GUI_CONST_STORAGE unsigned char ac006C[48] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ______XX,________,
+ __XXXXXX,________,
+ _____XXX,________,
+ _____XXX,________,
+ _____XXX,________,
+ _____XXX,________,
+ _____XXX,________,
+ _____XXX,________,
+ _____XXX,________,
+ _____XXX,________,
+ _____XXX,________,
+ _____XXX,________,
+ _____XXX,________,
+ _____XXX,________,
+ _____XXX,________,
+ _____XXX,________,
+ __XXXXXX,XXX_____,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: m code:0x006D */
+static GUI_CONST_STORAGE unsigned char ac006D[48] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ XXXXXXX_,XXXX____,
+ _XXXXXXX,XXXX____,
+ _XXX_XXX,_XXX____,
+ _XXX_XXX,_XXX____,
+ _XXX_XXX,_XXX____,
+ _XXX_XXX,_XXX____,
+ _XXX_XXX,_XXX____,
+ _XXX_XXX,_XXX____,
+ _XXX_XXX,_XXX____,
+ _XXX_XXX,_XXX____,
+ XXXXXXXX,XXXXX___,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: n code:0x006E */
+static GUI_CONST_STORAGE unsigned char ac006E[48] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ _XXXXXXX,XX______,
+ __XXXX__,XXX_____,
+ __XXX___,XXX_____,
+ __XXX___,XXX_____,
+ __XXX___,XXX_____,
+ __XXX___,XXX_____,
+ __XXX___,XXX_____,
+ __XXX___,XXX_____,
+ __XXX___,XXX_____,
+ __XXX___,XXX_____,
+ _XXXXX_X,XXXX____,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: o code:0x006F */
+static GUI_CONST_STORAGE unsigned char ac006F[48] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ____XXXX,X_______,
+ ___XXX_X,XX______,
+ __XXX___,XXX_____,
+ _XXX____,_XXX____,
+ _XXX____,_XXX____,
+ _XXX____,_XXX____,
+ _XXX____,_XXX____,
+ _XXX____,_XXX____,
+ __XXX___,XXX_____,
+ __XXX___,XXX_____,
+ ____XXXX,X_______,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: p code:0x0070 */
+static GUI_CONST_STORAGE unsigned char ac0070[48] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ _XXXXXXX,XX______,
+ __XXXX__,XXX_____,
+ __XXX___,_XXX____,
+ __XXX___,_XXX____,
+ __XXX___,_XXX____,
+ __XXX___,_XXX____,
+ __XXX___,_XXX____,
+ __XXX___,_XXX____,
+ __XXX___,XXX_____,
+ __XXXX__,XXX_____,
+ __XXXXXX,XX______,
+ __XXX___,________,
+ __XXX___,________,
+ _XXXXXX_,________
+};
+
+/* char: q code:0x0071 */
+static GUI_CONST_STORAGE unsigned char ac0071[48] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ___XXXXX,_XX_____,
+ __XXX__X,XXX_____,
+ __XXX___,XXX_____,
+ _XXX____,XXX_____,
+ _XXX____,XXX_____,
+ _XXX____,XXX_____,
+ _XXX____,XXX_____,
+ _XXX____,XXX_____,
+ __XX____,XXX_____,
+ __XXX__X,XXX_____,
+ ___XXXXX,XXX_____,
+ ________,XXX_____,
+ ________,XXX_____,
+ ______XX,XXXX____
+};
+
+/* char: r code:0x0072 */
+static GUI_CONST_STORAGE unsigned char ac0072[48] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ XXXXXX_X,XXX_____,
+ ___XXXXX,_XXX____,
+ ___XXXX_,_XXX____,
+ ___XXX__,________,
+ ___XXX__,________,
+ ___XXX__,________,
+ ___XXX__,________,
+ ___XXX__,________,
+ ___XXX__,________,
+ ___XXX__,________,
+ XXXXXXXX,X_______,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: s code:0x0073 */
+static GUI_CONST_STORAGE unsigned char ac0073[48] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ____XXXX,XXX_____,
+ __XXXX__,XXX_____,
+ __XXX___,_XX_____,
+ __XXX___,_XX_____,
+ ___XXXX_,________,
+ ____XXXX,X_______,
+ ______XX,XXX_____,
+ __XX____,XXX_____,
+ __XX____,XXX_____,
+ __XXX__X,XXX_____,
+ __XXXXXX,XX______,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: t code:0x0074 */
+static GUI_CONST_STORAGE unsigned char ac0074[48] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ _____XX_,________,
+ _____XX_,________,
+ ____XXX_,________,
+ ____XXX_,________,
+ _XXXXXXX,XX______,
+ ____XXX_,________,
+ ____XXX_,________,
+ ____XXX_,________,
+ ____XXX_,________,
+ ____XXX_,________,
+ ____XXX_,________,
+ ____XXX_,________,
+ ____XXX_,_XX_____,
+ ____XXX_,_XX_____,
+ _____XXX,XX______,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: u code:0x0075 */
+static GUI_CONST_STORAGE unsigned char ac0075[48] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ___XX___,_XX_____,
+ _XXXX__X,XXX_____,
+ __XXX___,XXX_____,
+ __XXX___,XXX_____,
+ __XXX___,XXX_____,
+ __XXX___,XXX_____,
+ __XXX___,XXX_____,
+ __XXX___,XXX_____,
+ __XXX___,XXX_____,
+ __XXX___,XXX_____,
+ __XXXX_X,XXXX____,
+ ___XXXXX,XX______,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: v code:0x0076 */
+static GUI_CONST_STORAGE unsigned char ac0076[48] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ _XXXXX__,XXXX____,
+ __XXX___,_XX_____,
+ ___XX___,XX______,
+ ___XX___,XX______,
+ ___XXX__,XX______,
+ ____XX_X,X_______,
+ ____XXXX,X_______,
+ ____XXXX,X_______,
+ _____XXX,________,
+ _____XXX,________,
+ _____XX_,________,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: w code:0x0077 */
+static GUI_CONST_STORAGE unsigned char ac0077[48] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ XXXXXXXX,XXXXX___,
+ _XX__XXX,__XX____,
+ _XXX__XX,__XX____,
+ __XX_XXX,_XX_____,
+ __XX_XXX,_XX_____,
+ __XXXXXX,XXX_____,
+ __XXXX_X,XX______,
+ ___XXX_X,XX______,
+ ___XXX_X,XX______,
+ ___XXX_X,XX______,
+ ___XX___,________,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: x code:0x0078 */
+static GUI_CONST_STORAGE unsigned char ac0078[48] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ __XXXXXX,XXXX____,
+ ___XXX__,XX______,
+ ____XX__,XX______,
+ ____XXXX,X_______,
+ _____XXX,________,
+ _____XXX,________,
+ _____XXX,X_______,
+ ____XX_X,X_______,
+ ___XX___,XX______,
+ ___XX___,XXX_____,
+ _XXXXX_X,XXXX____,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: y code:0x0079 */
+static GUI_CONST_STORAGE unsigned char ac0079[48] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ _XXXXX_X,XXXX____,
+ ___XX___,XX______,
+ ___XX___,XX______,
+ ___XX___,XX______,
+ ____XX_X,X_______,
+ ____XX_X,X_______,
+ ____XXXX,X_______,
+ _____XXX,________,
+ _____XXX,________,
+ _____XXX,________,
+ _____XX_,________,
+ _____XX_,________,
+ __XX_XX_,________,
+ __XXXX__,________
+};
+
+/* char: z code:0x007A */
+static GUI_CONST_STORAGE unsigned char ac007A[48] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ __XXXXXX,XX______,
+ __XX___X,XX______,
+ __XX__XX,X_______,
+ __XX__XX,________,
+ _____XXX,________,
+ _____XX_,________,
+ ____XXX_,________,
+ ___XXX__,_XX_____,
+ ___XX___,_XX_____,
+ __XXX___,XXX_____,
+ __XXXXXX,XX______,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: { code:0x007B */
+static GUI_CONST_STORAGE unsigned char ac007B[48] = {
+ ________,________,
+ ________,________,
+ ________,XXX_____,
+ _______X,X_______,
+ _______X,X_______,
+ _______X,X_______,
+ _______X,X_______,
+ _______X,X_______,
+ _______X,X_______,
+ _______X,X_______,
+ _______X,X_______,
+ ______XX,________,
+ _____XX_,________,
+ ______XX,________,
+ _______X,X_______,
+ _______X,X_______,
+ _______X,X_______,
+ _______X,X_______,
+ _______X,X_______,
+ _______X,X_______,
+ _______X,X_______,
+ _______X,X_______,
+ ________,XXX_____,
+ ________,________
+};
+
+/* char: | code:0x007C */
+static GUI_CONST_STORAGE unsigned char ac007C[48] = {
+ ______XX,________,
+ ______XX,________,
+ ______XX,________,
+ ______XX,________,
+ ______XX,________,
+ ______XX,________,
+ ______XX,________,
+ ______XX,________,
+ ______XX,________,
+ ______XX,________,
+ ______XX,________,
+ ______XX,________,
+ ______XX,________,
+ ______XX,________,
+ ______XX,________,
+ ______XX,________,
+ ______XX,________,
+ ______XX,________,
+ ______XX,________,
+ ______XX,________,
+ ______XX,________,
+ ______XX,________,
+ ______XX,________,
+ ______XX,________
+};
+
+/* char: } code:0x007D */
+static GUI_CONST_STORAGE unsigned char ac007D[48] = {
+ ________,________,
+ ________,________,
+ __XXX___,________,
+ ____XX__,________,
+ ____XX__,________,
+ ____XX__,________,
+ ____XX__,________,
+ ____XX__,________,
+ ____XX__,________,
+ ____XX__,________,
+ ____XX__,________,
+ _____XX_,________,
+ ______XX,________,
+ _____XX_,________,
+ ____XX__,________,
+ ____XX__,________,
+ ____XX__,________,
+ ____XX__,________,
+ ____XX__,________,
+ ____XX__,________,
+ ____XX__,________,
+ ____XX__,________,
+ __XXX___,________,
+ ________,________
+};
+
+/* char: ~ code:0x007E */
+static GUI_CONST_STORAGE unsigned char ac007E[48] = {
+ ________,________,
+ __XXXX__,________,
+ _XX__XX_,__XX____,
+ _XX___XX,X_XX____,
+ _______X,XXX_____,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: code:0x007F */
+static GUI_CONST_STORAGE unsigned char ac007F[48] = {
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________,
+ ________,________
+};
+
+/* char: 。 code:0xA1A3 */
+static GUI_CONST_STORAGE unsigned char acA1A3[72] = {
+ ________,________,________,
+ ________,________,________,
+ ________,________,________,
+ ________,________,________,
+ ________,________,________,
+ ________,________,________,
+ ________,________,________,
+ ________,________,________,
+ ________,________,________,
+ ________,________,________,
+ ________,________,________,
+ ________,________,________,
+ ________,________,________,
+ ________,________,________,
+ ________,________,________,
+ ________,________,________,
+ ____XXXX,________,________,
+ ___XX__X,X_______,________,
+ ___XX__X,X_______,________,
+ ___XX__X,X_______,________,
+ ____XXXX,________,________,
+ ________,________,________,
+ ________,________,________,
+ ________,________,________,
+};
+
+/* char: ° code:0xA1E3 */
+static GUI_CONST_STORAGE unsigned char acA1E3[72] = {
+ ________,________,________,
+ ________,________,________,
+ ________,________,________,
+ _____XXX,________,________,
+ ____XX_X,X_______,________,
+ ___XX___,XX______,________,
+ ___XX___,XX______,________,
+ ___XX__X,X_______,________,
+ ____XXXX,________,________,
+ ________,________,________,
+ ________,________,________,
+ ________,________,________,
+ ________,________,________,
+ ________,________,________,
+ ________,________,________,
+ ________,________,________,
+ ________,________,________,
+ ________,________,________,
+ ________,________,________,
+ ________,________,________,
+ ________,________,________,
+ ________,________,________,
+ ________,________,________,
+ ________,________,________,
+};
+
+/* char: ℃ code:0xA1E6 */
+static GUI_CONST_STORAGE unsigned char acA1E6[72] = {
+ ________,________,________,
+ ________,________,________,
+ ________,________,________,
+ ____XXX_,________,________,
+ ___XX_XX,___XXXXX,XX______,
+ ___XX_XX,__XXX___,_XXXXX__,
+ ___XX_XX,_XXX____,___XXX__,
+ ____XXX_,XXX_____,___XXX__,
+ ________,XX______,____XX__,
+ _______X,XX______,____XX__,
+ _______X,XX______,________,
+ _______X,XX______,________,
+ _______X,XX______,________,
+ _______X,XX______,________,
+ _______X,XX______,________,
+ ________,XX______,________,
+ ________,XXX_____,________,
+ ________,XXX_____,___XX___,
+ ________,_XXX____,__XX____,
+ ________,__XXXX__,XXX_____,
+ ________,____XXXX,X_______,
+ ________,________,________,
+ ________,________,________,
+ ________,________,________,
+};
+
+/* char: , code:0xA3AC */
+static GUI_CONST_STORAGE unsigned char acA3AC[72] = {
+ ________,________,________,
+ ________,________,________,
+ ________,________,________,
+ ________,________,________,
+ ________,________,________,
+ ________,________,________,
+ ________,________,________,
+ ________,________,________,
+ ________,________,________,
+ ________,________,________,
+ ________,________,________,
+ ________,________,________,
+ ________,________,________,
+ ________,________,________,
+ ________,________,________,
+ ____XXX_,________,________,
+ ___XXXX_,________,________,
+ ___XXXX_,________,________,
+ ____XXX_,________,________,
+ ____XX__,________,________,
+ ____XX__,________,________,
+ ___XX___,________,________,
+ ________,________,________,
+ ________,________,________,
+};
+
+/* char: ℉ code:0xA848 */
+static GUI_CONST_STORAGE unsigned char acA848[72] = {
+ ________,________,________,
+ ________,________,________,
+ ________,________,________,
+ ___XXXXX,XXXXXXXX,XXXXX___,
+ __XX_XXX,__XX____,__XXX___,
+ __XX__XX,__XX____,___XX___,
+ __XX_XX_,__XX____,________,
+ ___XXX__,__XX____,________,
+ ________,__XX____,XX______,
+ ________,__XX____,XX______,
+ ________,__XXXXXX,XX______,
+ ________,__XX___X,XX______,
+ ________,__XX____,XX______,
+ ________,__XX____,________,
+ ________,__XX____,________,
+ ________,__XX____,________,
+ ________,__XX____,________,
+ ________,__XX____,________,
+ ________,__XX____,________,
+ ________,XXXXXX__,________,
+ ________,________,________,
+ ________,________,________,
+ ________,________,________,
+ ________,________,________,
+};
+
+/* char: 败 code:0xB0DC */
+static GUI_CONST_STORAGE unsigned char acB0DC[72] = {
+ ________,________,________,
+ ________,______XX,________,
+ ________,______XX,X_______,
+ __XXXXXX,XXXX__XX,________,
+ __XXX___,_XX__XXX,________,
+ __XXX___,_XX__XX_,________,
+ __XXX_XX,_XX__XXX,XXXXXXX_,
+ __XXX_XX,_XX__XX_,__XXX___,
+ __XXX_XX,_XX_XXX_,__XXX___,
+ __XXX_XX,_XX_XXX_,__XX____,
+ __XXX_XX,_XXXX_XX,__XX____,
+ __XXX_XX,_XXX__XX,__XX____,
+ __XXX_XX,_XX___XX,_XXX____,
+ __XXXXXX,_XX___XX,_XX_____,
+ __XXXXX_,_XX____X,XXX_____,
+ __XXXXXX,XXX____X,XXX_____,
+ __XX_XX_,XX______,XX______,
+ ____XXX_,_XX____X,XXX_____,
+ ____XX__,_XXX__XX,XXX_____,
+ ___XX___,__XX_XXX,__XXX___,
+ __XX____,____XX__,__XXXX__,
+ _XX_____,__XXX___,___XXXXX,
+ ________,_XX_____,________,
+ ________,________,________,
+};
+
+/* char: 版 code:0xB0E6 */
+static GUI_CONST_STORAGE unsigned char acB0E6[72] = {
+ ________,________,________,
+ ______XX,________,________,
+ ______XX,X_______,___XXX__,
+ ___XX_XX,X______X,XXXXXX__,
+ ___XX_XX,X__XXXXX,________,
+ ___XX_XX,X__XX___,________,
+ ___XX_XX,X__XX___,________,
+ ___XX_XX,X__XX___,________,
+ ___XXXXX,XXXXXXXX,XXXXXX__,
+ ___XX___,___XXXX_,___XXX__,
+ ___XX___,___XX_XX,___XX___,
+ ___XX___,___XX_XX,___XX___,
+ ___XXXXX,XX_XX_XX,__XXX___,
+ ___XX__X,XX_XX_XX,__XX____,
+ ___XX__X,XX_XX__X,X_XX____,
+ ___XX__X,XX_XX__X,XXX_____,
+ ___XX__X,XX_XX___,XXX_____,
+ __XXX__X,XXXX____,XXX_____,
+ __XX___X,XXXX___X,XXXX____,
+ __XX___X,XXXX__XX,__XXX___,
+ __XX___X,XXX__XX_,___XXXX_,
+ _XX_____,_XXXXX__,____XXX_,
+ _XX_____,XXXX____,________,
+ ________,________,________,
+};
+
+/* char: 包 code:0xB0FC */
+static GUI_CONST_STORAGE unsigned char acB0FC[72] = {
+ ________,________,________,
+ ________,________,________,
+ _______X,XX______,________,
+ _______X,XX______,________,
+ ______XX,X_______,________,
+ ______XX,XXXXXXXX,XXXXX___,
+ _____XXX,________,__XX____,
+ _____XX_,________,__XX____,
+ ____XX__,________,__XX____,
+ ___XXXXX,XXXXXXXX,__XX____,
+ ___XXXXX,_____XX_,__XX____,
+ __XX__XX,_____XX_,__XX____,
+ _XX___XX,_____XX_,__XX____,
+ ______XX,_____XX_,__XX____,
+ ______XX,XXXXXXX_,__XX____,
+ ______XX,_____XX_,__XX____,
+ ______XX,______XX,XXXX____,
+ ______XX,________,XXX__XX_,
+ ______XX,________,_____XX_,
+ ______XX,________,_____XX_,
+ ______XX,________,_____XX_,
+ ______XX,XXX_____,_XXXXXX_,
+ ________,XXXXXXXX,XXXXX___,
+ ________,________,________,
+};
+
+/* char: 保 code:0xB1A3 */
+static GUI_CONST_STORAGE unsigned char acB1A3[72] = {
+ ________,________,________,
+ _______X,X_______,________,
+ ______XX,X_______,________,
+ ______XX,__XXXXXX,XXXXXX__,
+ ______XX,__XX____,___XX___,
+ _____XXX,__XX____,___XX___,
+ _____XX_,__XX____,___XX___,
+ ____XXX_,__XX____,___XX___,
+ ____XXX_,__XXXXXX,XXXXX___,
+ ___XXXX_,__XX__XX,___XX___,
+ ___XXXX_,______XX,________,
+ __XX_XX_,______XX,_____XX_,
+ _XX__XXX,XXXXXXXX,XXXXXXXX,
+ _____XX_,_____XXX,XX______,
+ _____XX_,____XXXX,XX______,
+ _____XX_,____XXXX,_XX_____,
+ _____XX_,___XXXXX,__XX____,
+ _____XX_,___XX_XX,__XX____,
+ _____XX_,__XX__XX,___XX___,
+ _____XX_,_XX___XX,____XXX_,
+ _____XX_,XX____XX,X___XXX_,
+ _____XXX,X_____XX,X_______,
+ _____XX_,______XX,________,
+ ________,________,________,
+};
+
+/* char: 备 code:0xB1B8 */
+static GUI_CONST_STORAGE unsigned char acB1B8[72] = {
+ ________,________,________,
+ ________,_XX_____,________,
+ ________,XXX_____,________,
+ ________,XXXXXXXX,XXX_____,
+ _______X,XX______,XX______,
+ _______X,XXX____X,XX______,
+ ______XX,_XX___XX,X_______,
+ _____XXX,__XX_XXX,________,
+ ____XXX_,__XXXXX_,________,
+ ___XX___,___XXX__,________,
+ ________,__XXXXX_,________,
+ ________,_XX___XX,X_______,
+ _______X,XX_____X,XXXX____,
+ _____XXX,XXXXXXXX,XXXXXXXX,
+ __XXXXXX,____XX__,_XX_XX__,
+ ______XX,____XX__,_XX_____,
+ ______XX,____XX__,_XX_____,
+ ______XX,XXXXXXXX,XXX_____,
+ ______XX,____XX__,_XX_____,
+ ______XX,____XX__,_XX_____,
+ ______XX,XXXXXXXX,XXX_____,
+ ______XX,________,_XX_____,
+ ______XX,________,_XX_____,
+ ________,________,________,
+};
+
+/* char: 本 code:0xB1BE */
+static GUI_CONST_STORAGE unsigned char acB1BE[72] = {
+ ________,________,________,
+ ________,___XX___,________,
+ ________,___XXX__,________,
+ ________,___XXX__,________,
+ ________,___XXX__,________,
+ ________,___XXX__,____XX__,
+ __XXXXXX,XXXXXXXX,XXXXXXX_,
+ ________,__XXXXX_,________,
+ ________,__XXXXX_,________,
+ ________,_XXXXXXX,________,
+ ________,_XXXXXXX,________,
+ ________,XXXXXX_X,X_______,
+ ________,XX_XXX_X,XX______,
+ _______X,XX_XXX__,XX______,
+ ______XX,X__XXX__,_XX_____,
+ ______XX,___XXX__,_XXX____,
+ _____XX_,___XXX__,XXXXXX__,
+ ____XXXX,XXXXXXXX,XXXXXXXX,
+ __XXX___,___XXX__,____XX__,
+ _XX_____,___XXX__,________,
+ ________,___XXX__,________,
+ ________,___XXX__,________,
+ ________,___XXX__,________,
+ ________,___XXX__,________,
+};
+
+/* char: 编 code:0xB1E0 */
+static GUI_CONST_STORAGE unsigned char acB1E0[72] = {
+ ________,________,________,
+ ________,______XX,________,
+ _____XXX,_______X,X_______,
+ _____XX_,_______X,X_______,
+ ____XX__,__XXXXXX,XXXXXX__,
+ ____XX__,__XX____,___XXX__,
+ ___XX__X,XXXX____,___XXX__,
+ ___XX__X,X_XX____,___XXX__,
+ __XX_XXX,X_XXXXXX,XXXXXX__,
+ __XXXXXX,__XX____,___XX___,
+ _____XX_,__XX____,________,
+ ____XX__,__XXXXXX,XXXXXXX_,
+ ___XX___,_XXXX_XX,_XX_XXX_,
+ __XXX_XX,XXXXX_XX,_XX_XXX_,
+ __XXXXX_,_XXXX_XX,_XX_XXX_,
+ ________,_XXXXXXX,XXXXXXX_,
+ _______X,XXXXX_XX,_XX_XXX_,
+ ____XXXX,XXXXX_XX,_XX_XXX_,
+ _XXXXX__,XX_XX_XX,_XX_XXX_,
+ __XX___X,XX_XX_XX,_XX_XXX_,
+ _______X,X__XX___,____XXX_,
+ ______XX,___XX___,___XXX__,
+ _____XX_,________,____XX__,
+ ________,________,________,
+};
+
+/* char: 变 code:0xB1E4 */
+static GUI_CONST_STORAGE unsigned char acB1E4[72] = {
+ ________,________,________,
+ ________,__XX____,________,
+ ________,___XXX__,________,
+ ________,___XXX__,____XX__,
+ _XXXXXXX,XXXXXXXX,XXXXXXX_,
+ ________,_XX___XX,________,
+ ________,_XX___XX,________,
+ ______XX,XXX___XX,XXX_____,
+ _____XXX,_XX___XX,__XX____,
+ ____XXX_,_XX___XX,___XXX__,
+ ____XX__,_XX___XX,____XXX_,
+ ___XX___,_XX___XX,_XX__XX_,
+ __XXXXXX,XXXXXXXX,XXXX____,
+ ________,XX______,XXX_____,
+ ________,_XX____X,XX______,
+ ________,_XX___XX,X_______,
+ ________,__XX__XX,________,
+ ________,___XXXX_,________,
+ ________,___XXX__,________,
+ ________,__XXXXXX,________,
+ ________,XXX____X,XXX_____,
+ _____XXX,X_______,_XXXXXXX,
+ __XXXX__,________,___XXX__,
+ ________,________,________,
+};
+
+/* char: 不 code:0xB2BB */
+static GUI_CONST_STORAGE unsigned char acB2BB[72] = {
+ ________,________,________,
+ ________,________,________,
+ ________,________,____XX__,
+ __XXXXXX,XXXXXXXX,XXXXXXX_,
+ ________,____XXX_,________,
+ ________,___XXX__,________,
+ ________,___XX___,________,
+ ________,__XXX___,________,
+ ________,__XXXX__,________,
+ ________,_XXXXX__,________,
+ ________,XXXXXX_X,XX______,
+ ________,XX_XXX__,_XX_____,
+ _______X,X__XXX__,__XXX___,
+ ______XX,___XXX__,___XXX__,
+ _____XX_,___XXX__,____XXX_,
+ ____XX__,___XXX__,____XXX_,
+ __XXX___,___XXX__,_____XX_,
+ _XX_____,___XXX__,________,
+ ________,___XXX__,________,
+ ________,___XXX__,________,
+ ________,___XXX__,________,
+ ________,___XXX__,________,
+ ________,___XX___,________,
+ ________,________,________,
+};
+
+/* char: 菜 code:0xB2CB */
+static GUI_CONST_STORAGE unsigned char acB2CB[72] = {
+ ________,________,________,
+ ________,XX____XX,________,
+ ________,XXX___XX,________,
+ ________,XXX___XX,____XX__,
+ _XXXXXXX,XXXXXXXX,XXXXXXX_,
+ ________,XXX___XX,________,
+ ________,XXX___XX,__XX____,
+ ________,____XXXX,XXXXX___,
+ ___XXXXX,XXXXX___,________,
+ ________,__XX____,________,
+ _____XX_,___XXX__,_XXX____,
+ ______XX,____XX__,XXX_____,
+ ______XX,X__XX___,XX______,
+ ________,___XXX_X,X___XX__,
+ _XXXXXXX,XXXXXXXX,XXXXXXX_,
+ ________,_XXXXXX_,________,
+ ________,_XXXXXXX,________,
+ ________,XX_XXX_X,X_______,
+ _______X,X__XXX__,XX______,
+ _____XXX,___XXX__,_XXX____,
+ ____XXX_,___XXX__,__XXXXXX,
+ __XXX___,___XXX__,____XX__,
+ _XX_____,___XX___,________,
+ ________,________,________,
+};
+
+/* char: 参 code:0xB2CE */
+static GUI_CONST_STORAGE unsigned char acB2CE[72] = {
+ ________,________,________,
+ ________,________,________,
+ ________,__XXX___,________,
+ ________,XXX___XX,X_______,
+ _______X,X_______,XXX_____,
+ _____XXX,____XXXX,XXXX____,
+ _____XXX,XXXXX___,__XXX___,
+ ________,_XXX____,___XX___,
+ _XXXXXXX,XXXXXXXX,XXXXXXX_,
+ ________,XXX___XX,________,
+ _______X,XX__XX_X,X_______,
+ ______XX,X__XXX__,XX______,
+ _____XXX,__XXX___,_XXX____,
+ ____XX__,_XXX__XX,__XXXXXX,
+ __XXX___,XX___XXX,X___XX__,
+ _XX___XX,X___XXX_,________,
+ ____XXX_,___XXX__,________,
+ ________,_XXX____,_XXX____,
+ _______X,XX_____X,XXX_____,
+ _____XXX,_____XXX,X_______,
+ ________,___XXXX_,________,
+ ________,XXXX____,________,
+ ___XXXXX,X_______,________,
+ ________,________,________,
+};
+
+/* char: 测 code:0xB2E2 */
+static GUI_CONST_STORAGE unsigned char acB2E2[72] = {
+ ________,________,________,
+ ________,________,________,
+ ___XX___,________,____XX__,
+ ____XX_X,XXXXXXXX,____XX__,
+ ____XXXX,XX___XXX,____XX__,
+ _______X,XX___XXX,____XX__,
+ _______X,XXXXXXXX,_XXXXX__,
+ _XX____X,XXXXXXXX,_XX_XX__,
+ __XXX_XX,XXXXXXXX,_XX_XX__,
+ ___XX_XX,XXXXXXXX,_XX_XX__,
+ ___XX_XX,XXXXXXXX,_XX_XX__,
+ _____XXX,XXXXXXXX,_XX_XX__,
+ _____XXX,XXXXXXXX,_XX_XX__,
+ _____XXX,XXXXXXXX,_XX_XX__,
+ ____XX_X,XXXX_XXX,_XX_XX__,
+ ____XX_X,XXXX_XXX,_XX_XX__,
+ __XXXX_X,XXXX_XX_,_XX_XX__,
+ ___XXX_X,XXXX____,____XX__,
+ ___XXX__,_XXXXX__,____XX__,
+ ___XXX__,XXX__XX_,____XX__,
+ ___XXX__,XX___XXX,____XX__,
+ ___XXXXX,X_____XX,__XXXX__,
+ _____XX_,________,___XXX__,
+ ________,________,________,
+};
+
+/* char: 查 code:0xB2E9 */
+static GUI_CONST_STORAGE unsigned char acB2E9[72] = {
+ ________,________,________,
+ ________,___XX___,________,
+ ________,___XXX__,________,
+ ________,___XXX__,____XX__,
+ __XXXXXX,XXXXXXXX,XXXXXXX_,
+ ________,__XXXXX_,________,
+ ________,_XXXXXXX,________,
+ ________,XXXXXX_X,X_______,
+ _______X,XX_XXX__,XX______,
+ ______XX,X__XXX__,_XXX____,
+ _____XX_,___XX___,__XXXXXX,
+ ___XXXXX,XXXXXXXX,XXXXXX__,
+ _XXX__XX,X_______,_XX_____,
+ ______XX,X_______,_XX_____,
+ ______XX,XXXXXXXX,XXX_____,
+ ______XX,X_______,_XX_____,
+ ______XX,X_______,_XX_____,
+ ______XX,X_______,_XX_____,
+ ______XX,XXXXXXXX,XXX_____,
+ ______XX,X_______,_XX_____,
+ ______XX,________,____XX__,
+ __XXXXXX,XXXXXXXX,XXXXXXX_,
+ ________,________,________,
+ ________,________,________,
+};
+
+/* char: 常 code:0xB3A3 */
+static GUI_CONST_STORAGE unsigned char acB3A3[72] = {
+ ________,________,________,
+ ________,___XXX__,________,
+ ______XX,X__XXX__,XXX_____,
+ _______X,XX_XXX__,XX______,
+ ________,XX_XXX_X,X_______,
+ ___XXXXX,XXXXXXXX,XXXXXXX_,
+ ___XX___,________,____XXX_,
+ __XXX___,________,____XX__,
+ __XX___X,XXXXXXXX,XX_XX___,
+ _______X,X_______,XX______,
+ _______X,X_______,XX______,
+ _______X,XXXXXXXX,XX______,
+ _______X,X__XXX__,XX______,
+ ________,___XXX__,________,
+ _____XXX,XXXXXXXX,XXXXX___,
+ _____XX_,___XXX__,__XX____,
+ _____XX_,___XXX__,__XX____,
+ _____XX_,___XXX__,__XX____,
+ _____XX_,___XXX__,__XX____,
+ _____XX_,___XXX__,XXXX____,
+ _____XX_,___XXX__,_XXX____,
+ ________,___XXX__,________,
+ ________,___XXX__,________,
+ ________,________,________,
+};
+
+/* char: 厂 code:0xB3A7 */
+static GUI_CONST_STORAGE unsigned char acB3A7[72] = {
+ ________,________,________,
+ ________,________,________,
+ ________,________,____XX__,
+ ____XXXX,XXXXXXXX,XXXXXXX_,
+ ____XXX_,________,________,
+ ____XXX_,________,________,
+ ____XXX_,________,________,
+ ____XXX_,________,________,
+ ____XXX_,________,________,
+ ____XXX_,________,________,
+ ____XXX_,________,________,
+ ____XXX_,________,________,
+ ____XXX_,________,________,
+ ____XXX_,________,________,
+ ____XX__,________,________,
+ ____XX__,________,________,
+ ____XX__,________,________,
+ ____XX__,________,________,
+ ___XX___,________,________,
+ ___XX___,________,________,
+ __XX____,________,________,
+ __XX____,________,________,
+ _XX_____,________,________,
+ ________,________,________,
+};
+
+/* char: 超 code:0xB3AC */
+static GUI_CONST_STORAGE unsigned char acB3AC[72] = {
+ ________,________,________,
+ ______XX,________,________,
+ ______XX,X_______,________,
+ ______XX,____XXXX,XXXXXXX_,
+ ______XX,_______X,X___XXX_,
+ __XXXXXX,XXXX___X,X___XX__,
+ ______XX,______XX,X___XX__,
+ ______XX,______XX,X___XX__,
+ ______XX,______XX,____XX__,
+ _XXXXXXX,XXXXXXX_,_XXXXX__,
+ ______XX,X___XX__,___XX___,
+ ______XX,X__XXX__,____XX__,
+ ___XXXXX,X____XXX,XXXXXXX_,
+ ___XX_XX,X_XX_XX_,____XX__,
+ ___XX_XX,XXXXXXX_,____XX__,
+ ___XX_XX,X____XX_,____XX__,
+ ___XX_XX,X____XX_,____XX__,
+ ___XXXXX,X____XXX,XXXXXX__,
+ __XXXXXX,X____XX_,____XX__,
+ __XX_XXX,X____XX_,________,
+ __XX___X,XX______,________,
+ _XX_____,XXXXXXXX,XXXXXXXX,
+ _XX_____,_____XXX,XXXXXXX_,
+ ________,________,________,
+};
+
+/* char: 成 code:0xB3C9 */
+static GUI_CONST_STORAGE unsigned char acB3C9[72] = {
+ ________,________,________,
+ ________,________,________,
+ ________,____XXX_,XX______,
+ ________,____XXX_,_XX_____,
+ ________,____XXX_,__XX____,
+ ________,_____XX_,__XXXX__,
+ ____XXXX,XXXXXXXX,XXXXXXX_,
+ ____XX__,_____XX_,________,
+ ____XX__,_____XX_,________,
+ ____XX__,_____XX_,___XX___,
+ ____XX__,_____XXX,___XXX__,
+ ____XXXX,XXXX_XXX,__XXX___,
+ ____XX__,__XX__XX,__XX____,
+ ____XX__,__XX__XX,_XXX____,
+ ____XX__,__XX__XX,XXXX____,
+ ____XX__,_XXX__XX,XXX_____,
+ ____XX__,_XXX___X,XX____XX,
+ ___XX___,_XXX___X,XX____XX,
+ ___XX_XX,XXX___XX,XXX__XX_,
+ ___XX___,XXX__XXX,_XXXXXX_,
+ __XX____,____XX__,__XXXXX_,
+ __XX____,__XXX___,___XXXX_,
+ _XX_____,________,________,
+ ________,________,________,
+};
+
+/* char: 程 code:0xB3CC */
+static GUI_CONST_STORAGE unsigned char acB3CC[72] = {
+ ________,________,________,
+ ________,________,________,
+ ________,XX______,________,
+ _____XXX,XXXXXXXX,XXXXXX__,
+ __XXXXXX,____XX__,____XX__,
+ ______XX,____XX__,____XX__,
+ ______XX,____XX__,____XX__,
+ ______XX,____XX__,____XX__,
+ _XXXXXXX,XXXXXXXX,XXXXXX__,
+ _____XXX,___XXX__,____XX__,
+ _____XXX,___XX___,____XX__,
+ _____XXX,X_XXXXXX,XXXXXXX_,
+ ____XXXX,XXX_____,XX______,
+ ____XXXX,_XX_____,XX______,
+ ___XXXXX,________,XX______,
+ ___XX_XX,________,XX__XX__,
+ __XX__XX,___XXXXX,XXXXXXX_,
+ __XX__XX,________,XX______,
+ _XX___XX,________,XX______,
+ _____XXX,________,XX______,
+ _____XXX,________,XX___XX_,
+ _____XXX,_XXXXXXX,XXXXXXXX,
+ _____XXX,________,________,
+ ________,________,________,
+};
+
+/* char: 出 code:0xB3F6 */
+static GUI_CONST_STORAGE unsigned char acB3F6[72] = {
+ ________,________,________,
+ ________,________,________,
+ ________,___XX___,________,
+ ________,___XXX__,________,
+ ________,___XXX__,________,
+ ____XXX_,___XXX__,__XXX___,
+ ____XXX_,___XXX__,__XX____,
+ ____XXX_,___XXX__,__XX____,
+ ____XXX_,___XXX__,__XX____,
+ ____XXX_,___XXX__,__XX____,
+ ____XXX_,___XXX__,__XX____,
+ ____XXXX,XXXXXXXX,XXXX____,
+ ________,___XXX__,__XXX___,
+ ________,___XXX__,________,
+ ________,___XXX__,________,
+ ____XXX_,___XXX__,___XXX__,
+ ____XX__,___XXX__,___XX___,
+ ____XX__,___XXX__,___XX___,
+ ____XX__,___XXX__,___XX___,
+ ____XX__,___XXX__,___XX___,
+ ____XX__,___XXX__,___XX___,
+ ___XXXXX,XXXXXXXX,XXXXX___,
+ ________,________,___XX___,
+ ________,________,________,
+};
+
+/* char: 存 code:0xB4E6 */
+static GUI_CONST_STORAGE unsigned char acB4E6[72] = {
+ ________,________,________,
+ ________,__XX____,________,
+ ________,__XXX___,________,
+ ________,__XX____,____XX__,
+ __XXXXXX,XXXXXXXX,XXXXXXX_,
+ ________,_XXX____,________,
+ ________,_XX_____,________,
+ ________,XXXXXXXX,XXXXX___,
+ _______X,XX______,__XXX___,
+ ______XX,X_______,_XX_____,
+ ______XX,________,XX______,
+ _____XXX,_______X,XX______,
+ _____XXX,_______X,X_______,
+ ____XXXX,_______X,X_______,
+ ___XX_XX,XXXXXXXX,XXXXXXX_,
+ __XX__XX,_______X,X_______,
+ _XX___XX,_______X,X_______,
+ ______XX,_______X,X_______,
+ ______XX,_______X,X_______,
+ ______XX,_______X,X_______,
+ ______XX,_______X,X_______,
+ ______XX,____XXXX,X_______,
+ ______XX,______XX,________,
+ ________,________,________,
+};
+
+/* char: 错 code:0xB4ED */
+static GUI_CONST_STORAGE unsigned char acB4ED[72] = {
+ ________,________,________,
+ ________,________,________,
+ ________,_____XX_,_XX_____,
+ ____XXXX,_____XX_,_XXX____,
+ ____XXX_,_____XX_,_XXX____,
+ ____XX__,_____XX_,_XXX____,
+ ____XXXX,XXXXXXXX,XXXXXXX_,
+ ___XXX__,_____XX_,_XXX____,
+ ___XX___,_____XX_,_XXX____,
+ __XXXXXX,XX___XX_,_XXX_XX_,
+ __XX_XX_,_XXXXXXX,XXXXXXXX,
+ _XX__XX_,________,________,
+ _____XX_,________,________,
+ _____XX_,___XXXXX,XXXXXX__,
+ _XXXXXXX,XXXXXX__,___XX___,
+ _____XX_,___XXX__,___XX___,
+ _____XX_,___XXXXX,XXXXX___,
+ _____XX_,___XXX__,___XX___,
+ _____XX_,___XXX__,___XX___,
+ _____XXX,X__XXX__,___XX___,
+ _____XXX,___XXXXX,XXXXX___,
+ _____XX_,___XXX__,___XX___,
+ ________,___XX___,________,
+ ________,________,________,
+};
+
+/* char: 单 code:0xB5A5 */
+static GUI_CONST_STORAGE unsigned char acB5A5[72] = {
+ ________,________,________,
+ _______X,X______X,X_______,
+ ________,XX_____X,XX______,
+ ________,XXX___XX,X_______,
+ ________,_XX___XX,________,
+ _____XXX,XXXXXXXX,XXXX____,
+ _____XX_,___XX___,__XX____,
+ _____XX_,___XX___,__XX____,
+ _____XX_,___XX___,__XX____,
+ _____XXX,XXXXXXXX,XXXX____,
+ _____XX_,___XX___,__XX____,
+ _____XX_,___XX___,__XX____,
+ _____XX_,___XX___,__XX____,
+ _____XXX,XXXXXXXX,XXXX____,
+ _____XX_,___XX___,__XX____,
+ ____XX__,___XX___,____XX__,
+ _XXXXXXX,XXXXXXXX,XXXXXXX_,
+ ________,___XX___,________,
+ ________,___XX___,________,
+ ________,___XX___,________,
+ ________,___XX___,________,
+ ________,___XX___,________,
+ ________,___XX___,________,
+ ________,________,________,
+};
+
+/* char: 但 code:0xB5AB */
+static GUI_CONST_STORAGE unsigned char acB5AB[72] = {
+ ________,________,________,
+ ________,________,________,
+ ______XX,________,________,
+ ______XX,X_______,________,
+ _____XXX,__XXXXXX,XXXXXX__,
+ _____XXX,__XX____,___XX___,
+ _____XX_,__XX____,___XX___,
+ ____XXX_,__XX____,___XX___,
+ ____XXX_,__XX____,___XX___,
+ ___XXXX_,__XX____,___XX___,
+ ___XXXX_,__XXXXXX,XXXXX___,
+ __XXXXX_,__XX____,___XX___,
+ _XX_XXX_,__XX____,___XX___,
+ ____XXX_,__XX____,___XX___,
+ ____XXX_,__XX____,___XX___,
+ ____XXX_,__XXXXXX,XXXXX___,
+ ____XXX_,__XX____,___XX___,
+ ____XXX_,_XXX____,___XX___,
+ ____XXX_,________,________,
+ ____XXX_,________,________,
+ ____XXX_,________,________,
+ ____XXXX,XXXXXXXX,XXXXXXX_,
+ ____XX__,________,________,
+ ________,________,________,
+};
+
+/* char: 当 code:0xB5B1 */
+static GUI_CONST_STORAGE unsigned char acB5B1[72] = {
+ ________,________,________,
+ ________,________,________,
+ ________,___XX___,________,
+ ________,___XXX__,________,
+ ____XX__,___XXX__,_XXX____,
+ _____XXX,___XXX__,_XXX____,
+ ______XX,X__XXX__,XXX_____,
+ ______XX,X__XXX__,XX______,
+ _______X,X__XXX_X,X_______,
+ ________,___XXXXX,________,
+ ___XXXXX,XXXXXXXX,XXXXXXX_,
+ ________,________,___XXX__,
+ ________,________,___XXX__,
+ ________,________,___XXX__,
+ ________,________,___XXX__,
+ ____XXXX,XXXXXXXX,XXXXXX__,
+ ________,________,___XXX__,
+ ________,________,___XXX__,
+ ________,________,___XXX__,
+ ________,________,___XXX__,
+ __XXXXXX,XXXXXXXX,XXXXXX__,
+ ________,________,___XXX__,
+ ________,________,___XXX__,
+ ________,________,________,
+};
+
+/* char: 的 code:0xB5C4 */
+static GUI_CONST_STORAGE unsigned char acB5C4[72] = {
+ ________,________,________,
+ ______XX,_______X,X_______,
+ ______XX,X______X,XX______,
+ ______XX,______XX,X_______,
+ ______XX,______XX,X_______,
+ _____XX_,______XX,________,
+ ___XXXXX,XXXX_XXX,XXXXXXX_,
+ ___XX___,_XX__XX_,____XX__,
+ ___XX___,_XX_XX__,____XX__,
+ ___XX___,_XX_XX__,____XX__,
+ ___XX___,_XXXX___,____XX__,
+ ___XX___,_XX__XX_,____XX__,
+ ___XXXXX,XXX___XX,X___XX__,
+ ___XX___,_XX____X,X___XX__,
+ ___XX___,_XX____X,X___XX__,
+ ___XX___,_XX_____,____XX__,
+ ___XX___,_XX_____,____XX__,
+ ___XX___,_XX_____,____XX__,
+ ___XX___,_XX_____,____XX__,
+ ___XXXXX,XXX_____,___XXX__,
+ ___XX___,_XX____X,X__XXX__,
+ ___XX___,_XX_____,XXXXX___,
+ ________,________,__XX____,
+ ________,________,________,
+};
+
+/* char: 电 code:0xB5E7 */
+static GUI_CONST_STORAGE unsigned char acB5E7[72] = {
+ ________,________,________,
+ ________,___XX___,________,
+ ________,___XX___,________,
+ ________,___XX___,________,
+ ________,___XX___,________,
+ ________,___XX___,________,
+ ____XXXX,XXXXXXXX,XXXXX___,
+ ____XX__,___XX___,__XX____,
+ ____XX__,___XX___,__XX____,
+ ____XX__,___XX___,__XX____,
+ ____XXXX,XXXXXXXX,XXXX____,
+ ____XX__,___XX___,__XX____,
+ ____XX__,___XX___,__XX____,
+ ____XX__,___XX___,__XX____,
+ ____XX__,___XX___,__XX____,
+ ____XXXX,XXXXXXXX,XXXX____,
+ ____XX__,___XX___,__XX____,
+ ____XX__,___XX___,________,
+ ________,___XX___,_____XX_,
+ ________,___XX___,_____XX_,
+ ________,___XX___,_____XX_,
+ ________,___XX___,____XXX_,
+ ________,___XXXXX,XXXXXXX_,
+ ________,________,________,
+};
+
+/* char: 定 code:0xB6A8 */
+static GUI_CONST_STORAGE unsigned char acB6A8[72] = {
+ ________,________,________,
+ ________,__XX____,________,
+ ________,___XXX__,________,
+ ________,____XX__,________,
+ ____XX__,____XX__,____XX__,
+ ____XXXX,XXXXXXXX,XXXXXX__,
+ ____XX__,________,___XXX__,
+ ___XXX__,________,___XX___,
+ __XXX___,________,__XX____,
+ ___XXXXX,XXXXXXXX,XXXXX___,
+ ________,___XXX__,________,
+ ________,___XXX__,________,
+ ______XX,___XXX__,________,
+ ______XX,X__XXX__,________,
+ ______XX,___XXXXX,XXXX____,
+ _____XXX,___XXX__,________,
+ _____XXX,___XXX__,________,
+ _____XXX,X__XXX__,________,
+ _____XX_,XX_XXX__,________,
+ ____XX__,_XXXXX__,________,
+ ___XX___,__XXXXXX,_____XX_,
+ ___XX___,____XXXX,XXXXXX__,
+ __XX____,________,________,
+ ________,________,________,
+};
+
+/* char: 动 code:0xB6AF */
+static GUI_CONST_STORAGE unsigned char acB6AF[72] = {
+ ________,________,________,
+ ________,________,________,
+ ________,_______X,X_______,
+ ________,_______X,X_______,
+ ________,_XX____X,X_______,
+ __XXXXXX,XXXX___X,X_______,
+ ________,_______X,X_______,
+ ________,____XXXX,XXXXXXX_,
+ ________,_______X,X___XXX_,
+ _XXXXXXX,XXXXX__X,X___XXX_,
+ ______XX,_______X,X___XXX_,
+ _____XXX,_______X,X___XXX_,
+ _____XX_,_______X,X___XX__,
+ ____XXX_,XX_____X,X___XX__,
+ ____XX__,_XX___XX,X___XX__,
+ ___XX___,_XXX__XX,____XX__,
+ ___XX___,__XX__XX,____XX__,
+ __XXXXXX,XXXXXXX_,____XX__,
+ __XXX___,___XXXX_,____XX__,
+ ________,____XX__,____XX__,
+ ________,___XX__X,XX_XXX__,
+ ________,_XXX____,_XXXX___,
+ ________,XX______,__XX____,
+ ________,________,________,
+};
+
+/* char: 度 code:0xB6C8 */
+static GUI_CONST_STORAGE unsigned char acB6C8[72] = {
+ ________,________,________,
+ ________,___XX___,________,
+ ________,____XXX_,________,
+ ________,____XXX_,____XX__,
+ ____XXXX,XXXXXXXX,XXXXXXX_,
+ ____XX__,_XX_____,XX______,
+ ____XX__,__XX____,XXX_____,
+ ____XX__,__XX____,XX__XX__,
+ ____XXXX,XXXXXXXX,XXXXXXX_,
+ ____XX__,__XX____,XX______,
+ ____XX__,__XX____,XX______,
+ ____XX__,__XXXXXX,XX______,
+ ____XX__,__XX____,XX______,
+ ____XX__,________,________,
+ ___XXX_X,XXXXXXXX,XXXX____,
+ ___XXX__,__XX____,_XX_____,
+ ___XX___,__XX____,XX______,
+ ___XX___,___XX__X,X_______,
+ ___XX___,____XXXX,________,
+ __XX____,____XXXX,________,
+ __XX____,__XXX__X,XXX_____,
+ _XX_____,XXX_____,_XXXXXXX,
+ _____XXX,X_______,____XX__,
+ ________,________,________,
+};
+
+/* char: 断 code:0xB6CF */
+static GUI_CONST_STORAGE unsigned char acB6CF[72] = {
+ ________,________,________,
+ ________,________,________,
+ ___XX___,XX______,____XX__,
+ ___XX___,XX______,__XXXXX_,
+ ___XX___,XX____XX,XXX_____,
+ ___XXXX_,XX_XXXXX,________,
+ ___XX_XX,XX_XX_XX,________,
+ ___XX_XX,XXXX__XX,________,
+ ___XX___,XXX___XX,________,
+ ___XXXXX,XXXXXXXX,XXXXXXX_,
+ ___XX__X,XX___XXX,___XX___,
+ ___XX__X,XXX___XX,___XX___,
+ ___XX__X,XXXX__XX,___XX___,
+ ___XX_XX,XX_XX_XX,___XX___,
+ ___XX_XX,XX_XXXXX,___XX___,
+ ___XXXX_,XX__XXXX,___XX___,
+ ___XXXX_,XX____XX,___XX___,
+ ___XXX__,XX___XXX,___XX___,
+ ___XX___,XXXX_XX_,___XX___,
+ __XXXXXX,XXXXXXX_,___XX___,
+ ________,____XX__,___XX___,
+ ________,___XX___,___XX___,
+ ________,__XX____,________,
+ ________,________,________,
+};
+
+/* char: 对 code:0xB6D4 */
+static GUI_CONST_STORAGE unsigned char acB6D4[72] = {
+ ________,________,________,
+ ________,________,________,
+ ________,________,________,
+ ________,________,__XX____,
+ ________,________,__XX____,
+ __XXXXXX,XXXX____,__XX____,
+ ________,_XX_____,__XX____,
+ ________,_XX_____,__XX____,
+ ________,XXXXXXXX,XXXXXXX_,
+ ___XX___,XX______,__XX____,
+ ____XX__,XX______,__XX____,
+ _____XXX,XX__XX__,__XX____,
+ ______XX,X___XXX_,__XX____,
+ ______XX,X____XXX,__XX____,
+ ______XX,X____XXX,__XX____,
+ _____XXX,XX___XX_,__XX____,
+ _____XX_,XXX_____,__XX____,
+ ____XX__,XXX_____,__XX____,
+ ___XX___,_XX_____,__XX____,
+ ___XX___,_XX_____,__XX____,
+ _XXX____,_XX__XXX,__XX____,
+ ________,_______X,XXXX____,
+ ________,________,_XX_____,
+ ________,________,________,
+};
+
+/* char: 发 code:0xB7A2 */
+static GUI_CONST_STORAGE unsigned char acB7A2[72] = {
+ ________,________,________,
+ ________,__XX__XX,________,
+ ________,__XX___X,XX______,
+ _____XXX,_XXX____,XXX_____,
+ ____XXX_,_XXX____,_XXX____,
+ ____XX__,_XX_____,_XXX____,
+ ___XXX__,_XX_____,____XX__,
+ __XXXXXX,XXXXXXXX,XXXXXXX_,
+ ___XX___,_XX_____,________,
+ ________,XXX_____,________,
+ ________,XXX_____,________,
+ ________,XXXXXXXX,XXXX____,
+ ________,XXXX____,_XXX____,
+ _______X,XXXX____,_XX_____,
+ _______X,X__XX___,XXX_____,
+ ______XX,X___XX_X,XX______,
+ ______XX,____XX_X,X_______,
+ _____XXX,_____XXX,________,
+ _____XX_,_____XXX,X_______,
+ ____XX__,___XXX_X,XXX_____,
+ ___XX___,__XXX___,XXXXX___,
+ __XX____,XXX_____,__XXXXXX,
+ _XX__XXX,X_______,____XX__,
+ ________,________,________,
+};
+
+/* char: 阀 code:0xB7A7 */
+static GUI_CONST_STORAGE unsigned char acB7A7[72] = {
+ ________,________,________,
+ _____XX_,________,________,
+ _____XXX,________,________,
+ ______XX,X_XXXXXX,XXXXXXX_,
+ ______XX,X_______,____XX__,
+ ___XXX__,____XX__,____XX__,
+ ___XXX__,_XXXXXXX,XX__XX__,
+ ___XXX__,XXX_XX__,XXX_XX__,
+ ___XXX__,XX__XX__,_XX_XX__,
+ ___XXX__,XX__XX__,_XX_XX__,
+ ___XXX_X,X__XXXXX,XX__XX__,
+ ___XXX_X,XXXX_XX_,XX__XX__,
+ ___XXXXX,XX___XX_,XXX_XX__,
+ ___XXXXX,XX___XXX,XX__XX__,
+ ___XXX_X,XX___XXX,X___XX__,
+ ___XXX_X,XX___XXX,__XXXX__,
+ ___XXX_X,XX__XXXX,X_XXXX__,
+ ___XXX_X,XXXXX__X,XXXXXX__,
+ ___XXX_X,XXX_____,XXXXXX__,
+ ___XXX_X,XX______,__XXXX__,
+ ___XXX__,________,____XX__,
+ ___XXX__,________,_XXXXX__,
+ ___XX___,________,___XX___,
+ ________,________,________,
+};
+
+/* char: 返 code:0xB7B5 */
+static GUI_CONST_STORAGE unsigned char acB7B5[72] = {
+ ________,________,________,
+ ________,________,________,
+ ________,________,__XX____,
+ ____XX__,______XX,XXXXX___,
+ _____XX_,__XXXXX_,________,
+ _____XXX,__XX____,________,
+ _____XX_,__XX____,________,
+ ________,__XX____,________,
+ ________,__XXXXXX,XXXXX___,
+ ________,__XX____,__XXX___,
+ _XXXXXXX,__XX____,__XX____,
+ _____XX_,__XXXX__,_XXX____,
+ _____XX_,_XXX_XX_,_XX_____,
+ _____XX_,_XXX__XX,XXX_____,
+ _____XX_,_XX_____,XXX_____,
+ _____XX_,_XX____X,XXXX____,
+ _____XX_,XX____XX,__XXX___,
+ _____XX_,XX___XX_,___XXX__,
+ _____XXX,X__XXX__,____XX__,
+ ____XXXX,_XXX____,________,
+ ___XX__X,X_______,________,
+ _XXX____,XXXXXXXX,XXXXXXXX,
+ __XX____,___XXXXX,XXXXXX__,
+ ________,________,________,
+};
+
+/* char: 复 code:0xB8B4 */
+static GUI_CONST_STORAGE unsigned char acB8B4[72] = {
+ ________,________,________,
+ _______X,X_______,________,
+ _______X,XX______,________,
+ ______XX,XXXXXXXX,XXXXXX__,
+ ______XX,________,________,
+ _____XX_,________,________,
+ ____XX_X,XXXXXXXX,XXXX____,
+ ___XX__X,X_______,_XX_____,
+ __XX___X,X_______,_XX_____,
+ _______X,XXXXXXXX,XXX_____,
+ _______X,X_______,_XX_____,
+ _______X,X_______,_XX_____,
+ _______X,XXXXXXXX,XXXX____,
+ ________,XXX_____,_XX_____,
+ ________,XXXXXXXX,XXX_____,
+ _______X,XXX_____,XXX_____,
+ ______XX,X_XX___X,XX______,
+ _____XX_,__XXX_XX,X_______,
+ ____XX__,___XXXXX,________,
+ ___XX___,___XXXX_,________,
+ ________,_XXX__XX,XX______,
+ ______XX,XX______,XXXXXXXX,
+ __XXXXX_,________,___XXX__,
+ ________,________,________,
+};
+
+/* char: 改 code:0xB8C4 */
+static GUI_CONST_STORAGE unsigned char acB8C4[72] = {
+ ________,________,________,
+ ________,________,________,
+ ________,______XX,X_______,
+ ________,______XX,X_______,
+ ________,______XX,________,
+ __XXXXXX,XXXX__XX,________,
+ ________,_XX__XX_,________,
+ ________,_XX__XXX,XXXXXXX_,
+ ________,_XX_XXX_,___XX___,
+ ________,_XX_XXX_,___XX___,
+ ___XXXXX,XXXXXXX_,__XXX___,
+ ___XX___,_XXXXXX_,__XX____,
+ ___XX___,__XX__XX,__XX____,
+ ___XX___,______XX,__XX____,
+ ___XX___,______XX,__XX____,
+ ___XX___,_______X,XXX_____,
+ ___XX___,_______X,XXX_____,
+ ___XX___,_XXX____,XX______,
+ ___XX__X,XX_____X,XXX_____,
+ ___XXXXX,______XX,__XX____,
+ __XXXX__,____XXX_,__XXXX__,
+ ___XX___,__XXX___,____XXXX,
+ ________,_XX_____,________,
+ ________,________,________,
+};
+
+/* char: 格 code:0xB8F1 */
+static GUI_CONST_STORAGE unsigned char acB8F1[72] = {
+ ________,________,________,
+ _____XX_,_____XX_,________,
+ _____XX_,____XXX_,________,
+ _____XX_,____XX__,________,
+ _____XX_,____XXXX,XXXXX___,
+ _____XX_,XX_XXX__,__XX____,
+ _XXXXXXX,XXXXXXX_,_XXX____,
+ _____XX_,__XX_XX_,XXX_____,
+ ____XXX_,_XX___XX,XX______,
+ ____XXXX,______XX,X_______,
+ ____XXXX,X_____XX,X_______,
+ ____XXXX,XX___XX_,XXX_____,
+ ___XXXX_,XX__XX__,_XXXX___,
+ ___XXXX_,__XXX___,___XXXX_,
+ __XX_XX_,XXXXXXXX,XXXXX___,
+ __XX_XXX,X__XX___,__XX____,
+ _XX__XX_,___XX___,__XX____,
+ _____XX_,___XX___,__XX____,
+ _____XX_,___XX___,__XX____,
+ _____XX_,___XX___,__XX____,
+ _____XX_,___XXXXX,XXXX____,
+ _____XX_,___XX___,__XX____,
+ _____XX_,___XX___,__XX____,
+ ________,________,________,
+};
+
+/* char: 功 code:0xB9A6 */
+static GUI_CONST_STORAGE unsigned char acB9A6[72] = {
+ ________,________,________,
+ ________,_______X,X_______,
+ ________,_______X,XX______,
+ ________,_______X,X_______,
+ ________,__XX___X,X_______,
+ __XXXXXX,XXXXX__X,X_______,
+ ______XX,_______X,X_______,
+ ______XX,___XXXXX,XXXXXXX_,
+ ______XX,_______X,X___XXX_,
+ ______XX,_______X,X___XXX_,
+ ______XX,_______X,X___XXX_,
+ ______XX,_______X,X___XX__,
+ ______XX,______XX,X___XX__,
+ ______XX,______XX,____XX__,
+ ______XX,______XX,____XX__,
+ ______XX,_XXX__XX,____XX__,
+ ______XX,XX___XX_,____XX__,
+ __XXXXX_,____XXX_,____XX__,
+ __XXX___,____XX__,____XX__,
+ ________,___XX___,____XX__,
+ ________,__XX___X,XX_XXX__,
+ ________,XXX_____,_XXXX___,
+ _______X,X_______,__XX____,
+ ________,________,________,
+};
+
+/* char: 公 code:0xB9AB */
+static GUI_CONST_STORAGE unsigned char acB9AB[72] = {
+ ________,________,________,
+ ________,________,________,
+ ________,_____XXX,________,
+ ________,_XX__XX_,________,
+ ________,XXX___XX,________,
+ ________,XXX___XX,________,
+ _______X,XX_____X,X_______,
+ _______X,X______X,X_______,
+ ______XX,X_______,XX______,
+ ______XX,________,XXX_____,
+ _____XX_,___XX___,_XXX____,
+ ____XX__,___XXX__,__XXX___,
+ ___XX___,__XXX___,___XXXX_,
+ __XX____,__XX____,____XX__,
+ ________,_XXX____,________,
+ ________,_XX_____,________,
+ ________,XX____XX,________,
+ _______X,X______X,XX______,
+ ______XX,X_______,XXX_____,
+ _____XXX,________,_XX_____,
+ ____XXXX,XXXXXXXX,XXXX____,
+ _____XXX,________,__XX____,
+ ________,________,__XX____,
+ ________,________,________,
+};
+
+/* char: 故 code:0xB9CA */
+static GUI_CONST_STORAGE unsigned char acB9CA[72] = {
+ ________,________,________,
+ ________,_______X,X_______,
+ _______X,XX_____X,XX______,
+ _______X,X______X,X_______,
+ _______X,X_____XX,X_______,
+ _______X,X_____XX,X_______,
+ _______X,X_____XX,________,
+ _XXXXXXX,XXXXXXXX,XXXXXXX_,
+ _______X,X____XXX,___XX___,
+ _______X,X____XXX,___XX___,
+ _______X,X___XXXX,___XX___,
+ _______X,X___XXXX,___XX___,
+ ___XXXXX,XXXX___X,X_XXX___,
+ ___XXX__,_XXX___X,X_XX____,
+ ___XXX__,_XXX___X,X_XX____,
+ ___XXX__,_XXX___X,X_XX____,
+ ___XXX__,_XXX____,XXX_____,
+ ___XXX__,_XXX____,XXX_____,
+ ___XXX__,_XXX___X,XXX_____,
+ ___XXXXX,XXXX__XX,X_XX____,
+ ___XXX__,_XXX_XXX,__XXXX__,
+ ___XXX__,___XXX__,____XXXX,
+ ________,__XX____,________,
+ ________,________,________,
+};
+
+/* char: 规 code:0xB9E6 */
+static GUI_CONST_STORAGE unsigned char acB9E6[72] = {
+ ________,________,________,
+ _____XXX,________,________,
+ _____XXX,________,________,
+ ______XX,____XXXX,XXXXXXX_,
+ ______XX,____XX__,____XX__,
+ ______XX,____XX__,____XX__,
+ __XXXXXX,XXX_XX_X,XX__XX__,
+ ______XX,____XX_X,XX__XX__,
+ ______XX,____XX_X,XX__XX__,
+ ______XX,____XX_X,XX__XX__,
+ ______XX,____XX_X,XX__XX__,
+ _XXXXXXX,XXXXXX_X,XX__XX__,
+ ______XX,____XX_X,XXX_XX__,
+ _____XXX,____XX_X,XXX_XX__,
+ _____XXX,____XX_X,XXX_____,
+ _____XXX,XX_____X,XXX_____,
+ _____XX_,XXX___XX,XXX_____,
+ _____XX_,_XX___XX,_XX__XX_,
+ ____XX__,_XX__XXX,_XX__XX_,
+ ____XX__,_____XX_,_XX__XX_,
+ ___XX___,___XXX__,_XX__XXX,
+ __XX____,__XX____,_XXXXXX_,
+ _XX_____,XXX_____,________,
+ ________,________,________,
+};
+
+/* char: 号 code:0xBAC5 */
+static GUI_CONST_STORAGE unsigned char acBAC5[72] = {
+ ________,________,________,
+ ________,________,________,
+ ______XX,XXXXXXXX,XXX_____,
+ ______XX,________,_XX_____,
+ ______XX,________,_XX_____,
+ ______XX,________,_XX_____,
+ ______XX,________,_XX_____,
+ ______XX,________,_XX_____,
+ ______XX,XXXXXXXX,XXX_____,
+ ______XX,________,_XX_____,
+ __XXXXXX,XXXXXXXX,XXXXXXX_,
+ ________,XXX_____,________,
+ ________,XX______,________,
+ _______X,XX______,________,
+ _______X,XXXXXXXX,XXXX____,
+ _______X,X_______,_XXX____,
+ ________,________,_XX_____,
+ ________,________,_XX_____,
+ ________,________,_XX_____,
+ ________,________,XXX_____,
+ ________,___XXX__,XX______,
+ ________,_____XXX,XX______,
+ ________,_____XXX,________,
+ ________,________,________,
+};
+
+/* char: 后 code:0xBAF3 */
+static GUI_CONST_STORAGE unsigned char acBAF3[72] = {
+ ________,________,________,
+ ________,________,________,
+ ________,________,___XX___,
+ ________,______XX,XXXXXX__,
+ _____XXX,XXXXXXX_,________,
+ _____XX_,________,________,
+ _____XX_,________,________,
+ _____XX_,________,____XX__,
+ _____XXX,XXXXXXXX,XXXXXXX_,
+ _____XX_,________,________,
+ _____XX_,________,________,
+ _____XX_,________,________,
+ _____XX_,________,________,
+ _____XX_,XXXXXXXX,XXXXX___,
+ _____XX_,_XX_____,__XXX___,
+ _____XX_,_XX_____,__XXX___,
+ ____XXX_,_XX_____,__XXX___,
+ ____XX__,_XX_____,__XXX___,
+ ____XX__,_XX_____,__XXX___,
+ ___XX___,XXXXXXXX,XXXXX___,
+ ___XX___,XXX_____,__XXX___,
+ __XX____,XXX_____,__XX____,
+ _XX_____,________,________,
+ ________,________,________,
+};
+
+/* char: 护 code:0xBBA4 */
+static GUI_CONST_STORAGE unsigned char acBBA4[72] = {
+ ________,________,________,
+ ________,________,________,
+ _____XX_,______XX,________,
+ _____XXX,_______X,X_______,
+ _____XXX,_______X,XX______,
+ _____XXX,________,XX______,
+ _____XXX,___XXXXX,XXXXXXX_,
+ _XXXXXXX,XXXXX___,____XX__,
+ _____XXX,__XXX___,____XX__,
+ _____XXX,___XX___,____XX__,
+ _____XXX,___XX___,____XX__,
+ _____XXX,XXXXXXXX,XXXXXXX_,
+ _____XXX,X__XX___,____XXX_,
+ __XXXXXX,___XX___,________,
+ __XX_XXX,___XX___,________,
+ _____XXX,___XX___,________,
+ _____XXX,__XXX___,________,
+ _____XXX,__XX____,________,
+ _____XXX,__XX____,________,
+ _____XXX,_XX_____,________,
+ __XX_XXX,XX______,________,
+ ___XXXX_,XX______,________,
+ ____XXXX,X_______,________,
+ ________,________,________,
+};
+
+/* char: 欢 code:0xBBB6 */
+static GUI_CONST_STORAGE unsigned char acBBB6[72] = {
+ ________,________,________,
+ ________,________,________,
+ ________,______XX,________,
+ ________,______XX,________,
+ ________,_____XXX,________,
+ _XXXXXXX,XXX__XX_,________,
+ ________,XXX__XX_,________,
+ ________,XX___XXX,XXXXXXX_,
+ __XX____,XX__XX_X,X___XXX_,
+ ___XX__X,XX__XX_X,XX__XX__,
+ ____XX_X,X__XX__X,XX_XX___,
+ _____XXX,X__XX__X,XX______,
+ _____XXX,X_XX___X,XX______,
+ ______XX,______XX,XX______,
+ _____XXX,X_____XX,_XX_____,
+ _____XXX,XX____XX,_XX_____,
+ ____XXX_,XXX__XXX,_XX_____,
+ ____XX__,XXX__XX_,_XXX____,
+ ___XX___,_XX_XXX_,__XX____,
+ __XX____,_XXXXX__,__XXX___,
+ __XX____,__XXX___,___XXX__,
+ _XX_____,_XX_____,____XXXX,
+ _______X,XX______,________,
+ ________,________,________,
+};
+
+/* char: 恢 code:0xBBD6 */
+static GUI_CONST_STORAGE unsigned char acBBD6[72] = {
+ ________,________,________,
+ _____XX_,____XX__,________,
+ _____XX_,____XXX_,________,
+ _____XX_,____XXX_,________,
+ _____XX_,____XXX_,________,
+ _____XX_,XXXXXXXX,XXXXXXX_,
+ _____XXX,____XX__,________,
+ _____XXX,X___XX_X,XX______,
+ __XX_XXX,XX_XXX_X,XX______,
+ __XX_XX_,___XX__X,XX______,
+ _XXX_XX_,___XXXXX,XX__XX__,
+ _____XX_,__XXXXXX,XX__XXX_,
+ _____XX_,__XX_XXX,XX_XX___,
+ _____XX_,__XXXX_X,XXXX____,
+ _____XX_,_XXXXX_X,XXX_____,
+ _____XX_,_XX___XX,XXX_____,
+ _____XX_,XX____XX,_XX_____,
+ _____XXX,X____XXX,__XX____,
+ _____XXX,X____XX_,__XXX___,
+ _____XXX,____XX__,___XXX__,
+ _____XX_,___XX___,___XXXX_,
+ _____XX_,_XXX____,____XXX_,
+ ____XX__,XX______,________,
+ ________,________,________,
+};
+
+/* char: 回 code:0xBBD8 */
+static GUI_CONST_STORAGE unsigned char acBBD8[72] = {
+ ________,________,________,
+ ________,________,________,
+ ________,________,____XX__,
+ ___XXXXX,XXXXXXXX,XXXXXX__,
+ ___XXX__,________,___XXX__,
+ ___XXX__,________,___XXX__,
+ ___XXX__,________,___XXX__,
+ ___XXX__,________,___XXX__,
+ ___XXX__,XXXXXXXX,XX_XXX__,
+ ___XXX__,XX_____X,X__XXX__,
+ ___XXX__,XX_____X,X__XXX__,
+ ___XXX__,XX_____X,X__XXX__,
+ ___XXX__,XX_____X,X__XXX__,
+ ___XXX__,XX_____X,X__XXX__,
+ ___XXX__,XXXXXXXX,X__XXX__,
+ ___XXX__,XX_____X,X__XXX__,
+ ___XXX__,XX______,___XXX__,
+ ___XXX__,________,___XXX__,
+ ___XXX__,________,___XXX__,
+ ___XXX__,________,___XXX__,
+ ___XXXXX,XXXXXXXX,XXXXXX__,
+ ___XXX__,________,___XXX__,
+ ___XXX__,________,________,
+ ________,________,________,
+};
+
+/* char: 或 code:0xBBF2 */
+static GUI_CONST_STORAGE unsigned char acBBF2[72] = {
+ ________,________,________,
+ ________,________,________,
+ ________,_____XX_,_XX_____,
+ ________,_____XXX,__XXX___,
+ ________,_____XXX,__XXX___,
+ ________,_____XXX,____XX__,
+ __XXXXXX,XXXXXXXX,XXXXXXX_,
+ ________,_____XXX,________,
+ ________,_____XXX,________,
+ ____XXXX,XXXX__XX,___XX___,
+ ____XX__,__XX__XX,___XXX__,
+ ____XX__,__XX__XX,__XXX___,
+ ____XX__,__XX__XX,__XXX___,
+ ____XX__,__XX__XX,X_XX____,
+ ____XXXX,XXXX__XX,XXXX____,
+ ____XX__,__XX___X,XXX_____,
+ ___XX___,_______X,XXX_____,
+ ________,___XXX_X,XX______,
+ _______X,XXXX__XX,XXX__XX_,
+ _XXXXXXX,_____XX_,_XXX_XX_,
+ __XXX___,____XX__,__XXXXX_,
+ ________,__XXX___,___XXXX_,
+ ________,_XX_____,_____XXX,
+ ________,________,________,
+};
+
+/* char: 辑 code:0xBCAD */
+static GUI_CONST_STORAGE unsigned char acBCAD[72] = {
+ ________,________,________,
+ _____XX_,________,________,
+ _____XXX,___XXXXX,XXXXX___,
+ _____XX_,___XX___,__XX____,
+ ____XXX_,___XX___,__XX____,
+ _XXXXXXX,XXXXX___,__XX____,
+ ____XX__,___XXXXX,XXXX____,
+ ___XXX__,___XX___,__XX____,
+ ___XX_XX,X__XX___,________,
+ ___XX_XX,_XXXXXXX,XXXXXXX_,
+ __XXX_XX,XX_XXX__,__XX____,
+ _XXXXXXX,XXXXXXXX,XXXX____,
+ __XX__XX,___XXX__,__XX____,
+ ______XX,___XXX__,__XX____,
+ ______XX,___XXXXX,XXXX____,
+ ______XX,XXXXXX__,__XX____,
+ ____XXXX,___XXX__,__XX____,
+ _XXXX_XX,___XXX__,__XX_XX_,
+ ______XX,_XXXXXXX,XXXXXXX_,
+ ______XX,________,__XX____,
+ ______XX,________,__XX____,
+ ______XX,________,__XX____,
+ ______XX,________,__XX____,
+ ________,________,________,
+};
+
+/* char: 技 code:0xBCBC */
+static GUI_CONST_STORAGE unsigned char acBCBC[72] = {
+ ________,________,________,
+ _____XX_,_______X,X_______,
+ _____XXX,_______X,XX______,
+ _____XXX,_______X,X_______,
+ _____XXX,_______X,X_______,
+ _____XXX,_______X,X_______,
+ _XXXXXXX,XXXXXXXX,XXXXXXX_,
+ _____XXX,_______X,X_______,
+ _____XXX,_______X,X_______,
+ _____XXX,_______X,X_______,
+ _____XXX,_XX____X,X_______,
+ _____XXX,XXXXXXXX,XXXXXX__,
+ ____XXXX,____XX__,___XX___,
+ _XXXXXXX,____XX__,__XXX___,
+ __XX_XXX,_____XX_,__XX____,
+ _____XXX,_____XX_,_XXX____,
+ _____XXX,______XX,_XX_____,
+ _____XXX,______XX,XXX_____,
+ _____XXX,_______X,XX______,
+ _____XXX,______XX,XXX_____,
+ __XX_XXX,____XXX_,_XXXX___,
+ ___XXXXX,__XXX___,__XXXXXX,
+ _____XX_,XXX_____,____XX__,
+ ________,________,________,
+};
+
+/* char: 计 code:0xBCC6 */
+static GUI_CONST_STORAGE unsigned char acBCC6[72] = {
+ ________,________,________,
+ ________,________,________,
+ ____XX__,______XX,________,
+ _____XXX,______XX,X_______,
+ ______XX,______XX,X_______,
+ ______XX,______XX,X_______,
+ ________,______XX,X_______,
+ ________,______XX,X_______,
+ ________,______XX,X_______,
+ _XXXXXXX,______XX,X____XX_,
+ _____XX_,XXXXXXXX,XXXXXXX_,
+ _____XX_,______XX,X_______,
+ _____XX_,______XX,X_______,
+ _____XX_,______XX,X_______,
+ _____XX_,______XX,X_______,
+ _____XX_,______XX,X_______,
+ _____XX_,_XX___XX,X_______,
+ _____XX_,XX____XX,X_______,
+ _____XXX,X_____XX,X_______,
+ _____XXX,X_____XX,X_______,
+ _____XXX,______XX,X_______,
+ ________,______XX,X_______,
+ ________,______XX,X_______,
+ ________,________,________,
+};
+
+/* char: 加 code:0xBCD3 */
+static GUI_CONST_STORAGE unsigned char acBCD3[72] = {
+ ________,________,________,
+ ______XX,________,________,
+ ______XX,________,________,
+ ______XX,________,________,
+ ______XX,________,________,
+ ______XX,________,________,
+ _XXXXXXX,XXXXX_XX,XXXXXXX_,
+ ______XX,__XXX_XX,____XX__,
+ ______XX,__XXX_XX,____XX__,
+ ______XX,__XXX_XX,____XX__,
+ ______XX,__XXX_XX,____XX__,
+ _____XXX,__XX__XX,____XX__,
+ _____XXX,__XX__XX,____XX__,
+ _____XX_,__XX__XX,____XX__,
+ _____XX_,__XX__XX,____XX__,
+ _____XX_,__XX__XX,____XX__,
+ ____XXX_,__XX__XX,____XX__,
+ ____XX__,__XX__XX,____XX__,
+ ____XX__,__XX__XX,____XX__,
+ ___XXXXX,_XXX__XX,XXXXXX__,
+ ___XX__X,XXX___XX,____XXX_,
+ __XX____,XX____XX,____XXX_,
+ _XX_____,______XX,________,
+ ________,________,________,
+};
+
+/* char: 检 code:0xBCEC */
+static GUI_CONST_STORAGE unsigned char acBCEC[72] = {
+ ________,________,________,
+ _____XX_,______XX,________,
+ _____XX_,______XX,________,
+ _____XX_,_____XXX,X_______,
+ _____XX_,_____XXX,X_______,
+ _____XX_,____XXX_,XX______,
+ _XXXXXXX,XXX_XX__,_XX_____,
+ _____XX_,___XX___,__XXX___,
+ ____XXX_,__XX____,___XXXX_,
+ ____XXXX,_XX_____,____XX__,
+ ____XXXX,XXXXXXXX,XXXX____,
+ ____XXXX,XX______,________,
+ ___XXXX_,XX___XX_,__XXX___,
+ ___XXXX_,______XX,__XXX___,
+ __XX_XX_,__XX__XX,__XXX___,
+ __XX_XX_,__XX__XX,X_XX____,
+ _XX__XX_,___XX_XX,X_XX____,
+ _____XX_,___XX__X,XXXX____,
+ _____XX_,___XX___,_XX_____,
+ _____XX_,___XX___,_XX_____,
+ _____XX_,________,XX______,
+ _____XX_,XXXXXXXX,XXXXXXX_,
+ _____XX_,________,________,
+ ________,________,________,
+};
+
+/* char: 键 code:0xBCFC */
+static GUI_CONST_STORAGE unsigned char acBCFC[72] = {
+ ________,________,________,
+ ____XX__,________,XX______,
+ ____XXX_,________,XXX_____,
+ ____XX__,________,XX______,
+ ___XXX__,XXXXXXXX,XXXXXX__,
+ ___XXXXX,X__XX___,XX__XX__,
+ ___XX___,__XXXXXX,XXXXXXX_,
+ __XX____,__XX____,XX__XX__,
+ __XXXXXX,X_XX____,XX__XX__,
+ _XX_XX__,_XX___XX,XXXXXX__,
+ ____XX__,XXXXXX__,XX______,
+ ____XX__,_XX_XX__,XX______,
+ ____XX__,____XXXX,XXXXXX__,
+ _XXXXXXX,XX__XX__,XX______,
+ ____XX__,_XXXXX__,XX______,
+ ____XX__,_XXXX___,XX______,
+ ____XX__,_XXXXXXX,XXXXXXX_,
+ ____XX__,__XXX___,XX______,
+ ____XX_X,X_XX____,XX______,
+ ____XXXX,_XXXXX__,XXX_____,
+ ____XXX_,XXX_XXXX,XX___XXX,
+ _______X,X______X,XXXXXXX_,
+ ______XX,________,________,
+ ________,________,________,
+};
+
+/* char: 件 code:0xBCFE */
+static GUI_CONST_STORAGE unsigned char acBCFE[72] = {
+ ________,________,________,
+ _______X,X______X,X_______,
+ ______XX,XX_____X,X_______,
+ ______XX,X______X,X_______,
+ ______XX,__XXX__X,X_______,
+ _____XXX,__XXX__X,X_______,
+ _____XX_,__XX___X,X_______,
+ ____XXX_,__XXXXXX,XXXXXX__,
+ ____XXX_,__XX___X,X_______,
+ ___XXXX_,_XX____X,X_______,
+ ___XXXX_,_XX____X,X_______,
+ __XX_XX_,XX_____X,X_______,
+ _XX__XX_,XX_____X,X_______,
+ _____XX_,XXXXXXXX,XXXXXXX_,
+ _____XX_,_______X,X_______,
+ _____XX_,_______X,X_______,
+ _____XX_,_______X,X_______,
+ _____XX_,_______X,X_______,
+ _____XX_,_______X,X_______,
+ _____XX_,_______X,X_______,
+ _____XX_,_______X,X_______,
+ _____XX_,_______X,X_______,
+ _____XX_,_______X,X_______,
+ ________,________,________,
+};
+
+/* char: 江 code:0xBDAD */
+static GUI_CONST_STORAGE unsigned char acBDAD[72] = {
+ ________,________,________,
+ ________,________,________,
+ ________,________,________,
+ ___XX___,________,________,
+ ____XX__,________,____XX__,
+ ____XXX_,XXXXXXXX,XXXXXX__,
+ _____XXX,X_____XX,________,
+ _______X,X_____XX,________,
+ _XX____X,X_____XX,________,
+ __XXX_XX,______XX,________,
+ ___XX_XX,______XX,________,
+ ___XX_XX,______XX,________,
+ _____XX_,______XX,________,
+ _____XX_,______XX,________,
+ _____XX_,______XX,________,
+ ____XX__,______XX,________,
+ __XXXX__,______XX,________,
+ ___XXX__,______XX,________,
+ ___XXX__,______XX,________,
+ ___XXX__,______XX,_____XX_,
+ ___XXXXX,XXXXXXXX,XXXXXXXX,
+ ___XXX__,________,________,
+ ________,________,________,
+ ________,________,________,
+};
+
+/* char: 阶 code:0xBDD7 */
+static GUI_CONST_STORAGE unsigned char acBDD7[72] = {
+ ________,________,________,
+ ________,______XX,________,
+ ________,_____XXX,________,
+ __XXXXXX,XX___XXX,X_______,
+ __XX___X,X___XXXX,X_______,
+ __XX__XX,X___XX__,XX______,
+ __XX__XX,___XXX__,_XX_____,
+ __XX__XX,___XX___,_XXX____,
+ __XX_XX_,__XX____,__XXXX__,
+ __XX_XX_,XXXXX___,____XXXX,
+ __XX_XX_,___XXX__,_XX_____,
+ __XX__XX,___XXX__,_XX_____,
+ __XX___X,X__XXX__,_XX_____,
+ __XX___X,X__XXX__,_XX_____,
+ __XX___X,XX_XXX__,_XX_____,
+ __XX___X,X__XXX__,_XX_____,
+ __XXXXXX,X__XXX__,_XX_____,
+ __XX_XXX,___XX___,_XX_____,
+ __XX____,___XX___,_XX_____,
+ __XX____,__XXX___,_XX_____,
+ __XX____,__XX____,_XX_____,
+ __XX____,XXX_____,_XX_____,
+ __XX___X,X_______,________,
+ ________,________,________,
+};
+
+/* char: 进 code:0xBDF8 */
+static GUI_CONST_STORAGE unsigned char acBDF8[72] = {
+ ________,________,________,
+ ________,________,________,
+ ________,________,XX______,
+ ____XX__,____XX__,_XX_____,
+ ____XXX_,____XX__,_XX_____,
+ _____XXX,____XX__,_XX_____,
+ _____XX_,____XX__,_XX_XX__,
+ ________,XXXXXXXX,XXXXXXX_,
+ ________,____XX__,_XX_____,
+ _____XX_,____XX__,_XX_____,
+ _XXXXXXX,____XX__,_XX_____,
+ _____XX_,____XX__,_XX_____,
+ _____XXX,XXXXXXXX,XXXXXXX_,
+ _____XX_,____XX__,_XX_____,
+ _____XX_,___XXX__,_XX_____,
+ _____XX_,___XX___,_XX_____,
+ _____XX_,___XX___,_XX_____,
+ _____XX_,__XX____,_XX_____,
+ _____XX_,_XX_____,_XX_____,
+ ____XXXX,XX______,_XX_____,
+ __XXX__X,X_______,________,
+ _XXX____,XXXXXXX_,__XXXXXX,
+ ________,___XXXXX,XXXXXX__,
+ ________,________,________,
+};
+
+/* char: 据 code:0xBEDD */
+static GUI_CONST_STORAGE unsigned char acBEDD[72] = {
+ ________,________,________,
+ ________,________,________,
+ _____XX_,________,________,
+ _____XXX,__XXXXXX,XXXXXX__,
+ _____XX_,__XXX___,___XXX__,
+ _____XX_,__XXX___,___XXX__,
+ _____XX_,XXXXX___,___XXX__,
+ _XXXXXXX,XXXXXXXX,XXXXXX__,
+ _____XX_,__XXX___,XX_XXX__,
+ _____XX_,__XX____,XX______,
+ _____XX_,_XXX____,XX______,
+ _____XXX,XXXXXXXX,XXXXXXX_,
+ _____XXX,__XX____,XX______,
+ ____XXX_,__XX____,XX______,
+ _XXXXXX_,__XX____,XX______,
+ __XX_XX_,_XXXXXXX,XXXXXX__,
+ _____XX_,_XX_XX__,___XXX__,
+ _____XX_,_XX_XX__,___XXX__,
+ _____XX_,XX__XX__,___XXX__,
+ _____XX_,XX__XX__,___XXX__,
+ _____XXX,X___XXXX,XXXXXX__,
+ __XXXXXX,____XX__,___XXX__,
+ ____XXX_,____XX__,___XX___,
+ ________,________,________,
+};
+
+/* char: 巨 code:0xBEDE */
+static GUI_CONST_STORAGE unsigned char acBEDE[72] = {
+ ________,________,________,
+ ________,________,________,
+ ________,________,___XX___,
+ ____XXXX,XXXXXXXX,XXXXXX__,
+ ____XX__,________,________,
+ ____XX__,________,________,
+ ____XX__,________,________,
+ ____XX__,________,________,
+ ____XXXX,XXXXXXXX,XXXXX___,
+ ____XX__,________,__XX____,
+ ____XX__,________,__XX____,
+ ____XX__,________,__XX____,
+ ____XX__,________,__XX____,
+ ____XX__,________,__XX____,
+ ____XX__,________,__XX____,
+ ____XXXX,XXXXXXXX,XXXX____,
+ ____XX__,________,__XX____,
+ ____XX__,________,________,
+ ____XX__,________,________,
+ ____XX__,________,________,
+ ____XX__,________,____XX__,
+ ____XXXX,XXXXXXXX,XXXXXXX_,
+ ____XX__,________,________,
+ ________,________,________,
+};
+
+/* char: 控 code:0xBFD8 */
+static GUI_CONST_STORAGE unsigned char acBFD8[72] = {
+ ________,________,________,
+ _____XX_,________,________,
+ _____XXX,______XX,________,
+ _____XX_,_______X,XX______,
+ _____XX_,_______X,X_______,
+ _____XX_,__XXXXXX,XXXXXXX_,
+ _XXXXXXX,XXXX____,____XXX_,
+ _____XX_,_XXX_XX_,____XX__,
+ _____XX_,_____XXX,XXX_____,
+ _____XX_,____XXX_,__XXX___,
+ _____XX_,XX_XXX__,___XXX__,
+ _____XXX,X_XX____,____XX__,
+ ____XXXX,_XX_____,____XX__,
+ _XXXXXX_,__XXXXXX,XXXXX___,
+ _XXX_XX_,______XX,X_______,
+ _____XX_,______XX,X_______,
+ _____XX_,______XX,X_______,
+ _____XX_,______XX,X_______,
+ _____XX_,______XX,X_______,
+ _____XX_,______XX,X_______,
+ _____XX_,XXXXXXXX,XXXXXXX_,
+ __XXXXX_,________,________,
+ ____XX__,________,________,
+ ________,________,________,
+};
+
+/* char: 括 code:0xC0A8 */
+static GUI_CONST_STORAGE unsigned char acC0A8[72] = {
+ ________,________,________,
+ _____XX_,________,________,
+ _____XXX,________,________,
+ _____XXX,________,_XXXXX__,
+ _____XXX,___XXXXX,XX______,
+ _____XXX,_______X,X_______,
+ _XXXXXXX,XXX____X,X_______,
+ _____XXX,_______X,X_______,
+ _____XXX,_______X,X____XX_,
+ _____XXX,_XXXXXXX,XXXXXXXX,
+ _____XXX,_______X,X_______,
+ _____XXX,XXX____X,X_______,
+ _____XXX,X______X,X_______,
+ __XXXXXX,___XXXXX,XXXXXX__,
+ _XXX_XXX,___XX___,___XXX__,
+ _____XXX,___XX___,___XXX__,
+ _____XXX,___XX___,___XXX__,
+ _____XXX,___XX___,___XXX__,
+ _____XXX,___XX___,___XXX__,
+ _____XXX,___XXXXX,XXXXXX__,
+ __XX_XXX,___XX___,___XXX__,
+ ___XXXXX,___XX___,___XXX__,
+ _____XX_,________,________,
+ ________,________,________,
+};
+
+/* char: 量 code:0xC1BF */
+static GUI_CONST_STORAGE unsigned char acC1BF[72] = {
+ ________,________,________,
+ ________,________,________,
+ _____XXX,XXXXXXXX,XXX_____,
+ _____XXX,________,_XX_____,
+ _____XXX,XXXXXXXX,XXX_____,
+ _____XXX,________,_XX_____,
+ _____XXX,________,_XX_____,
+ _____XXX,XXXXXXXX,XXX_____,
+ _____XXX,________,_XX__XX_,
+ _XXXXXXX,XXXXXXXX,XXXXXXXX,
+ ________,________,________,
+ _____XXX,XXXXXXXX,XXXX____,
+ _____XX_,___XXX__,_XXX____,
+ _____XXX,XXXXXXXX,XXXX____,
+ _____XX_,___XXX__,_XXX____,
+ _____XX_,___XXX__,_XXX____,
+ _____XXX,XXXXXXXX,XXXX____,
+ _____XX_,___XXX__,_XXX____,
+ ___XXXXX,XXXXXXXX,XXXXX___,
+ ________,___XXX__,________,
+ ________,___XXX__,_____XX_,
+ _XXXXXXX,XXXXXXXX,XXXXXXX_,
+ ________,________,________,
+ ________,________,________,
+};
+
+/* char: 流 code:0xC1F7 */
+static GUI_CONST_STORAGE unsigned char acC1F7[72] = {
+ ________,________,________,
+ ________,____XX__,________,
+ ___XX___,_____XXX,________,
+ ____XXX_,______XX,____XX__,
+ _____XXX,XXXXXXXX,XXXXXXX_,
+ _____XXX,_____XXX,________,
+ ________,XX__XXX_,________,
+ _______X,X___XX__,_XX_____,
+ _XXX___X,X__XX___,__XX____,
+ __XXX__X,X_XX___X,XXXXX___,
+ ___XX_XX,_XXXXXXX,___XX___,
+ ___XX_XX,________,___XX___,
+ ______XX,_XXX_XXX,_XXX____,
+ _____XX_,_XXX_XX_,_XX_____,
+ _____XX_,_XXX_XX_,_XX_____,
+ ____XX__,_XXX_XX_,_XX_____,
+ _XXXXX__,_XXX_XX_,_XX_____,
+ ___XXX__,_XX__XX_,_XX_____,
+ ___XXX__,_XX__XX_,_XX__XX_,
+ ___XXX__,XXX__XX_,_XX__XX_,
+ ___XXX__,XX___XX_,_XX__XXX,
+ ___XXX_X,X____XX_,_XXXXXX_,
+ _____XXX,_____XX_,________,
+ ________,________,________,
+};
+
+/* char: 码 code:0xC2EB */
+static GUI_CONST_STORAGE unsigned char acC2EB[72] = {
+ ________,________,________,
+ ________,________,________,
+ ________,________,___XX___,
+ _XXXXXXX,XXXXXXXX,XXXXXX__,
+ _____XX_,________,___XX___,
+ ____XXX_,____XXX_,___XX___,
+ ____XX__,____XXX_,___XX___,
+ ____XX__,____XX__,__XXX___,
+ ____XX__,____XX__,__XXX___,
+ ___XXXXX,XX__XX__,__XX____,
+ ___XXX_X,XX__XX__,__XX____,
+ __XXXX_X,XX__XX__,__XX____,
+ __XXXX_X,XX_XXXXX,XXXXXXX_,
+ _XXXXX_X,XX__XX__,_____XX_,
+ ___XXX_X,XX______,_____XX_,
+ ___XXX_X,XX______,_____XX_,
+ ___XXX_X,XXXXXXXX,XXXXXXX_,
+ ___XXXXX,XX______,____XXX_,
+ ___XXX_X,XX______,____XX__,
+ ___XXX_X,X_______,____XX__,
+ ___XXX__,________,XX__XX__,
+ ________,________,_XXXXX__,
+ ________,________,__XXX___,
+ ________,________,________,
+};
+
+/* char: 满 code:0xC2FA */
+static GUI_CONST_STORAGE unsigned char acC2FA[72] = {
+ ________,________,________,
+ ________,____XX__,XX______,
+ ___XX___,____XX__,XX______,
+ ____XXX_,____XX__,XX______,
+ _____XX_,XXXXXXXX,XXXXXXX_,
+ _____XX_,____XX__,XX______,
+ ________,____XX__,XX______,
+ _XX___XX,________,________,
+ __XXX_XX,XXXXXXXX,XXXXXXX_,
+ ___XX_XX,____XX__,XX______,
+ ___XXXX_,____XX__,XX______,
+ _____XX_,XXXXXXXX,XXXXXXX_,
+ _____XX_,XX__XX__,XX__XX__,
+ _____XX_,XX__XX__,XX__XX__,
+ ____XX__,XX__XXX_,XX__XX__,
+ ____XX__,XX__XXXX,XXX_XX__,
+ __XXXX__,XX_XX_XX,X_XXXX__,
+ ___XXX__,XX_XX__X,X_XXXX__,
+ ___XXX__,XXXX__XX,____XX__,
+ ___XXX__,XXX__XX_,____XX__,
+ ___XXX__,XX______,____XX__,
+ ___XXX__,XX______,__XXXX__,
+ ________,XX______,___XX___,
+ ________,________,________,
+};
+
+/* char: 门 code:0xC3C5 */
+static GUI_CONST_STORAGE unsigned char acC3C5[72] = {
+ ________,________,________,
+ ________,________,________,
+ ______XX,________,________,
+ ______XX,X_______,________,
+ _______X,XX_XXXXX,XXXXXX__,
+ _______X,XX______,___XXX__,
+ ____XX__,________,___XXX__,
+ ____XX__,________,___XXX__,
+ ____XX__,________,___XXX__,
+ ____XX__,________,___XXX__,
+ ____XX__,________,___XXX__,
+ ____XX__,________,___XXX__,
+ ____XX__,________,___XXX__,
+ ____XX__,________,___XXX__,
+ ____XX__,________,___XXX__,
+ ____XX__,________,___XXX__,
+ ____XX__,________,___XXX__,
+ ____XX__,________,___XXX__,
+ ____XX__,________,___XXX__,
+ ____XX__,________,___XXX__,
+ ____XX__,_______X,XX_XXX__,
+ ____XX__,________,_XXXX___,
+ ____XX__,________,__XX____,
+ ________,________,________,
+};
+
+/* char: 密 code:0xC3DC */
+static GUI_CONST_STORAGE unsigned char acC3DC[72] = {
+ ________,________,________,
+ ________,__XX____,________,
+ ________,___XXX__,________,
+ ________,___XXX__,________,
+ ___XXXXX,XXXXXXXX,XXXXXXX_,
+ ___XX___,_XX_____,____XX__,
+ __XXX___,__XXX___,XX_XX___,
+ __XX____,XX_XX__X,XX______,
+ ________,XX_XX_XX,X_______,
+ _____XX_,XX__XXX_,__XXX___,
+ ____XX__,XX_XXX__,XX_XXX__,
+ ___XXX__,XXXX____,XX__XX__,
+ _______X,XXX_____,XX__XX__,
+ ____XXXX,XXXXXXXX,XX______,
+ _XXXX___,________,________,
+ ________,___XX___,________,
+ ________,___XXX__,________,
+ _____XXX,___XX___,__XXX___,
+ _____XX_,___XX___,__XX____,
+ _____XX_,___XX___,__XX____,
+ _____XX_,___XX___,__XX____,
+ ____XXXX,XXXXXXXX,XXXX____,
+ ________,________,__XX____,
+ ________,________,________,
+};
+
+/* char: 面 code:0xC3E6 */
+static GUI_CONST_STORAGE unsigned char acC3E6[72] = {
+ ________,________,________,
+ ________,________,________,
+ ________,________,_____XX_,
+ _XXXXXXX,XXXXXXXX,XXXXXXXX,
+ ________,__XXX___,________,
+ ________,__XX____,________,
+ ________,__XX____,________,
+ ___XXXXX,XXXXXXXX,XXXXXX__,
+ ___XXX__,_XX___XX,___XXX__,
+ ___XXX__,_XX___XX,___XXX__,
+ ___XXX__,_XX___XX,___XXX__,
+ ___XXX__,_XXXXXXX,___XXX__,
+ ___XXX__,_XX___XX,___XXX__,
+ ___XXX__,_XX___XX,___XXX__,
+ ___XXX__,_XX___XX,___XXX__,
+ ___XXX__,_XX___XX,___XXX__,
+ ___XXX__,_XXXXXXX,___XXX__,
+ ___XXX__,_XX___XX,___XXX__,
+ ___XXX__,_XX___XX,___XXX__,
+ ___XXX__,_XX___XX,___XXX__,
+ ___XXXXX,XXXXXXXX,XXXXXX__,
+ ___XXX__,________,___XXX__,
+ ___XX___,________,___XX___,
+ ________,________,________,
+};
+
+/* char: 秒 code:0xC3EB */
+static GUI_CONST_STORAGE unsigned char acC3EB[72] = {
+ ________,________,________,
+ ________,________,XX______,
+ ________,XXX_____,XX______,
+ ____XXXX,XX______,XX______,
+ __XXX_XX,________,XX______,
+ ______XX,________,XX______,
+ ______XX,____XXX_,XX_XX___,
+ ______XX,____XXX_,XX__XX__,
+ _XXXXXXX,XXX_XX__,XX__XXX_,
+ _____XXX,____XX__,XX___XX_,
+ _____XXX,___XXX__,XX___XX_,
+ _____XXX,XX_XX___,XX______,
+ ____XXXX,XXXXX___,XX__XX__,
+ ____XXXX,XXXX____,XX_XXXX_,
+ ___XX_XX,________,XX_XXX__,
+ __XX__XX,________,XXXXX___,
+ __XX__XX,________,_XXX____,
+ _XX___XX,________,XXX_____,
+ ______XX,_______X,XX______,
+ ______XX,______XX,X_______,
+ ______XX,____XXX_,________,
+ ______XX,_XXXX___,________,
+ ________,XX______,________,
+ ________,________,________,
+};
+
+/* char: 默 code:0xC4AC */
+static GUI_CONST_STORAGE unsigned char acC4AC[72] = {
+ ________,________,________,
+ ________,_______X,X_______,
+ ________,_______X,XX______,
+ __XXXXXX,XXXX___X,X_XX____,
+ __XX__XX,_XXX___X,X__XXX__,
+ __XX__XX,XXXX___X,X__XXX__,
+ __XXXXXX,XXXX___X,X___XX__,
+ __XXXXXX,_XXX___X,X____XX_,
+ __XXXXXX,XXXXXXXX,XXXXXXX_,
+ __XX__XX,_XXX___X,XX______,
+ ______XX,_______X,XXX_____,
+ ______XX,_______X,XXX_____,
+ __XXXXXX,XXXX___X,XXX_____,
+ ______XX,_______X,XXX_____,
+ ______XX,_______X,XXX_____,
+ ______XX,XXXX__XX,XXX_____,
+ ___XXXXX,X_____XX,__XX____,
+ __XXX___,__XX__XX,__XX____,
+ _______X,X__XXXXX,__XXX___,
+ _____XX_,XX_XXXX_,___XX___,
+ __XX_XXX,XX__XX__,___XXX__,
+ __XX_XXX,___XX___,____XXX_,
+ __XX____,__XX____,____XX__,
+ ________,_XX_____,________,
+};
+
+/* char: 目 code:0xC4BF */
+static GUI_CONST_STORAGE unsigned char acC4BF[72] = {
+ ________,________,________,
+ ________,________,________,
+ ________,________,_XX_____,
+ ______XX,XXXXXXXX,XXXX____,
+ ______XX,________,_XX_____,
+ ______XX,________,_XX_____,
+ ______XX,________,_XX_____,
+ ______XX,________,_XX_____,
+ ______XX,XXXXXXXX,XXX_____,
+ ______XX,________,_XX_____,
+ ______XX,________,_XX_____,
+ ______XX,________,_XX_____,
+ ______XX,________,_XX_____,
+ ______XX,XXXXXXXX,XXX_____,
+ ______XX,________,_XX_____,
+ ______XX,________,_XX_____,
+ ______XX,________,_XX_____,
+ ______XX,________,_XX_____,
+ ______XX,________,_XX_____,
+ ______XX,XXXXXXXX,XXX_____,
+ ______XX,________,_XX_____,
+ ______XX,________,_XXX____,
+ ________,________,_XX_____,
+ ________,________,________,
+};
+
+/* char: 能 code:0xC4DC */
+static GUI_CONST_STORAGE unsigned char acC4DC[72] = {
+ ________,________,________,
+ ______XX,________,________,
+ ______XX,X_____XX,X_______,
+ _____XXX,______XX,___XX___,
+ _____XX_,_XX___XX,__XXXX__,
+ ____XX__,__XX__XX,_XXX____,
+ __XXX___,XXXXX_XX,XX______,
+ __XXXXXX,X__XX_XX,________,
+ ________,___XX_XX,_____XX_,
+ ___XXXXX,XXXX__XX,_____XX_,
+ ___XXX__,_XXX__XX,XXXXXXX_,
+ ___XXX__,_XXX____,________,
+ ___XXXXX,XXXX_XX_,________,
+ ___XXX__,_XXX__XX,___XX___,
+ ___XXX__,_XXX__XX,__XXXX__,
+ ___XXX__,_XXX__XX,_XXX____,
+ ___XXXXX,XXXX__XX,XX______,
+ ___XXX__,_XXX__XX,_____XX_,
+ ___XXX__,_XXX__XX,_____XX_,
+ ___XXX__,_XXX__XX,_____XX_,
+ ___XXX__,_XXX__XX,_____XXX,
+ ___XXX_X,XXXX__XX,XXXXXXX_,
+ ___XX___,_XX_____,________,
+ ________,________,________,
+};
+
+/* char: 配 code:0xC5E4 */
+static GUI_CONST_STORAGE unsigned char acC5E4[72] = {
+ ________,________,________,
+ ________,________,________,
+ ________,___XX___,____XX__,
+ _XXXXXXX,XXXXXXXX,XXXXXXX_,
+ _____XX_,XX______,____XX__,
+ _____XX_,XX______,____XX__,
+ __XXXXXX,XXXXX___,____XX__,
+ __XXXXX_,XXXXX___,____XX__,
+ __XXXXX_,XXXXX___,____XX__,
+ __XXXXX_,XXXXX___,____XX__,
+ __XXXXX_,XXXXX_XX,XXXXXX__,
+ __XXXXX_,XXXXX_XX,____XX__,
+ __XXXX__,XXXXX_XX,________,
+ __XXX___,XXXXX_XX,________,
+ __XXX___,__XXX_XX,________,
+ __XXXXXX,XXXXX_XX,________,
+ __XXX___,__XXX_XX,_____XX_,
+ __XXX___,__XXX_XX,_____XX_,
+ __XXX___,__XXX_XX,_____XX_,
+ __XXX___,__XXX_XX,_____XX_,
+ __XXXXXX,XXXXX_XX,_____XXX,
+ __XXX___,__XXX_XX,XXXXXXX_,
+ __XXX___,__XX____,________,
+ ________,________,________,
+};
+
+/* char: 坡 code:0xC6C2 */
+static GUI_CONST_STORAGE unsigned char acC6C2[72] = {
+ ________,________,________,
+ _____XX_,_______X,X_______,
+ _____XX_,_______X,X_______,
+ _____XX_,_______X,X_______,
+ _____XX_,_______X,X_______,
+ _____XX_,__XXXXXX,XXXXXXX_,
+ _____XX_,__XXX__X,X___XXX_,
+ _____XX_,__XXX__X,X__XX___,
+ _XXXXXXX,XXXXX__X,X_______,
+ _____XX_,__XXX__X,X_______,
+ _____XX_,__XXX__X,X_______,
+ _____XX_,__XXXXXX,XXXXX___,
+ _____XX_,__XX_XX_,__XXX___,
+ _____XX_,__XX_XX_,__XX____,
+ _____XX_,__XX__XX,__XX____,
+ _____XXX,XXXX__XX,_XXX____,
+ ____XXXX,__XX___X,XXX_____,
+ _XXXX___,_XX____X,XX______,
+ __XX____,_XX____X,XX______,
+ ________,XX____XX,_XXX____,
+ ________,XX__XXX_,__XXXX__,
+ _______X,X_XXX___,___XXXXX,
+ ______XX,_XX_____,________,
+ ________,________,________,
+};
+
+/* char: 启 code:0xC6F4 */
+static GUI_CONST_STORAGE unsigned char acC6F4[72] = {
+ ________,________,________,
+ ________,___XX___,________,
+ ________,____XX__,________,
+ ________,____XXX_,________,
+ _____XXX,XXXXXXXX,XXXXX___,
+ _____XX_,________,__XXX___,
+ _____XX_,________,__XXX___,
+ _____XX_,________,__XXX___,
+ _____XX_,________,__XXX___,
+ _____XXX,XXXXXXXX,XXXXX___,
+ _____XX_,________,__XXX___,
+ _____XX_,________,________,
+ _____XX_,________,________,
+ _____XX_,XXXXXXXX,XXXXX___,
+ _____XX_,XX______,__XXX___,
+ _____XX_,XX______,__XXX___,
+ ____XXX_,XX______,__XXX___,
+ ____XX__,XX______,__XXX___,
+ ____XX__,XX______,__XXX___,
+ ___XXX__,XX______,__XXX___,
+ ___XX___,XXXXXXXX,XXXXX___,
+ __XX____,XX______,__XXX___,
+ _XX_____,XX______,__XX____,
+ ________,________,________,
+};
+
+/* char: 器 code:0xC6F7 */
+static GUI_CONST_STORAGE unsigned char acC6F7[72] = {
+ ________,________,________,
+ ________,________,________,
+ ____XXXX,XXX__XXX,XXXXX___,
+ ____XXX_,_XXX_XXX,__XXX___,
+ ____XXX_,_XXX_XXX,__XXX___,
+ ____XXX_,_XXX_XXX,__XXX___,
+ ____XXX_,_XXX_XXX,__XXX___,
+ ____XXXX,XXXX_XXX,XXXXX___,
+ ____XXX_,_XXXXXXX,XXXXX___,
+ ____XX__,__XXX___,XXX_XX__,
+ __XXXXXX,XXXXXXXX,XXXXXXX_,
+ ________,_XX___XX,________,
+ ________,XX_____X,X_______,
+ _______X,X_______,XX______,
+ _____XXX,________,_XXXX___,
+ ____XXXX,XXXX_XXX,XXXXXXX_,
+ __XXXXX_,_XXX_XX_,__XXX___,
+ _____XX_,_XXX_XX_,__XXX___,
+ _____XX_,_XXX_XX_,__XXX___,
+ _____XX_,_XXX_XX_,__XXX___,
+ _____XXX,XXXX_XXX,XXXXX___,
+ _____XX_,_XXX_XX_,__XXX___,
+ ____XX__,_XX__XX_,__XX____,
+ ________,________,________,
+};
+
+/* char: 前 code:0xC7B0 */
+static GUI_CONST_STORAGE unsigned char acC7B0[72] = {
+ ________,________,________,
+ _______X,X_______,________,
+ ________,XX_____X,XX______,
+ ________,XXX____X,X_______,
+ ________,_XX___XX,____XX__,
+ _XXXXXXX,XXXXXXXX,XXXXXXX_,
+ ________,________,________,
+ ________,________,__XX____,
+ ____XXXX,XXXX__XX,__XXX___,
+ ____XX__,__XX__XX,X_XXX___,
+ ____XX__,__XX__XX,__XXX___,
+ ____XX__,__XX__XX,__XXX___,
+ ____XXXX,XXXX__XX,__XXX___,
+ ____XX__,__XX__XX,__XXX___,
+ ____XX__,__XX__XX,__XXX___,
+ ____XX__,__XX__XX,__XXX___,
+ ____XXXX,XXXX__XX,__XXX___,
+ ____XX__,__XX__XX,__XXX___,
+ ____XX__,__XX__XX,X_XXX___,
+ ____XX__,__XX____,__XXX___,
+ ____XX__,__XX___X,X_XXX___,
+ ____XX_X,XXXX____,XXXX____,
+ ____XX__,_XX_____,_XX_____,
+ ________,________,________,
+};
+
+/* char: 请 code:0xC7EB */
+static GUI_CONST_STORAGE unsigned char acC7EB[72] = {
+ ________,________,________,
+ ________,______XX,________,
+ ____XX__,______XX,X_______,
+ ____XXX_,______XX,X___XX__,
+ ____XXX_,XXXXXXXX,XXXXXXX_,
+ _____XX_,______XX,X__XX___,
+ ________,__XXXXXX,XXXXXX__,
+ ________,______XX,X_______,
+ ________,______XX,X____XX_,
+ _XXXXXXX,XXXXXXXX,XXXXXXX_,
+ ____XXX_,________,________,
+ ____XXX_,________,________,
+ ____XXX_,__XXXXXX,XXXXX___,
+ ____XXX_,__XXX___,___XX___,
+ ____XXX_,__XXXXXX,XXXXX___,
+ ____XXX_,__XXX___,___XX___,
+ ____XXX_,XXXXX___,___XX___,
+ ____XXXX,X_XXXXXX,XXXXX___,
+ ____XXXX,__XXX___,___XX___,
+ ____XXXX,__XXX___,___XX___,
+ ____XXX_,__XXX___,___XX___,
+ ________,__XXX___,XXXXX___,
+ ________,__XX____,__XX____,
+ ________,________,________,
+};
+
+/* char: 求 code:0xC7F3 */
+static GUI_CONST_STORAGE unsigned char acC7F3[72] = {
+ ________,________,________,
+ ________,___XX___,________,
+ ________,___XXX_X,XX______,
+ ________,___XX___,XXX_____,
+ ________,___XX___,_XXX____,
+ ________,___XX___,_XX_XX__,
+ __XXXXXX,XXXXXXXX,XXXXXXX_,
+ ________,___XXX__,________,
+ ________,___XXX__,________,
+ ____XXX_,___XXX__,___XX___,
+ _____XXX,___XXXX_,__XXXX__,
+ ______XX,X__XXXX_,_XXX____,
+ _______X,X__XX_XX,XX______,
+ ________,___XX_XX,X_______,
+ ________,_XXXX_XX,X_______,
+ ________,XX_XX__X,XX______,
+ ______XX,X__XX___,XXX_____,
+ ____XXX_,___XX___,XXXX____,
+ _XXXXX__,___XX___,_XXXXX__,
+ __XX____,___XX___,__XXXXXX,
+ _______X,XX_XX___,____XX__,
+ ________,_XXXX___,________,
+ ________,__XX____,________,
+ ________,________,________,
+};
+
+/* char: 驱 code:0xC7FD */
+static GUI_CONST_STORAGE unsigned char acC7FD[72] = {
+ ________,________,________,
+ ________,________,________,
+ ________,________,________,
+ __XXXXXX,XX______,_____XX_,
+ ________,XXX_XXXX,XXXXXXX_,
+ ________,XX__XX__,________,
+ ____XX__,XX__XX__,________,
+ ____XX__,XX__XX__,____XX__,
+ ___XXX__,XX__XXXX,____XXX_,
+ ___XXX__,XX__XX_X,X__XXX__,
+ ___XX___,XX__XX__,XX_XX___,
+ ___XX__X,XX__XX__,_XXXX___,
+ ___XX__X,XX__XX__,_XXX____,
+ ___XXXXX,XXXXXX__,_XXX____,
+ ___XX___,__XXXX__,_XXXX___,
+ ________,_XXXXX__,XX_XXX__,
+ ________,XXX_XX__,XX__XX__,
+ _____XXX,XXX_XX_X,X___XX__,
+ _XXXXX__,_XX_XXXX,________,
+ ________,_XX_XX__,________,
+ ________,XXX_XX__,_____XX_,
+ ______XX,XX__XXXX,XXXXXXXX,
+ _______X,X___XX__,________,
+ ________,________,________,
+};
+
+/* char: 取 code:0xC8A1 */
+static GUI_CONST_STORAGE unsigned char acC8A1[72] = {
+ ________,________,________,
+ ________,________,________,
+ ________,___XX___,________,
+ _XXXXXXX,XXXXX___,________,
+ ____XX__,_XX_____,________,
+ ____XX__,_XXXXXXX,XXXXXX__,
+ ____XX__,_XX__XX_,___XX___,
+ ____XXXX,XXX__XX_,___XX___,
+ ____XX__,_XX__XX_,___XX___,
+ ____XX__,_XX___XX,__XXX___,
+ ____XX__,_XX___XX,__XX____,
+ ____XX__,_XX___XX,__XX____,
+ ____XXXX,XXX___XX,_XXX____,
+ ____XX__,_XX____X,XXX_____,
+ ____XX__,_XX____X,XXX_____,
+ ____XX__,_XXXXX_X,XX______,
+ ____XX_X,XXXX____,XX______,
+ _XXXXXXX,_XX____X,XXX_____,
+ __XXX___,_XX___XX,_XXX____,
+ ________,_XX__XXX,__XXXX__,
+ ________,_XX_XXX_,___XXXXX,
+ ________,_XXXX___,____XX__,
+ ________,_XXX____,________,
+ ________,________,________,
+};
+
+/* char: 认 code:0xC8CF */
+static GUI_CONST_STORAGE unsigned char acC8CF[72] = {
+ ________,________,________,
+ ________,________,________,
+ ________,______XX,________,
+ _____XX_,______XX,X_______,
+ _____XXX,______XX,________,
+ ______XX,______XX,________,
+ ______XX,______XX,________,
+ ______XX,______XX,X_______,
+ ________,______XX,X_______,
+ _____XX_,______XX,X_______,
+ _XXXXXXX,______XX,X_______,
+ _____XX_,_____XXX,X_______,
+ _____XX_,_____XXX,X_______,
+ _____XX_,_____XX_,XX______,
+ _____XX_,_____XX_,XX______,
+ _____XX_,__XXXXX_,XX______,
+ _____XX_,_XX_XX__,_XX_____,
+ _____XX_,XX_XXX__,_XXX____,
+ _____XXX,X__XX___,__XX____,
+ _____XXX,__XX____,__XXX___,
+ _____XXX,_XX_____,___XXXX_,
+ _____XXX,XX______,____XXX_,
+ ______XX,________,________,
+ ________,________,________,
+};
+
+/* char: 入 code:0xC8EB */
+static GUI_CONST_STORAGE unsigned char acC8EB[72] = {
+ ________,________,________,
+ ________,________,________,
+ _______X,XX______,________,
+ ________,_XXX____,________,
+ ________,__XXX___,________,
+ ________,___XX___,________,
+ ________,___XXX__,________,
+ ________,___XXX__,________,
+ ________,___XXX__,________,
+ ________,__XXXXX_,________,
+ ________,__XX_XX_,________,
+ ________,__XX_XX_,________,
+ ________,_XXX__XX,________,
+ ________,_XX___XX,________,
+ ________,XX____XX,X_______,
+ _______X,XX_____X,XX______,
+ _______X,X_______,XX______,
+ ______XX,________,XXX_____,
+ _____XXX,________,_XXX____,
+ ____XXX_,________,__XXXX__,
+ ___XX___,________,___XXXXX,
+ __XX____,________,____XX__,
+ _XX_____,________,________,
+ ________,________,________,
+};
+
+/* char: 设 code:0xC9E8 */
+static GUI_CONST_STORAGE unsigned char acC9E8[72] = {
+ ________,________,________,
+ ________,________,________,
+ ____XX__,___XXXXX,XXX_____,
+ _____XX_,___XXX__,_XXX____,
+ _____XXX,___XXX__,_XX_____,
+ _____XXX,___XXX__,_XX_____,
+ ________,___XX___,_XX_____,
+ ________,___XX___,_XX_____,
+ ________,__XX____,_XX_____,
+ _XXXXXXX,_XXX____,_XXXXXXX,
+ _____XX_,XX______,__XX____,
+ _____XXX,X_XXXXXX,XXXXX___,
+ _____XX_,___XX___,__XX____,
+ _____XX_,____XX__,_XXX____,
+ _____XX_,____XX__,_XXX____,
+ _____XX_,_____XX_,_XX_____,
+ _____XX_,_XX__XX_,XX______,
+ _____XX_,XX____XX,XX______,
+ _____XXX,X_____XX,X_______,
+ _____XXX,_____XXX,XXX_____,
+ _____XXX,___XXX__,_XXXX___,
+ ________,_XXX____,___XXXX_,
+ _______X,XX______,________,
+ ________,________,________,
+};
+
+/* char: 生 code:0xC9FA */
+static GUI_CONST_STORAGE unsigned char acC9FA[72] = {
+ ________,________,________,
+ ________,___XX___,________,
+ ________,___XXX__,________,
+ ______XX,___XXX__,________,
+ _____XXX,___XXX__,________,
+ _____XXX,___XXX__,________,
+ _____XX_,___XXX__,___XX___,
+ ____XXXX,XXXXXXXX,XXXXXX__,
+ ____XX__,___XXX__,________,
+ ____XX__,___XXX__,________,
+ ___XX___,___XXX__,________,
+ ___XX___,___XXX__,________,
+ __XX____,___XXX__,________,
+ _XX_____,___XXX__,__XX____,
+ _____XXX,XXXXXXXX,XXXXX___,
+ ________,___XXX__,________,
+ ________,___XXX__,________,
+ ________,___XXX__,________,
+ ________,___XXX__,________,
+ ________,___XXX__,________,
+ ________,___XXX__,____XXX_,
+ _XXXXXXX,XXXXXXXX,XXXXXXX_,
+ ________,________,________,
+ ________,________,________,
+};
+
+/* char: 失 code:0xCAA7 */
+static GUI_CONST_STORAGE unsigned char acCAA7[72] = {
+ ________,________,________,
+ ________,___XX___,________,
+ ________,___XXX__,________,
+ ______XX,___XXX__,________,
+ ______XX,___XXX__,________,
+ _____XXX,___XXX__,__XX____,
+ _____XXX,XXXXXXXX,XXXXX___,
+ _____XX_,___XXX__,________,
+ ____XX__,___XXX__,________,
+ ____XX__,___XX___,________,
+ ___XX___,___XX___,________,
+ ________,___XX___,____XX__,
+ __XXXXXX,XXXXXXXX,XXXXXXX_,
+ ________,___XXXX_,________,
+ ________,__XXXXX_,________,
+ ________,__XX__XX,________,
+ ________,_XXX__XX,________,
+ ________,_XX____X,X_______,
+ ________,XX______,XX______,
+ _______X,X_______,_XXX____,
+ ______XX,________,__XXX___,
+ ____XXX_,________,___XXXXX,
+ __XXX___,________,____XX__,
+ ________,________,________,
+};
+
+/* char: 石 code:0xCAAF */
+static GUI_CONST_STORAGE unsigned char acCAAF[72] = {
+ ________,________,________,
+ ________,________,________,
+ ________,________,________,
+ ________,________,____XX__,
+ __XXXXXX,XXXXXXXX,XXXXXXX_,
+ ________,__XXX___,________,
+ ________,__XX____,________,
+ ________,_XXX____,________,
+ ________,_XX_____,________,
+ ________,XX______,________,
+ _______X,XX______,__XX____,
+ _______X,XXXXXXXX,XXXXX___,
+ ______XX,XX______,__XX____,
+ _____XXX,XX______,__XX____,
+ ____XXX_,XX______,__XX____,
+ ___XX___,XX______,__XX____,
+ __XX____,XX______,__XX____,
+ _XX_____,XX______,__XX____,
+ ________,XX______,__XX____,
+ ________,XXXXXXXX,XXXX____,
+ ________,XX______,__XX____,
+ ________,XX______,__XX____,
+ _______X,X_______,________,
+ ________,________,________,
+};
+
+/* char: 时 code:0xCAB1 */
+static GUI_CONST_STORAGE unsigned char acCAB1[72] = {
+ ________,________,________,
+ ________,________,_XX_____,
+ ________,________,_XXX____,
+ ________,________,_XX_____,
+ __XXXXXX,XX______,_XX_____,
+ __XX___X,XX______,_XX_____,
+ __XX___X,XX______,_XX_____,
+ __XX___X,XXXXXXXX,XXXXXXX_,
+ __XX___X,XX______,_XX_____,
+ __XX___X,XX______,_XX_____,
+ __XXXXXX,XX______,_XX_____,
+ __XX___X,XX_XX___,_XX_____,
+ __XX___X,XX__XXX_,_XX_____,
+ __XX___X,XX__XXX_,_XX_____,
+ __XX___X,XX___XX_,_XX_____,
+ __XX___X,XX______,_XX_____,
+ __XX___X,XX______,_XX_____,
+ __XXXXXX,XX______,_XX_____,
+ __XX___X,XX______,_XX_____,
+ __XX___X,X_______,_XX_____,
+ ________,_____XX_,_XX_____,
+ ________,______XX,XXX_____,
+ ________,________,XX______,
+ ________,________,________,
+};
+
+/* char: 实 code:0xCAB5 */
+static GUI_CONST_STORAGE unsigned char acCAB5[72] = {
+ ________,________,________,
+ ________,___XX___,________,
+ ________,___XXX__,________,
+ ________,____XXX_,________,
+ ________,____XX__,________,
+ ____XXXX,XXXXXXXX,XXXXXXX_,
+ ___XX___,________,____XXX_,
+ ___XX__X,X____XX_,___XX___,
+ __XXX___,XXX__XXX,________,
+ ________,_XXX_XX_,________,
+ ________,_XX__XX_,________,
+ _____XXX,_____XX_,________,
+ ______XX,X____XX_,________,
+ _______X,X___XXX_,________,
+ _______X,X___XXX_,____XX__,
+ __XXXXXX,XXXXXXXX,XXXXXXX_,
+ ________,____XX__,________,
+ ________,___XXXX_,________,
+ ________,___XX_XX,X_______,
+ ________,__XX____,XXXX____,
+ ________,XXX_____,__XXX___,
+ _____XXX,X_______,___XXX__,
+ __XXXX__,________,____XX__,
+ ________,________,________,
+};
+
+/* char: 使 code:0xCAB9 */
+static GUI_CONST_STORAGE unsigned char acCAB9[72] = {
+ ________,________,________,
+ _______X,X_____XX,________,
+ ______XX,X_____XX,X_______,
+ ______XX,X_____XX,X_______,
+ ______XX,______XX,X_______,
+ _____XXX,XXXXXXXX,XXXXXXX_,
+ _____XX_,______XX,X_______,
+ ____XXX_,______XX,X_______,
+ ____XXXX,__XXXXXX,XXXXXX__,
+ ___XXXX_,__XX__XX,X__XXX__,
+ ___XXXX_,__XX__XX,X__XXX__,
+ __XX_XX_,__XX__XX,X__XXX__,
+ _XX__XX_,__XXXXXX,XXXXXX__,
+ _____XX_,_XXX__XX,X__XXX__,
+ _____XX_,__XX__XX,________,
+ _____XX_,___XX_XX,________,
+ _____XX_,____XXXX,________,
+ _____XX_,_____XXX,________,
+ _____XX_,_____XXX,________,
+ _____XX_,____XXXX,XX______,
+ _____XX_,___XXX__,XXXX____,
+ _____XX_,_XXX____,_XXXXXXX,
+ _____XXX,XX______,____XX__,
+ ________,________,________,
+};
+
+/* char: 试 code:0xCAD4 */
+static GUI_CONST_STORAGE unsigned char acCAD4[72] = {
+ ________,________,________,
+ ________,________,________,
+ ________,_______X,X_______,
+ ___XX___,_______X,XXXXX___,
+ ____XX__,________,XX_XXX__,
+ ____XXX_,________,XX__XX__,
+ _____XX_,________,XX___XX_,
+ _____XX_,XXXXXXXX,XXXXXXXX,
+ ________,________,XX______,
+ ________,________,XX______,
+ _XXXXXXX,______XX,XX______,
+ _____XX_,XXXXXXXX,XX______,
+ _____XX_,____XX__,XX______,
+ _____XX_,____XX__,XXX_____,
+ _____XX_,____XX__,_XX_____,
+ _____XX_,____XX__,_XX_____,
+ _____XX_,_XX_XX__,_XXX____,
+ _____XX_,XX__XX_X,X_XX__XX,
+ _____XXX,X___XXXX,__XXX_XX,
+ _____XXX,_XXXX___,___XX_XX,
+ ____XXXX,_XX_____,___XXXX_,
+ _____XX_,________,____XXXX,
+ ________,________,______XX,
+ ________,________,________,
+};
+
+/* char: 首 code:0xCAD7 */
+static GUI_CONST_STORAGE unsigned char acCAD7[72] = {
+ ________,________,________,
+ _______X,X______X,X_______,
+ ________,XX_____X,XX______,
+ ________,XXX____X,X_______,
+ ________,_XX___XX,____XX__,
+ _XXXXXXX,XXXXXXXX,XXXXXXX_,
+ ________,__XXX___,________,
+ ________,__XX____,________,
+ ________,__XX____,________,
+ ______XX,XXXXXXXX,XXXX____,
+ ______XX,________,_XX_____,
+ ______XX,________,_XX_____,
+ ______XX,XXXXXXXX,XXX_____,
+ ______XX,________,_XX_____,
+ ______XX,________,_XX_____,
+ ______XX,________,_XX_____,
+ ______XX,XXXXXXXX,XXX_____,
+ ______XX,________,_XX_____,
+ ______XX,________,_XX_____,
+ ______XX,________,_XX_____,
+ ______XX,XXXXXXXX,XXX_____,
+ ______XX,________,_XX_____,
+ ______XX,________,_XX_____,
+ ________,________,________,
+};
+
+/* char: 输 code:0xCAE4 */
+static GUI_CONST_STORAGE unsigned char acCAE4[72] = {
+ ________,________,________,
+ ________,______XX,________,
+ ____XXX_,______XX,X_______,
+ ____XXX_,_____XXX,X_______,
+ ____XX__,_____XX_,XX______,
+ _XXXXXXX,XXX_XXX_,_XX_____,
+ ___XXX__,____XX__,__XX____,
+ ___XX___,___XX___,_XXXXX__,
+ ___XXXXX,_XXXXXXX,XXXXXXX_,
+ __XXX_XX,XX______,________,
+ __XX__XX,__XXXXXX,____XX__,
+ _XXXXXXX,XXXX__XX,_XX_XX__,
+ ______XX,__XX__XX,_XX_XX__,
+ ______XX,__XXXXXX,_XX_XX__,
+ ______XX,__XX__XX,_XX_XX__,
+ ______XX,XXXX__XX,_XX_XX__,
+ ___XXXXX,__XXXXXX,_XX_XX__,
+ _XXX__XX,__XX__XX,_XX_XX__,
+ ______XX,__XX__XX,_XX_XX__,
+ ______XX,__XX__XX,____XX__,
+ _____XXX,__XX__XX,____XX__,
+ _____XXX,__XXXXXX,__XXXX__,
+ _____XXX,__XX_XX_,___XX___,
+ ________,________,________,
+};
+
+/* char: 术 code:0xCAF5 */
+static GUI_CONST_STORAGE unsigned char acCAF5[72] = {
+ ________,________,________,
+ ________,___XX___,________,
+ ________,___XXX_X,X_______,
+ ________,___XXX__,XXX_____,
+ ________,___XXX__,_XXX____,
+ ________,___XXX__,__XX____,
+ ________,___XXX__,__XXXX__,
+ _XXXXXXX,XXXXXXXX,XXXXXXX_,
+ ________,__XXXXX_,________,
+ ________,__XXXXX_,________,
+ ________,_XXXXXXX,________,
+ ________,_XXXXXXX,________,
+ ________,XXXXXX_X,X_______,
+ _______X,XX_XXX_X,X_______,
+ _______X,X__XXX__,XX______,
+ ______XX,___XXX__,XXX_____,
+ _____XX_,___XXX__,_XXXX___,
+ ____XX__,___XXX__,__XXXX__,
+ ___XX___,___XXX__,___XXXX_,
+ __XX____,___XXX__,____XX__,
+ ________,___XXX__,________,
+ ________,___XXX__,________,
+ ________,___XX___,________,
+ ________,________,________,
+};
+
+/* char: 数 code:0xCAFD */
+static GUI_CONST_STORAGE unsigned char acCAFD[72] = {
+ ________,________,________,
+ _______X,X______X,X_______,
+ ___XX__X,X__XX__X,XX______,
+ ____XX_X,X__XX__X,X_______,
+ ____XXXX,X_XX__XX,X_______,
+ ____XX_X,XXX___XX,________,
+ __XXXXXX,XXXXXXXX,XXXXXXX_,
+ ______XX,X____XXX,___XX___,
+ _____XXX,XXX__XXX,___XX___,
+ _____XXX,X_XX_XXX,___XX___,
+ ____XX_X,X_XXXXXX,__XXX___,
+ __XXX__X,X___XXXX,__XXX___,
+ _XX____X,X______X,X_XXX___,
+ ______XX,X______X,X_XX____,
+ _XXXXXXX,XXXXX__X,X_XX____,
+ _____XXX,__XX___X,XXXX____,
+ _____XX_,__XX____,XXX_____,
+ ____XXXX,_XX_____,XXX_____,
+ _______X,XXXX___X,XXXX____,
+ _______X,XXXXX_XX,X_XXX___,
+ _____XXX,___XXXXX,___XXXX_,
+ ___XXX__,___XXX__,____XXX_,
+ _XXX____,__XX____,________,
+ ________,________,________,
+};
+
+/* char: 司 code:0xCBBE */
+static GUI_CONST_STORAGE unsigned char acCBBE[72] = {
+ ________,________,________,
+ ________,________,________,
+ ____XXXX,XXXXXXXX,XXXXX___,
+ ________,________,___XX___,
+ ________,________,___XX___,
+ ________,________,___XX___,
+ ________,________,___XX___,
+ __XXXXXX,XXXXXXXX,X__XX___,
+ ________,________,___XX___,
+ ________,________,___XX___,
+ _____XXX,XXXXXXX_,___XX___,
+ _____XX_,____XXX_,___XX___,
+ _____XX_,____XXX_,___XX___,
+ _____XX_,____XXX_,___XX___,
+ _____XX_,____XXX_,___XX___,
+ _____XX_,____XXX_,___XX___,
+ _____XXX,XXXXXXX_,___XX___,
+ _____XX_,____XXX_,___XX___,
+ _____XX_,____XX__,___XX___,
+ ________,________,___XX___,
+ ________,_______X,X_XXX___,
+ ________,________,XXXXX___,
+ ________,________,__XX____,
+ ________,________,________,
+};
+
+/* char: 苏 code:0xCBD5 */
+static GUI_CONST_STORAGE unsigned char acCBD5[72] = {
+ ________,________,________,
+ ________,XX____XX,________,
+ ________,XX____XX,X_______,
+ ________,XX____XX,X___XX__,
+ _XXXXXXX,XXXXXXXX,XXXXXXX_,
+ ________,XX____XX,X_______,
+ ________,XX____XX,X_______,
+ ________,XXXXX_XX,X_______,
+ ________,__XXX___,________,
+ ________,__XXX___,________,
+ ___XXXXX,XXXXXXXX,XXXX____,
+ ________,__XX____,XXX_____,
+ ________,__XX____,XXX_____,
+ ________,__XX____,XXX_____,
+ ____XX__,_XXX____,XX_XXX__,
+ ____XX__,_XX_____,XX__XXX_,
+ ___XXX__,_XX_____,XX__XXX_,
+ __XXX___,XX______,XX___XX_,
+ _______X,XX______,XX______,
+ _______X,X______X,XX______,
+ _____XXX,___XXXXX,XX______,
+ ____XX__,_____XXX,X_______,
+ ___XX___,________,________,
+ ________,________,________,
+};
+
+/* char: 所 code:0xCBF9 */
+static GUI_CONST_STORAGE unsigned char acCBF9[72] = {
+ ________,________,________,
+ ________,________,________,
+ ________,__XX____,____XX__,
+ _______X,XXXXX___,_XXXXXX_,
+ ____XXXX,_____XXX,XX______,
+ ____XX__,_____XX_,________,
+ ____XX__,_____XX_,________,
+ ____XX__,_____XX_,________,
+ ____XXXX,XXXX_XX_,_____XX_,
+ ____XX__,_XXX_XXX,XXXXXXXX,
+ ____XX__,_XXX_XX_,__XX____,
+ ____XX__,_XXX_XX_,__XX____,
+ ____XX__,_XXX_XX_,__XX____,
+ ____XXXX,XXXX_XX_,__XX____,
+ ____XX__,_XXXXXX_,__XX____,
+ ____XX__,____XX__,__XX____,
+ ___XXX__,____XX__,__XX____,
+ ___XX___,___XXX__,__XX____,
+ ___XX___,___XX___,__XX____,
+ ___XX___,__XX____,__XX____,
+ __XX____,__XX____,__XX____,
+ __XX____,_XX_____,__XX____,
+ _XX_____,XX______,__XX____,
+ ________,________,________,
+};
+
+/* char: 特 code:0xCCD8 */
+static GUI_CONST_STORAGE unsigned char acCCD8[72] = {
+ ________,________,________,
+ ________,______XX,X_______,
+ ______XX,______XX,X_______,
+ ______XX,______XX,X__XX___,
+ __XXX_XX,__XXXXXX,XXXXXX__,
+ __XXX_XX,______XX,X_______,
+ __XX__XX,______XX,X_______,
+ __XXXXXX,XXX___XX,X_______,
+ __XX__XX,______XX,X____XX_,
+ _XX___XX,_XXXXXXX,XXXXXXXX,
+ _XX___XX,________,_XX_____,
+ ______XX,_XX_____,_XXX____,
+ ______XX,XX______,_XX__XX_,
+ _____XXX,_XXXXXXX,XXXXXXXX,
+ ___XXXXX,________,_XX_____,
+ _XXXX_XX,___XX___,_XX_____,
+ __XX__XX,___XXX__,_XX_____,
+ ______XX,____XXX_,_XX_____,
+ ______XX,____XX__,_XX_____,
+ ______XX,________,_XX_____,
+ ______XX,_____XXX,_XX_____,
+ ______XX,_______X,XXX_____,
+ ______XX,________,XX______,
+ ________,________,________,
+};
+
+/* char: 条 code:0xCCF5 */
+static GUI_CONST_STORAGE unsigned char acCCF5[72] = {
+ ________,________,________,
+ ________,XX______,________,
+ ________,XXX_____,________,
+ _______X,XXXXXXXX,XXX_____,
+ _______X,XX______,XXX_____,
+ ______XX,_XX____X,XX______,
+ _____XX_,_XX___XX,X_______,
+ ____XX__,__XX_XXX,________,
+ ___XX___,___XXXX_,________,
+ __XX____,___XXXX_,________,
+ ________,_XXX_XXX,X_______,
+ ______XX,XX__XX_X,XXXXXXXX,
+ __XXXXX_,____XX__,_XXXXX__,
+ ________,____XX__,__XX____,
+ ____XXXX,XXXXXXXX,XXXXX___,
+ ________,____XX__,________,
+ _______X,XX__XX_X,X_______,
+ _______X,XX__XX__,XX______,
+ ______XX,X___XX__,_XXX____,
+ _____XXX,____XX__,__XXX___,
+ ____XX__,XX_XXX__,___XXX__,
+ ___XX___,_XXXXX__,___XXX__,
+ ________,___XX___,________,
+ ________,________,________,
+};
+
+/* char: 维 code:0xCEAC */
+static GUI_CONST_STORAGE unsigned char acCEAC[72] = {
+ ________,________,________,
+ ________,____XX__,________,
+ _____XXX,____XXX_,XX______,
+ _____XX_,____XX__,XXX_____,
+ ____XXX_,___XXX__,_XX_____,
+ ____XX__,___XX___,_XX_____,
+ ____XX__,XXXXXXXX,XXXXXXX_,
+ ___XX__X,XXXXX___,XX______,
+ ___XX__X,X_XXX___,XX______,
+ __XX_XXX,XXXXX___,XX__XX__,
+ __XXXXXX,_XXXXXXX,XXXXXXX_,
+ __XX_XXX,XX_XX___,XX______,
+ _____XX_,___XX___,XX______,
+ ____XX__,___XX___,XX______,
+ ___XX__X,XX_XX___,XX__XX__,
+ __XXXXXX,___XXXXX,XXXXXXX_,
+ __XXX___,___XX___,XX______,
+ ________,_XXXX___,XX______,
+ ______XX,XX_XX___,XX______,
+ ___XXXX_,___XX___,XX___XX_,
+ __XXX___,___XXXXX,XXXXXXXX,
+ ________,___XX___,________,
+ ________,___XX___,________,
+ ________,________,________,
+};
+
+/* char: 未 code:0xCEB4 */
+static GUI_CONST_STORAGE unsigned char acCEB4[72] = {
+ ________,________,________,
+ ________,___XX___,________,
+ ________,___XXX__,________,
+ ________,___XXX__,________,
+ ________,___XXX__,________,
+ ____XXXX,XXXXXXXX,XXXX____,
+ ________,___XXX__,________,
+ ________,___XXX__,________,
+ ________,___XXX__,________,
+ ________,___XXX__,____XX__,
+ __XXXXXX,XXXXXXXX,XXXXXXX_,
+ ________,__XXXXX_,________,
+ ________,_XXXXXX_,________,
+ ________,_XXXXXXX,________,
+ ________,XXXXXX_X,X_______,
+ _______X,XX_XXX_X,XX______,
+ ______XX,X__XXX__,XXX_____,
+ _____XXX,___XXX__,_XXX____,
+ ____XX__,___XXX__,__XXXX__,
+ ___XX___,___XXX__,___XXXX_,
+ _XXX____,___XXX__,____XX__,
+ ________,___XXX__,________,
+ ________,___XX___,________,
+ ________,________,________,
+};
+
+/* char: 位 code:0xCEBB */
+static GUI_CONST_STORAGE unsigned char acCEBB[72] = {
+ ________,________,________,
+ ______XX,____XX__,________,
+ ______XX,X____XX_,________,
+ ______XX,_____XXX,________,
+ _____XXX,______XX,________,
+ _____XX_,______XX,____XX__,
+ _____XX_,XXXXXXXX,XXXXXXX_,
+ ____XXX_,________,________,
+ ____XXXX,________,__XX____,
+ ___XXXX_,________,__XXX___,
+ ___XXXX_,__XX____,_XXX____,
+ __XX_XX_,___XX___,_XXX____,
+ __XX_XX_,___XX___,_XX_____,
+ _XX__XX_,___XXX__,_XX_____,
+ _____XX_,___XXX__,_XX_____,
+ _____XX_,___XXX__,XX______,
+ _____XX_,____XX__,XX______,
+ _____XX_,________,XX______,
+ _____XX_,_______X,X_______,
+ _____XX_,_______X,X____XX_,
+ _____XXX,XXXXXXXX,XXXXXXXX,
+ _____XX_,________,________,
+ _____XX_,________,________,
+ ________,________,________,
+};
+
+/* char: 温 code:0xCEC2 */
+static GUI_CONST_STORAGE unsigned char acCEC2[72] = {
+ ________,________,________,
+ ________,________,________,
+ ___XX___,________,__XX____,
+ ____XXX_,_XXXXXXX,XXXX____,
+ _____XX_,_XX_____,__XX____,
+ ________,_XX_____,__XX____,
+ _______X,XXXXXXXX,XXXX____,
+ _XX____X,XXX_____,__XX____,
+ __XXX_XX,_XX_____,__XX____,
+ ___XX_XX,_XX_____,__XX____,
+ ___XX_XX,_XXXXXXX,XXXX____,
+ _____XX_,_XX_____,__XX____,
+ _____XX_,________,________,
+ _____XX_,XXXXXXXX,XXXXXX__,
+ _____XX_,XX__XX_X,X__XX___,
+ ____XX__,XX__XX_X,X__XX___,
+ _XXXXX__,XX__XX_X,X__XX___,
+ ___XXX__,XX__XX_X,X__XX___,
+ ___XXX__,XX__XX_X,X__XX___,
+ ___XXX__,XX__XX_X,X__XX___,
+ ___XXX__,XX__XX_X,X__XXXX_,
+ ___XXXXX,XXXXXXXX,XXXXXXXX,
+ ________,________,________,
+ ________,________,________,
+};
+
+/* char: 误 code:0xCEF3 */
+static GUI_CONST_STORAGE unsigned char acCEF3[72] = {
+ ________,________,________,
+ ________,________,________,
+ ________,__XXXXXX,XXXXX___,
+ ____XXX_,__XXX___,___XX___,
+ _____XX_,__XXX___,___XX___,
+ _____XXX,__XXX___,___XX___,
+ ________,__XXX___,___XX___,
+ ________,__XXXXXX,XXXXX___,
+ ________,__XXX___,________,
+ _XXXXXXX,________,________,
+ _____XX_,_XXXXXXX,XXXXXX__,
+ _____XX_,______XX,________,
+ _____XX_,______XX,________,
+ _____XX_,______XX,________,
+ _____XX_,XXXXXXXX,XXXXXXX_,
+ _____XX_,_XX___XX,X_______,
+ _____XX_,XX___XXX,XX______,
+ _____XXX,X____XX_,XX______,
+ _____XXX,____XXX_,_XX_____,
+ _____XXX,___XXX__,__XX____,
+ _____XX_,__XXX___,__XXXX__,
+ ________,_XXX____,___XXXXX,
+ _______X,XX______,________,
+ ________,________,________,
+};
+
+/* char: 息 code:0xCFA2 */
+static GUI_CONST_STORAGE unsigned char acCFA2[72] = {
+ ________,________,________,
+ ________,__XXX___,________,
+ ________,__XX____,________,
+ ______XX,XXXXXXXX,XXXX____,
+ ______XX,________,_XX_____,
+ ______XX,________,_XX_____,
+ ______XX,XXXXXXXX,XXX_____,
+ ______XX,________,_XX_____,
+ ______XX,________,_XX_____,
+ ______XX,XXXXXXXX,XXX_____,
+ ______XX,________,_XX_____,
+ ______XX,________,_XX_____,
+ ______XX,XXXXXXXX,XXXX____,
+ ______XX,__XX____,_XX_____,
+ ________,___XX___,________,
+ _______X,X__XXX__,________,
+ ____XX_X,XX__XXX_,___XX___,
+ ____XX_X,XX__XXX_,____XX__,
+ ____XX_X,XX______,_XX_XXX_,
+ ___XXX_X,XX______,_XX__XX_,
+ __XXXX__,XX______,XXX__XX_,
+ ________,XXXXXXXX,XXX_____,
+ ________,________,________,
+ ________,________,________,
+};
+
+/* char: 限 code:0xCFDE */
+static GUI_CONST_STORAGE unsigned char acCFDE[72] = {
+ ________,________,________,
+ ________,________,________,
+ ___XXXXX,XX______,___XX___,
+ ___XX__X,X__XXXXX,XXXXX___,
+ ___XX__X,X__XX___,__XXX___,
+ ___XX__X,X__XX___,__XXX___,
+ ___XX_XX,___XX___,__XXX___,
+ ___XX_XX,___XXXXX,XXXXX___,
+ ___XX_XX,___XX___,__XXX___,
+ ___XX_XX,___XX___,__XXX___,
+ ___XX__X,X__XX___,__XXX___,
+ ___XX__X,X__XXXXX,XXXXX___,
+ ___XX___,XX_XX_XX,__XX____,
+ ___XX___,XX_XX_XX,___XXX__,
+ ___XX___,XX_XX_XX,___XXX__,
+ ___XXX_X,XX_XX__X,XXXX____,
+ ___XXXXX,XX_XX__X,XX______,
+ ___XX_XX,___XX___,XX______,
+ ___XX___,___XX__X,XXX_____,
+ ___XX___,___XXXXX,_XXX____,
+ ___XX___,___XXX__,__XXXX__,
+ ___XX___,___XX___,___XXXX_,
+ ___XX___,___XX___,________,
+ ________,________,________,
+};
+
+/* char: 项 code:0xCFEE */
+static GUI_CONST_STORAGE unsigned char acCFEE[72] = {
+ ________,________,________,
+ ________,________,____XX__,
+ ________,_XXXXXXX,XXXXXXX_,
+ ________,XX_____X,X_______,
+ _XXXXXXX,XXX____X,X_______,
+ _____XX_,______XX,________,
+ _____XX_,___XXXXX,XXXXXX__,
+ _____XX_,___XX___,____XX__,
+ _____XX_,___XX___,____XX__,
+ _____XX_,___XX__X,XX__XX__,
+ _____XX_,___XX__X,XX__XX__,
+ _____XX_,___XX__X,XX__XX__,
+ _____XX_,___XX__X,XX__XX__,
+ _____XX_,___XX__X,XX__XX__,
+ _____XX_,XXXXX__X,X___XX__,
+ _____XXX,X__XX__X,X___XX__,
+ __XXXX__,___XX__X,XX__XX__,
+ __XX____,______XX,XXX_____,
+ ________,______XX,__XXX___,
+ ________,_____XXX,___XXX__,
+ ________,____XXX_,____XXX_,
+ ________,__XXX___,_____XX_,
+ ________,XXX_____,_____XX_,
+ ________,________,________,
+};
+
+/* char: 消 code:0xCFFB */
+static GUI_CONST_STORAGE unsigned char acCFFB[72] = {
+ ________,________,________,
+ ________,_______X,X_______,
+ ____XX__,_XX____X,X_______,
+ ____XXX_,__XX___X,X__XXXX_,
+ _____XXX,___XX__X,X__XX___,
+ _____XXX,___XXX_X,X_XX____,
+ ________,XX_XXX_X,XXX_____,
+ _XX_____,XX_____X,XXX_____,
+ __XXX___,XXXXXXXX,XXXXXX__,
+ ___XXX_X,X_XX____,___XX___,
+ ___XXX_X,X_XX____,___XX___,
+ _______X,X_XXXXXX,XXXXX___,
+ ______XX,__XX____,___XX___,
+ ______XX,__XX____,___XX___,
+ ______XX,__XX____,___XX___,
+ _____XX_,__XXXXXX,XXXXX___,
+ __XXXXX_,__XX____,___XX___,
+ ____XXX_,__XX____,___XX___,
+ ____XXX_,__XX____,___XX___,
+ ____XXX_,__XX____,___XX___,
+ ____XXX_,__XX____,___XX___,
+ ____XXX_,__XX____,XXXXX___,
+ _____XX_,__XX____,__XX____,
+ ________,________,________,
+};
+
+/* char: 校 code:0xD0A3 */
+static GUI_CONST_STORAGE unsigned char acD0A3[72] = {
+ ________,________,________,
+ _____XX_,_____XX_,________,
+ _____XXX,______XX,X_______,
+ _____XX_,_______X,X_______,
+ _____XX_,_______X,X_______,
+ _____XX_,XXXXXXXX,XXXXXXX_,
+ _XXXXXXX,XXX_____,________,
+ _____XX_,_____XX_,_XX_____,
+ _____XX_,____XXX_,__XXX___,
+ ____XXXX,X__XXX__,___XXX__,
+ ____XXXX,XX_XX___,____XXX_,
+ ____XXX_,XXXXX___,__XXXXX_,
+ ___XXXX_,_XX_XX__,_XXXX___,
+ ___XXXX_,____XX__,_XXX____,
+ ___XXXX_,____XX__,XXX_____,
+ __XX_XX_,_____XX_,XXX_____,
+ _XX__XX_,_____XXX,XX______,
+ _____XX_,______XX,X_______,
+ _____XX_,______XX,X_______,
+ _____XX_,_____XXX,XXX_____,
+ _____XX_,___XXX__,_XXXX___,
+ _____XX_,_XXX____,__XXXXXX,
+ _____XXX,XX______,____XX__,
+ ________,________,________,
+};
+
+/* char: 斜 code:0xD0B1 */
+static GUI_CONST_STORAGE unsigned char acD0B1[72] = {
+ ________,________,________,
+ _______X,X_______,__XX____,
+ _______X,XX______,__XXX___,
+ ______XX,XX______,__XXX___,
+ ______XX,_XXX__XX,__XXX___,
+ _____XX_,__XXX__X,XXXXX___,
+ ____XXX_,___XXX_X,XXXXX___,
+ ____XX__,__XXXX__,__XXX___,
+ ___XXXXX,XXXXX___,__XXX___,
+ __XX___X,X____XX_,__XXX___,
+ _XX____X,X_____XX,X_XXX___,
+ _______X,X__XX__X,X_XXX___,
+ __XXXXXX,XXXXXX_X,X_XXX___,
+ _______X,X_______,__XXXXX_,
+ ____XX_X,X_______,__XXXXX_,
+ ____XXXX,X_XXXXXX,XXXXX___,
+ ____XX_X,X_XXX___,__XXX___,
+ ___XXX_X,X__XXX__,__XXX___,
+ ___XX__X,X__XXX__,__XXX___,
+ __XX___X,X___XX__,__XXX___,
+ __XX___X,X_______,__XXX___,
+ _XX__XXX,X_______,__XXX___,
+ ______XX,________,__XX____,
+ ________,________,________,
+};
+
+/* char: 信 code:0xD0C5 */
+static GUI_CONST_STORAGE unsigned char acD0C5[72] = {
+ ________,________,________,
+ ________,_____XX_,________,
+ ______XX,X_____XX,________,
+ ______XX,______XX,X_______,
+ ______XX,______XX,X___XX__,
+ _____XX_,XXXXXXXX,XXXXXXX_,
+ _____XX_,________,________,
+ ____XX__,________,___XX___,
+ ____XXX_,_XXXXXXX,XXXXXX__,
+ ___XXXX_,________,________,
+ ___XXXX_,________,___XX___,
+ __XX_XX_,_XXXXXXX,XXXXXX__,
+ _XX__XX_,________,________,
+ _____XX_,________,________,
+ _____XX_,________,________,
+ _____XX_,__XXXXXX,XXXXXX__,
+ _____XX_,__XX____,___XX___,
+ _____XX_,__XX____,___XX___,
+ _____XX_,__XX____,___XX___,
+ _____XX_,__XX____,___XX___,
+ _____XX_,__XXXXXX,XXXXX___,
+ _____XX_,__XX____,___XX___,
+ _____XX_,__XX____,___XX___,
+ ________,________,________,
+};
+
+/* char: 行 code:0xD0D0 */
+static GUI_CONST_STORAGE unsigned char acD0D0[72] = {
+ ________,________,________,
+ ________,________,________,
+ ________,________,________,
+ ______XX,X_______,________,
+ ______XX,___XXXXX,XXXXXX__,
+ _____XX_,________,________,
+ ____XX__,XX______,________,
+ ___XX__X,XX______,________,
+ __XX__XX,X_______,_____XX_,
+ ______XX,_XXXXXXX,XXXXXXX_,
+ _____XXX,________,XX______,
+ ____XXXX,________,XX______,
+ ____XXXX,________,XX______,
+ ___XX_XX,________,XX______,
+ __XX__XX,________,XX______,
+ ______XX,________,XX______,
+ ______XX,________,XX______,
+ ______XX,________,XX______,
+ ______XX,________,XX______,
+ ______XX,________,XX______,
+ ______XX,___XXXXX,XX______,
+ ______XX,______XX,XX______,
+ ________,_______X,X_______,
+ ________,________,________,
+};
+
+/* char: 性 code:0xD0D4 */
+static GUI_CONST_STORAGE unsigned char acD0D4[72] = {
+ ________,________,________,
+ _____XX_,_______X,X_______,
+ _____XX_,_______X,XX______,
+ _____XX_,___XX__X,X_______,
+ _____XX_,___XXX_X,X_______,
+ _____XX_,__XXX__X,X_______,
+ _____XXX,__XXX__X,X___XX__,
+ _____XXX,XXXXXXXX,XXXXXXX_,
+ ___XXXXX,XXXX___X,X_______,
+ __XX_XX_,_XX____X,X_______,
+ __XX_XX_,_XX____X,X_______,
+ _XXX_XX_,XX_____X,X_______,
+ _____XX_,XX_____X,X_______,
+ _____XX_,__XXXXXX,XXXXXX__,
+ _____XX_,_______X,X_______,
+ _____XX_,_______X,X_______,
+ _____XX_,_______X,X_______,
+ _____XX_,_______X,X_______,
+ _____XX_,_______X,X_______,
+ _____XX_,_______X,X____XX_,
+ _____XX_,XXXXXXXX,XXXXXXXX,
+ _____XX_,________,________,
+ _____XX_,________,________,
+ ________,________,________,
+};
+
+/* char: 修 code:0xD0DE */
+static GUI_CONST_STORAGE unsigned char acD0DE[72] = {
+ ________,________,________,
+ ______XX,______XX,________,
+ ______XX,_____XXX,________,
+ _____XXX,_____XX_,________,
+ _____XX_,____XXXX,XXXXXX__,
+ _____XX_,____XXX_,___XXX__,
+ ____XX_X,XX_XX_XX,__XXX___,
+ ____XXXX,XXXX___X,XXXX____,
+ ___XXXXX,XX______,XXX_____,
+ ___XXXXX,XX_____X,XXX_____,
+ __XXXXXX,XX___XXX,__XXXX__,
+ __XXXXXX,XX_XXX__,_XX_XXX_,
+ _XX_XXXX,XXXX___X,XXX_____,
+ ____XXXX,XX____XX,X_______,
+ ____XXXX,XX___XX_,__XXX___,
+ ____XXXX,XX_XXX__,_XXX____,
+ ____XXXX,XX______,XXX__XX_,
+ ____XXXX,XX____XX,X___XXX_,
+ ____XXXX,XX__XXX_,___XXX__,
+ ____XXX_,__XXX___,_XXX____,
+ ____XXX_,_______X,XX______,
+ ____XXX_,___XXXXX,________,
+ ____XX__,XXXX____,________,
+ ________,________,________,
+};
+
+/* char: 需 code:0xD0E8 */
+static GUI_CONST_STORAGE unsigned char acD0E8[72] = {
+ ________,________,________,
+ ________,________,________,
+ ________,________,__XX____,
+ ____XXXX,XXXXXXXX,XXXXX___,
+ ________,____XX__,________,
+ ____XXXX,XXXXXXXX,XXXXXXX_,
+ ___XX___,____XX__,____XX__,
+ __XXX_XX,XXX_XXXX,XXXXX___,
+ ________,____XX__,________,
+ _____XXX,XXX_XXXX,XXX_____,
+ ________,____XX__,________,
+ ________,________,________,
+ __XXXXXX,XXXXXXXX,XXXXXX__,
+ ________,__XX____,________,
+ ____XXXX,XXXXXXXX,XXXXX___,
+ ____XXX_,_XXX__XX,___XX___,
+ ____XXX_,_XXX__XX,___XX___,
+ ____XXX_,_XXX__XX,___XX___,
+ ____XXX_,_XXX__XX,___XX___,
+ ____XXX_,_XXX__XX,___XX___,
+ ____XXX_,_XXX__XX,___XX___,
+ ____XXX_,_XX_____,_XXXX___,
+ ____XX__,________,__XX____,
+ ________,________,________,
+};
+
+/* char: 选 code:0xD1A1 */
+static GUI_CONST_STORAGE unsigned char acD1A1[72] = {
+ ________,________,________,
+ ________,______XX,________,
+ ___XX___,______XX,________,
+ ____XX__,__XX__XX,________,
+ _____XX_,__XXX_XX,________,
+ _____XX_,__XX__XX,________,
+ ________,__XXXXXX,XXXXX___,
+ ________,_XX___XX,________,
+ ________,_XX___XX,________,
+ _XXXXXXX,XX____XX,____XX__,
+ _____XXX,XXXXXXXX,XXXXXX__,
+ _____XX_,____XX_X,XX______,
+ _____XX_,____XX_X,XX______,
+ _____XX_,____XX_X,XX______,
+ _____XX_,___XXX_X,XX______,
+ _____XX_,___XX__X,XX______,
+ _____XX_,__XXX__X,XX__XX__,
+ _____XX_,__XX___X,XX__XX__,
+ ____XXX_,XXX____X,XX__XXX_,
+ __XXX_XX,X_______,XXXXXXX_,
+ _XXX___X,XX______,________,
+ ________,_XXXXXXX,XXXXXXX_,
+ ________,___XXXXX,XXXXXX__,
+ ________,________,________,
+};
+
+/* char: 要 code:0xD2AA */
+static GUI_CONST_STORAGE unsigned char acD2AA[72] = {
+ ________,________,________,
+ ________,________,________,
+ ________,________,____XX__,
+ __XXXXXX,XXXXXXXX,XXXXXXX_,
+ ________,_XX___XX,________,
+ ________,_XX___XX,________,
+ ____XXXX,XXXXXXXX,XXXXX___,
+ ____XXX_,_XX___XX,__XXX___,
+ ____XXX_,_XX___XX,__XXX___,
+ ____XXX_,_XX___XX,__XXX___,
+ ____XXXX,XXXXXXXX,XXXXX___,
+ ____XXX_,_XX_____,__XX____,
+ ________,_XXX____,________,
+ ________,_XX_____,____XX__,
+ _XXXXXXX,XXXXXXXX,XXXXXXX_,
+ ________,XX_____X,XX______,
+ _______X,X_____XX,X_______,
+ ______XX,X_____XX,________,
+ ________,XXXXXXXX,________,
+ ________,____XXXX,XX______,
+ ________,__XXX___,XXXXX___,
+ ______XX,XXX_____,__XXXX__,
+ __XXXXX_,________,____XX__,
+ ________,________,________,
+};
+
+/* char: 页 code:0xD2B3 */
+static GUI_CONST_STORAGE unsigned char acD2B3[72] = {
+ ________,________,________,
+ ________,________,________,
+ ________,________,___XX___,
+ __XXXXXX,XXXXXXXX,XXXXXX__,
+ ________,__XXX___,________,
+ ________,__XXX___,________,
+ ________,__XX____,_XX_____,
+ _____XXX,XXXXXXXX,XXXX____,
+ _____XXX,________,_XX_____,
+ _____XXX,___XX___,_XX_____,
+ _____XXX,___XXX__,_XX_____,
+ _____XXX,___XX___,_XX_____,
+ _____XXX,___XX___,_XX_____,
+ _____XXX,___XX___,_XX_____,
+ _____XXX,___XX___,_XX_____,
+ _____XXX,___XX___,_XX_____,
+ _____XXX,__XXX___,_XX_____,
+ _____XX_,__XXXXXX,________,
+ ________,_XXX___X,XX______,
+ ________,XXX_____,XXXX____,
+ _______X,XX______,__XXXX__,
+ _____XXX,________,___XXX__,
+ __XXXX__,________,________,
+ ________,________,________,
+};
+
+/* char: 一 code:0xD2BB */
+static GUI_CONST_STORAGE unsigned char acD2BB[72] = {
+ ________,________,________,
+ ________,________,________,
+ ________,________,________,
+ ________,________,________,
+ ________,________,________,
+ ________,________,________,
+ ________,________,________,
+ ________,________,________,
+ ________,________,________,
+ ________,________,________,
+ ________,________,____XX__,
+ _XXXXXXX,XXXXXXXX,XXXXXXX_,
+ ________,________,________,
+ ________,________,________,
+ ________,________,________,
+ ________,________,________,
+ ________,________,________,
+ ________,________,________,
+ ________,________,________,
+ ________,________,________,
+ ________,________,________,
+ ________,________,________,
+ ________,________,________,
+ ________,________,________,
+};
+
+/* char: 已 code:0xD2D1 */
+static GUI_CONST_STORAGE unsigned char acD2D1[72] = {
+ ________,________,________,
+ ________,________,________,
+ ________,________,__XX____,
+ ____XXXX,XXXXXXXX,XXXX____,
+ ________,________,_XXX____,
+ ________,________,_XXX____,
+ ________,________,_XXX____,
+ ________,________,_XXX____,
+ ____XX__,________,_XXX____,
+ ____XXX_,________,_XXX____,
+ ____XXXX,XXXXXXXX,XXXX____,
+ ____XXX_,________,_XXX____,
+ ____XXX_,________,________,
+ ____XXX_,________,________,
+ ____XXX_,________,________,
+ ____XXX_,________,________,
+ ____XXX_,________,____XX__,
+ ____XXX_,________,____XX__,
+ ____XXX_,________,____XX__,
+ ____XXX_,________,____XX__,
+ ____XXX_,________,____XXX_,
+ _____XXX,XXXXXXXX,XXXXXXX_,
+ ________,________,________,
+ ________,________,________,
+};
+
+/* char: 迎 code:0xD3AD */
+static GUI_CONST_STORAGE unsigned char acD3AD[72] = {
+ ________,________,________,
+ ________,________,________,
+ ________,______XX,________,
+ ____XX__,____XXXX,X_______,
+ ____XXX_,_XXXX___,________,
+ _____XX_,_XX____X,XXXXXXX_,
+ ________,_XX____X,X___XX__,
+ ________,_XX____X,X___XX__,
+ ________,_XX____X,X___XX__,
+ _XXXXXXX,_XX____X,X___XX__,
+ _____XX_,_XX____X,X___XX__,
+ _____XX_,_XX____X,X___XX__,
+ _____XX_,_XX____X,X___XX__,
+ _____XX_,_XX__XXX,X___XX__,
+ _____XX_,_XXXXX_X,X___XX__,
+ _____XX_,_XXX___X,XXXXXX__,
+ _____XX_,_XX____X,X__XXX__,
+ _____XX_,_______X,X_______,
+ ___XXXXX,_______X,X_______,
+ _XXX___X,XX_____X,X_______,
+ __XX____,XXXXXXX_,__XXXXXX,
+ ________,___XXXXX,XXXXXX__,
+ ________,________,________,
+ ________,________,________,
+};
+
+/* char: 用 code:0xD3C3 */
+static GUI_CONST_STORAGE unsigned char acD3C3[72] = {
+ ________,________,________,
+ ________,________,________,
+ ________,________,___XX___,
+ ____XXXX,XXXXXXXX,XXXXXX__,
+ ____XXX_,____XX__,___XX___,
+ ____XXX_,____XX__,___XX___,
+ ____XXX_,____XX__,___XX___,
+ ____XXX_,____XX__,___XX___,
+ ____XXXX,XXXXXXXX,XXXXX___,
+ ____XXX_,____XX__,___XX___,
+ ____XX__,____XX__,___XX___,
+ ____XX__,____XX__,___XX___,
+ ____XX__,____XX__,___XX___,
+ ____XX__,____XX__,___XX___,
+ ____XXXX,XXXXXXXX,XXXXX___,
+ ____XX__,____XX__,___XX___,
+ ____XX__,____XX__,___XX___,
+ ___XXX__,____XX__,___XX___,
+ ___XX___,____XX__,___XX___,
+ ___XX___,___XXX__,___XX___,
+ __XX____,___XXX__,XX_XX___,
+ __XX____,___XXX__,_XXXX___,
+ _XX_____,___XX___,__XX____,
+ ________,________,________,
+};
+
+/* char: 有 code:0xD3D0 */
+static GUI_CONST_STORAGE unsigned char acD3D0[72] = {
+ ________,________,________,
+ ________,___XX___,________,
+ ________,__XXX___,________,
+ ________,__XXX___,____XX__,
+ _XXXXXXX,XXXXXXXX,XXXXXXX_,
+ ________,_XXX____,________,
+ ________,XXX_____,________,
+ ________,XX______,________,
+ _______X,XXXXXXXX,XXXX____,
+ _______X,X_______,_XX_____,
+ ______XX,X_______,_XX_____,
+ _____XXX,X_______,_XX_____,
+ ____XX_X,XXXXXXXX,XXX_____,
+ ___XX__X,X_______,_XX_____,
+ __XX___X,X_______,_XX_____,
+ _______X,X_______,_XX_____,
+ _______X,XXXXXXXX,XXX_____,
+ _______X,X_______,_XX_____,
+ _______X,X_______,_XX_____,
+ _______X,X_______,_XX_____,
+ _______X,X_______,_XX_____,
+ _______X,X______X,XXX_____,
+ _______X,X_______,XX______,
+ ________,________,________,
+};
+
+/* char: 跃 code:0xD4BE */
+static GUI_CONST_STORAGE unsigned char acD4BE[72] = {
+ ________,________,________,
+ ________,________,________,
+ ________,________,___XX___,
+ __XXXXXX,XXX_____,_XXXXX__,
+ __XX____,XX__XXXX,XX______,
+ __XX____,XX_____X,X_______,
+ __XX____,XX_____X,X_______,
+ __XX____,XX_____X,X_______,
+ __XX____,XX_____X,X_______,
+ __XXXXXX,XX_____X,X____XX_,
+ __XX_XXX,XXXXXXXX,XXXXXXXX,
+ _____XXX,______XX,XX______,
+ __XXXXXX,______XX,XX______,
+ __XX_XXX,XXX___XX,XX______,
+ __XX_XXX,______XX,_XX_____,
+ __XX_XXX,_____XXX,_XX_____,
+ __XX_XXX,_____XX_,_XX_____,
+ __XX_XXX,____XXX_,__XX____,
+ __XX_XXX,XXX_XX__,__XXX___,
+ __XXXXX_,___XX___,___XX___,
+ _XXXX___,__XX____,___XXXX_,
+ ________,XXX_____,____XXXX,
+ _______X,X_______,________,
+ ________,________,________,
+};
+
+/* char: 载 code:0xD4D8 */
+static GUI_CONST_STORAGE unsigned char acD4D8[72] = {
+ ________,________,________,
+ _______X,X_____XX,________,
+ _______X,X_____XX,________,
+ _______X,X_____XX,_XXX____,
+ ___XXXXX,XXXXX_XX,__XXX___,
+ _______X,X_____XX,___XX___,
+ _______X,X_____XX,________,
+ _XXXXXXX,XXXXXXXX,XXXXXXX_,
+ ______XX,X_____XX,________,
+ ______XX,___XX_XX,___XX___,
+ _XXXXXXX,XXXXX_XX,___XXX__,
+ _____XX_,______XX,X__XX___,
+ ____XXXX,XX_____X,X_XXX___,
+ ____XX_X,XX_XX__X,X_XX____,
+ ___XXXXX,XXXXXX_X,XXXX____,
+ _______X,XX_____X,XXX_____,
+ _______X,XX______,XX______,
+ _______X,XXXXX__X,XXX_____,
+ __XXXXXX,XX____XX,XXX__XX_,
+ __XXX__X,XX___XXX,_XXX_XX_,
+ _______X,XX__XXX_,__XXXXX_,
+ _______X,XX_XX___,____XXX_,
+ _______X,X_XX____,_____XXX,
+ ________,________,________,
+};
+
+/* char: 择 code:0xD4F1 */
+static GUI_CONST_STORAGE unsigned char acD4F1[72] = {
+ ________,________,________,
+ ______XX,________,___XX___,
+ ______XX,__XXXXXX,XXXXXX__,
+ ______XX,____XX__,__XXX___,
+ ______XX,____XX__,__XX____,
+ ______XX,_____XX_,_XX_____,
+ _XXXXXXX,XXXX__XX,XXX_____,
+ ______XX,______XX,XX______,
+ ______XX,______XX,XXX_____,
+ ______XX,__XXXXX_,_XXXXXXX,
+ ______XX,XXXXX__X,X__XXX__,
+ ______XX,XXX____X,X_______,
+ ____XXXX,_______X,X_______,
+ _XXXX_XX,__XXXXXX,XXXXXX__,
+ __XX__XX,_______X,X_______,
+ ______XX,_______X,X_______,
+ ______XX,_______X,X_______,
+ ______XX,XXXXXXXX,XXXXXXX_,
+ ______XX,_______X,X_______,
+ ______XX,_______X,X_______,
+ __XXXXXX,_______X,X_______,
+ ____XXXX,_______X,X_______,
+ _____XX_,_______X,X_______,
+ ________,________,________,
+};
+
+/* char: 障 code:0xD5CF */
+static GUI_CONST_STORAGE unsigned char acD5CF[72] = {
+ ________,________,________,
+ ________,_____XX_,________,
+ ________,______XX,________,
+ __XXXXXX,X_____XX,X__XX___,
+ __XX__XX,XXXXXXXX,XXXXXX__,
+ __XX__XX,___XX___,_XX_____,
+ __XX__XX,____XX__,_XX_____,
+ __XX_XX_,____XXX_,XX______,
+ __XX_XX_,XXXXXXXX,XXXXXXX_,
+ __XX_XX_,________,________,
+ __XX_XX_,__XXXXXX,XXXXXX__,
+ __XX__XX,__XX____,___XX___,
+ __XX___X,X_XXXXXX,XXXXX___,
+ __XX___X,X_XX____,___XX___,
+ __XX___X,X_XX____,___XX___,
+ __XX___X,X_XXXXXX,XXXXX___,
+ __XXXXXX,X_XX__XX,X__XX___,
+ __XX_XXX,______XX,X____XX_,
+ __XX___X,XXXXXXXX,XXXXXXXX,
+ __XX____,______XX,X_______,
+ __XX____,______XX,X_______,
+ __XX____,______XX,X_______,
+ __XX____,______XX,X_______,
+ ________,________,________,
+};
+
+/* char: 诊 code:0xD5EF */
+static GUI_CONST_STORAGE unsigned char acD5EF[72] = {
+ ________,________,________,
+ ________,______XX,________,
+ ____XX__,_____XXX,________,
+ _____XX_,_____XXX,X_______,
+ _____XXX,____XXXX,X_______,
+ _____XXX,____XX__,XX______,
+ ________,___XXX__,XXX_____,
+ ________,___XX___,_XXX____,
+ ________,__XX____,__XXX___,
+ _XXXXXX_,_XX___XX,X__XXXXX,
+ ____XXX_,XX___XXX,____XX__,
+ ____XXX_,____XXX_,________,
+ ____XXX_,___XXX__,_XX_____,
+ ____XXX_,__XX____,XXXX____,
+ ____XXX_,_______X,XX______,
+ ____XXX_,______XX,X_______,
+ ____XXX_,XX___XX_,____XX__,
+ ____XXXX,X__XXX__,__XXXX__,
+ ____XXXX,_XXX____,_XXXX___,
+ ____XXXX,________,XXX_____,
+ _____XX_,______XX,X_______,
+ ________,___XXXX_,________,
+ ________,_XXX____,________,
+ ________,________,________,
+};
+
+/* char: 整 code:0xD5FB */
+static GUI_CONST_STORAGE unsigned char acD5FB[72] = {
+ ________,________,________,
+ _______X,X______X,X_______,
+ _______X,X______X,X_______,
+ __XXXXXX,XXXXXXXX,X_______,
+ _______X,X_____XX,XXXXXXX_,
+ _______X,X_____XX,___XX___,
+ ___XXXXX,XXXXXXXX,__XXX___,
+ ___XXX_X,X_XXXXXX,X_XXX___,
+ ___XXX_X,X_XXXX_X,X_XX____,
+ ___XXXXX,XXXXX___,XXXX____,
+ ___XXXXX,XXXX____,XXX_____,
+ _____XXX,XXXX___X,XXXX____,
+ ____XX_X,X_XX__XX,__XXXX__,
+ ___XX__X,X_XXXXX_,__XXXXX_,
+ __XXXXXX,XXXXXXXX,XXXXX___,
+ ________,___XXX__,________,
+ ________,___XXX__,_XX_____,
+ _______X,X__XXXXX,XXXX____,
+ _______X,X__XXX__,________,
+ _______X,X__XXX__,________,
+ _______X,X__XXX__,____XX__,
+ __XXXXXX,XXXXXXXX,XXXXXXX_,
+ ________,________,________,
+ ________,________,________,
+};
+
+/* char: 正 code:0xD5FD */
+static GUI_CONST_STORAGE unsigned char acD5FD[72] = {
+ ________,________,________,
+ ________,________,________,
+ ________,________,____XX__,
+ ___XXXXX,XXXXXXXX,XXXXXXX_,
+ ________,____XX__,________,
+ ________,____XX__,________,
+ ________,____XX__,________,
+ ________,____XX__,________,
+ ______XX,____XX__,________,
+ ______XX,X___XX__,________,
+ ______XX,____XX__,___XX___,
+ ______XX,____XXXX,XXXXXX__,
+ ______XX,____XX__,________,
+ ______XX,____XX__,________,
+ ______XX,____XX__,________,
+ ______XX,____XX__,________,
+ ______XX,____XX__,________,
+ ______XX,____XX__,________,
+ ______XX,____XX__,________,
+ ______XX,____XX__,____XX__,
+ _XXXXXXX,XXXXXXXX,XXXXXXX_,
+ ________,________,________,
+ ________,________,________,
+ ________,________,________,
+};
+
+/* char: 知 code:0xD6AA */
+static GUI_CONST_STORAGE unsigned char acD6AA[72] = {
+ ________,________,________,
+ ________,________,________,
+ _____XX_,________,________,
+ _____XX_,________,________,
+ _____XX_,________,________,
+ ____XXX_,________,________,
+ ____XXXX,XXXXX_XX,XXXXXXX_,
+ ____XX_X,X_____XX,____XX__,
+ ___XX__X,X_____XX,____XX__,
+ ___XX__X,X_____XX,____XX__,
+ __XX___X,X_____XX,____XX__,
+ _______X,X__XX_XX,____XX__,
+ _XXXXXXX,XXXXXXXX,____XX__,
+ _______X,X_____XX,____XX__,
+ _______X,X_____XX,____XX__,
+ _______X,XX____XX,____XX__,
+ ______XX,XXX___XX,____XX__,
+ ______XX,__XXX_XX,____XX__,
+ _____XXX,__XXX_XX,XXXXXX__,
+ _____XX_,___XXXXX,____XX__,
+ ____XX__,______XX,____XX__,
+ ___XX___,______XX,____XX__,
+ __XX____,________,________,
+ ________,________,________,
+};
+
+/* char: 至 code:0xD6C1 */
+static GUI_CONST_STORAGE unsigned char acD6C1[72] = {
+ ________,________,________,
+ ________,________,________,
+ ________,________,___XX___,
+ __XXXXXX,XXXXXXXX,XXXXXX__,
+ ________,__XXX___,________,
+ ________,_XXX____,________,
+ ________,_XX__XXX,________,
+ ________,XX_____X,X_______,
+ _______X,X_______,XXX_____,
+ ______XX,________,_XXXX___,
+ ____XXXX,XXXXXXXX,XXXXX___,
+ ____XXXX,X__XXX__,___XX___,
+ ________,___XXX__,________,
+ ________,___XXX__,________,
+ ________,___XXX__,__XX____,
+ ____XXXX,XXXXXXXX,XXXXX___,
+ ________,___XXX__,________,
+ ________,___XXX__,________,
+ ________,___XXX__,________,
+ ________,___XXX__,________,
+ ________,___XXX__,____XX__,
+ _XXXXXXX,XXXXXXXX,XXXXXXX_,
+ ________,________,________,
+ ________,________,________,
+};
+
+/* char: 置 code:0xD6C3 */
+static GUI_CONST_STORAGE unsigned char acD6C3[72] = {
+ ________,________,________,
+ ________,________,________,
+ ____XXXX,XXXXXXXX,XXXXX___,
+ ____XX__,_XX___XX,___XX___,
+ ____XX__,_XX___XX,___XX___,
+ ____XX__,_XX___XX,___XX___,
+ ____XXXX,XXXXXXXX,XXXXX___,
+ ____XX__,___XX___,___XX___,
+ ________,___XX___,___XX___,
+ ___XXXXX,XXXXXXXX,XXXXXX__,
+ ________,___XX___,_XX_____,
+ ______XX,XXXXXXXX,XXXX____,
+ ______XX,________,_XX_____,
+ ______XX,________,_XX_____,
+ ______XX,XXXXXXXX,XXX_____,
+ ______XX,________,_XX_____,
+ ______XX,XXXXXXXX,XXX_____,
+ ______XX,________,_XX_____,
+ ______XX,XXXXXXXX,XXX_____,
+ ______XX,________,_XX_____,
+ ______XX,________,_XX__XX_,
+ _XXXXXXX,XXXXXXXX,XXXXXXXX,
+ ________,________,________,
+ ________,________,________,
+};
+
+/* char: 制 code:0xD6C6 */
+static GUI_CONST_STORAGE unsigned char acD6C6[72] = {
+ ________,________,________,
+ _______X,X_______,____XX__,
+ _______X,XX______,____XX__,
+ _______X,X_______,____XX__,
+ ____XX_X,X_______,____XX__,
+ ___XXX_X,X__XX___,XXX_XX__,
+ ___XXXXX,XXXXXX__,XX__XX__,
+ ___XX__X,X_______,XX__XX__,
+ __XX___X,X_______,XX__XX__,
+ _XXXXXXX,XXXXXXX_,XX__XX__,
+ _______X,X_______,XX__XX__,
+ _______X,X_______,XX__XX__,
+ ___XXXXX,XXXXXX__,XX__XX__,
+ ___XX__X,X___XX__,XX__XX__,
+ ___XX__X,X___XX__,XX__XX__,
+ ___XX__X,X___XX__,XX__XX__,
+ ___XX__X,X___XX__,XX__XX__,
+ ___XX__X,X___XX__,____XX__,
+ ___XX__X,XXXXXX__,____XX__,
+ ___XX__X,X__XX___,____XX__,
+ _______X,X_______,____XX__,
+ _______X,X_______,_XXXXX__,
+ _______X,X_______,___XX___,
+ ________,________,________,
+};
+
+/* char: 智 code:0xD6C7 */
+static GUI_CONST_STORAGE unsigned char acD6C7[72] = {
+ ________,________,________,
+ _____XX_,________,________,
+ _____XX_,________,________,
+ ____XXXX,XXXXX_XX,XXXXXX__,
+ ____XX__,XX____XX,____XX__,
+ ___XX___,XX____XX,____XX__,
+ ___XX__X,XX____XX,____XX__,
+ __XXXXXX,XXXXXXXX,____XX__,
+ _______X,X_____XX,____XX__,
+ _______X,XXX___XX,____XX__,
+ ______XX,X_XXX_XX,XXXXXX__,
+ _____XXX,___XXXXX,____XX__,
+ ____XXX_,___XX_XX,________,
+ ___XX__X,XXXXXXXX,XXXX____,
+ __XX___X,X_______,_XX_____,
+ _______X,X_______,_XX_____,
+ _______X,XXXXXXXX,XXX_____,
+ _______X,X_______,_XX_____,
+ _______X,X_______,_XX_____,
+ _______X,X_______,_XX_____,
+ _______X,XXXXXXXX,XXXX____,
+ _______X,X_______,_XXX____,
+ ________,________,_XX_____,
+ ________,________,________,
+};
+
+/* char: 中 code:0xD6D0 */
+static GUI_CONST_STORAGE unsigned char acD6D0[72] = {
+ ________,________,________,
+ ________,___XX___,________,
+ ________,___XXX__,________,
+ ________,___XX___,________,
+ ________,___XX___,________,
+ ________,___XX___,________,
+ ___XXXXX,XXXXXXXX,XXXXXX__,
+ ___XXX__,___XX___,___XXX__,
+ ___XXX__,___XX___,___XXX__,
+ ___XXX__,___XX___,___XXX__,
+ ___XXX__,___XX___,___XXX__,
+ ___XXX__,___XX___,___XXX__,
+ ___XXX__,___XX___,___XXX__,
+ ___XXXXX,XXXXXXXX,XXXXXX__,
+ ___XXX__,___XX___,___XXX__,
+ ___XX___,___XX___,___XX___,
+ ________,___XX___,________,
+ ________,___XX___,________,
+ ________,___XX___,________,
+ ________,___XX___,________,
+ ________,___XXX__,________,
+ ________,___XXX__,________,
+ ________,___XX___,________,
+ ________,________,________,
+};
+
+/* char: 重 code:0xD6D8 */
+static GUI_CONST_STORAGE unsigned char acD6D8[72] = {
+ ________,________,________,
+ ________,________,________,
+ ________,________,XXX_____,
+ ________,__XXXXXX,XXXX____,
+ ____XXXX,XXXXX___,________,
+ ________,___XX___,________,
+ __XXXXXX,XXXXXXXX,XXXXXX__,
+ ________,___XX___,________,
+ ________,___XX___,________,
+ _____XXX,XXXXXXXX,XXXX____,
+ _____XXX,___XX___,_XX_____,
+ _____XXX,___XX___,_XX_____,
+ _____XXX,XXXXXXXX,XXX_____,
+ _____XXX,___XX___,_XX_____,
+ _____XXX,___XX___,_XX_____,
+ _____XXX,XXXXXXXX,XXX_____,
+ _____XXX,___XX___,_XX_____,
+ ________,___XX___,__XX____,
+ ___XXXXX,XXXXXXXX,XXXXX___,
+ ________,___XX___,________,
+ ________,___XX___,____XXX_,
+ _XXXXXXX,XXXXXXXX,XXXXXXX_,
+ ________,________,________,
+ ________,________,________,
+};
+
+/* char: 主 code:0xD6F7 */
+static GUI_CONST_STORAGE unsigned char acD6F7[72] = {
+ ________,________,________,
+ ________,________,________,
+ ________,_XX_____,________,
+ ________,__XXX___,________,
+ ________,___XXX__,________,
+ ________,___XXX__,________,
+ ________,____XX__,___XX___,
+ ___XXXXX,XXXXXXXX,XXXXXX__,
+ ________,___XXX__,________,
+ ________,___XXX__,________,
+ ________,___XXX__,________,
+ ________,___XXX__,________,
+ ________,___XXX__,________,
+ ________,___XXX__,__XX____,
+ _____XXX,XXXXXXXX,XXXXX___,
+ ________,___XXX__,________,
+ ________,___XXX__,________,
+ ________,___XXX__,________,
+ ________,___XXX__,________,
+ ________,___XXX__,________,
+ ________,___XXX__,____XX__,
+ _XXXXXXX,XXXXXXXX,XXXXXXX_,
+ ________,________,________,
+ ________,________,________,
+};
+
+/* char: 准 code:0xD7BC */
+static GUI_CONST_STORAGE unsigned char acD7BC[72] = {
+ ________,________,________,
+ ________,___XX__X,X_______,
+ ________,___XXX_X,XX______,
+ __XXX___,__XXX___,XX______,
+ ___XXX__,__XX____,XX__XX__,
+ ___XXX_X,X_XXXXXX,XXXXXXX_,
+ ____XX_X,XXXX___X,XX______,
+ ______XX,_XXX___X,XX______,
+ ______XX,XXXX___X,XX______,
+ _____XX_,XXXX___X,XX______,
+ _____XXX,X_XXXXXX,XXXXXX__,
+ _____XXX,__XX___X,XX______,
+ ____XX__,__XX___X,XX______,
+ ___XXX__,__XX___X,XX______,
+ __XXXX__,__XX___X,XX__XX__,
+ ___XXX__,__XXXXXX,XXXXXXX_,
+ ___XX___,__XX___X,XX______,
+ ___XX___,__XX___X,XX______,
+ ___XX___,__XX___X,XX______,
+ ___XX___,__XX___X,XX______,
+ ___XX___,__XXXXXX,XXXXXXX_,
+ ________,__XX____,________,
+ ________,__XX____,________,
+ ________,________,________,
+};
+
+/* char: 自 code:0xD7D4 */
+static GUI_CONST_STORAGE unsigned char acD7D4[72] = {
+ ________,________,________,
+ ________,__XXX___,________,
+ ________,__XXX___,________,
+ ________,__XX____,________,
+ ________,__XX____,________,
+ _____XXX,XXXXXXXX,XXXXX___,
+ _____XX_,________,__XX____,
+ _____XX_,________,__XX____,
+ _____XX_,________,__XX____,
+ _____XX_,________,__XX____,
+ _____XXX,XXXXXXXX,XXXX____,
+ _____XX_,________,__XX____,
+ _____XX_,________,__XX____,
+ _____XX_,________,__XX____,
+ _____XX_,________,__XX____,
+ _____XXX,XXXXXXXX,XXXX____,
+ _____XX_,________,__XX____,
+ _____XX_,________,__XX____,
+ _____XX_,________,__XX____,
+ _____XX_,________,__XX____,
+ _____XXX,XXXXXXXX,XXXX____,
+ _____XX_,________,__XX____,
+ _____XX_,________,__XX____,
+ ________,________,________,
+};
+
+/* char: 字 code:0xD7D6 */
+static GUI_CONST_STORAGE unsigned char acD7D6[72] = {
+ ________,________,________,
+ ________,__XX____,________,
+ ________,___XXX__,________,
+ ________,___XXX__,________,
+ ____XX__,____XX__,____XX__,
+ ____XXXX,XXXXXXXX,XXXXXXX_,
+ ____XX__,________,___XXX__,
+ ___XXX__,________,___XX___,
+ __XXXXXX,XXXXXXXX,XXXX____,
+ ________,_______X,XXX_____,
+ ________,______XX,X_______,
+ ________,_____XX_,________,
+ ________,___XXX__,________,
+ ________,___XXX__,________,
+ _XXXXXXX,XXXXXXXX,XXXXXXX_,
+ ________,___XXX__,________,
+ ________,___XXX__,________,
+ ________,___XXX__,________,
+ ________,___XXX__,________,
+ ________,___XXX__,________,
+ ________,___XXX__,________,
+ ________,XXXXXX__,________,
+ ________,__XXX___,________,
+ ________,________,________,
+};
+
+/* char: 足 code:0xD7E3 */
+static GUI_CONST_STORAGE unsigned char acD7E3[72] = {
+ ________,________,________,
+ ________,________,________,
+ ________,________,_XX_____,
+ ______XX,XXXXXXXX,XXXX____,
+ ______XX,________,_XX_____,
+ ______XX,________,_XX_____,
+ ______XX,________,_XX_____,
+ ______XX,________,_XX_____,
+ ______XX,________,_XX_____,
+ ______XX,XXXXXXXX,XXX_____,
+ ______XX,___XXX__,_XX_____,
+ ________,___XXX__,________,
+ ________,___XXX__,________,
+ ______XX,___XXX__,________,
+ _____XXX,___XXXXX,XXXXX___,
+ _____XXX,___XXX__,________,
+ _____XX_,___XXX__,________,
+ ____XXXX,___XXX__,________,
+ ____XXXX,XX_XXX__,________,
+ ____XX__,XXXXXX__,________,
+ ___XX___,_XXXXX__,________,
+ __XX____,___XXXXX,XXXXXXXX,
+ _XX_____,______XX,XXXXXX__,
+ ________,________,________,
+};
+
+static GUI_CONST_STORAGE GUI_CHARINFO Cinfo[245] = {
+ { 10, 10, 2, (unsigned char *)&ac0020 }, /*0: */
+ { 8, 8, 2, (unsigned char *)&ac0021 }, /*1: !*/
+ { 12, 12, 2, (unsigned char *)&ac0022 }, /*2: "*/
+ { 12, 12, 2, (unsigned char *)&ac0023 }, /*3: #*/
+ { 11, 11, 2, (unsigned char *)&ac0024 }, /*4: $*/
+ { 12, 12, 2, (unsigned char *)&ac0025 }, /*5: %*/
+ { 13, 13, 2, (unsigned char *)&ac0026 }, /*6: &*/
+ { 6, 6, 2, (unsigned char *)&ac0027 }, /*7: '*/
+ { 12, 12, 2, (unsigned char *)&ac0028 }, /*8: (*/
+ { 8, 8, 2, (unsigned char *)&ac0029 }, /*9: )*/
+ { 13, 13, 2, (unsigned char *)&ac002A }, /*10: **/
+ { 13, 13, 2, (unsigned char *)&ac002B }, /*11: +*/
+ { 6, 6, 2, (unsigned char *)&ac002C }, /*12: ,*/
+ { 12, 12, 2, (unsigned char *)&ac002D }, /*13: -*/
+ { 6, 6, 2, (unsigned char *)&ac002E }, /*14: .*/
+ { 12, 12, 2, (unsigned char *)&ac002F }, /*15: /*/
+ { 12, 12, 2, (unsigned char *)&ac0030 }, /*16: 0*/
+ { 11, 11, 2, (unsigned char *)&ac0031 }, /*17: 1*/
+ { 11, 11, 2, (unsigned char *)&ac0032 }, /*18: 2*/
+ { 11, 11, 2, (unsigned char *)&ac0033 }, /*19: 3*/
+ { 13, 13, 2, (unsigned char *)&ac0034 }, /*20: 4*/
+ { 11, 11, 2, (unsigned char *)&ac0035 }, /*21: 5*/
+ { 12, 12, 2, (unsigned char *)&ac0036 }, /*22: 6*/
+ { 12, 12, 2, (unsigned char *)&ac0037 }, /*23: 7*/
+ { 12, 12, 2, (unsigned char *)&ac0038 }, /*24: 8*/
+ { 12, 12, 2, (unsigned char *)&ac0039 }, /*25: 9*/
+ { 9, 9, 2, (unsigned char *)&ac003A }, /*26: :*/
+ { 8, 8, 2, (unsigned char *)&ac003B }, /*27: ;*/
+ { 12, 12, 2, (unsigned char *)&ac003C }, /*28: <*/
+ { 12, 12, 2, (unsigned char *)&ac003D }, /*29: =*/
+ { 12, 12, 2, (unsigned char *)&ac003E }, /*30: >*/
+ { 13, 13, 2, (unsigned char *)&ac003F }, /*31: ?*/
+ { 12, 12, 2, (unsigned char *)&ac0040 }, /*32: @*/
+ { 13, 13, 2, (unsigned char *)&ac0041 }, /*33: A*/
+ { 12, 12, 2, (unsigned char *)&ac0042 }, /*34: B*/
+ { 12, 12, 2, (unsigned char *)&ac0043 }, /*35: C*/
+ { 12, 12, 2, (unsigned char *)&ac0044 }, /*36: D*/
+ { 12, 12, 2, (unsigned char *)&ac0045 }, /*37: E*/
+ { 12, 12, 2, (unsigned char *)&ac0046 }, /*38: F*/
+ { 13, 13, 2, (unsigned char *)&ac0047 }, /*39: G*/
+ { 13, 13, 2, (unsigned char *)&ac0048 }, /*40: H*/
+ { 11, 11, 2, (unsigned char *)&ac0049 }, /*41: I*/
+ { 12, 12, 2, (unsigned char *)&ac004A }, /*42: J*/
+ { 12, 12, 2, (unsigned char *)&ac004B }, /*43: K*/
+ { 12, 12, 2, (unsigned char *)&ac004C }, /*44: L*/
+ { 12, 12, 2, (unsigned char *)&ac004D }, /*45: M*/
+ { 13, 13, 2, (unsigned char *)&ac004E }, /*46: N*/
+ { 12, 12, 2, (unsigned char *)&ac004F }, /*47: O*/
+ { 12, 12, 2, (unsigned char *)&ac0050 }, /*48: P*/
+ { 12, 12, 2, (unsigned char *)&ac0051 }, /*49: Q*/
+ { 13, 13, 2, (unsigned char *)&ac0052 }, /*50: R*/
+ { 12, 12, 2, (unsigned char *)&ac0053 }, /*51: S*/
+ { 13, 13, 2, (unsigned char *)&ac0054 }, /*52: T*/
+ { 12, 12, 2, (unsigned char *)&ac0055 }, /*53: U*/
+ { 12, 12, 2, (unsigned char *)&ac0056 }, /*54: V*/
+ { 13, 13, 2, (unsigned char *)&ac0057 }, /*55: W*/
+ { 12, 12, 2, (unsigned char *)&ac0058 }, /*56: X*/
+ { 13, 13, 2, (unsigned char *)&ac0059 }, /*57: Y*/
+ { 12, 12, 2, (unsigned char *)&ac005A }, /*58: Z*/
+ { 11, 11, 2, (unsigned char *)&ac005B }, /*59: [*/
+ { 12, 12, 2, (unsigned char *)&ac005C }, /*60: \*/
+ { 8, 8, 2, (unsigned char *)&ac005D }, /*61: ]*/
+ { 10, 10, 2, (unsigned char *)&ac005E }, /*62: ^*/
+ { 13, 13, 2, (unsigned char *)&ac005F }, /*63: _*/
+ { 8, 8, 2, (unsigned char *)&ac0060 }, /*64: `*/
+ { 13, 13, 2, (unsigned char *)&ac0061 }, /*65: a*/
+ { 12, 12, 2, (unsigned char *)&ac0062 }, /*66: b*/
+ { 11, 11, 2, (unsigned char *)&ac0063 }, /*67: c*/
+ { 12, 12, 2, (unsigned char *)&ac0064 }, /*68: d*/
+ { 12, 12, 2, (unsigned char *)&ac0065 }, /*69: e*/
+ { 12, 12, 2, (unsigned char *)&ac0066 }, /*70: f*/
+ { 12, 12, 2, (unsigned char *)&ac0067 }, /*71: g*/
+ { 12, 12, 2, (unsigned char *)&ac0068 }, /*72: h*/
+ { 11, 11, 2, (unsigned char *)&ac0069 }, /*73: i*/
+ { 10, 10, 2, (unsigned char *)&ac006A }, /*74: j*/
+ { 12, 12, 2, (unsigned char *)&ac006B }, /*75: k*/
+ { 11, 11, 2, (unsigned char *)&ac006C }, /*76: l*/
+ { 13, 13, 2, (unsigned char *)&ac006D }, /*77: m*/
+ { 12, 12, 2, (unsigned char *)&ac006E }, /*78: n*/
+ { 12, 12, 2, (unsigned char *)&ac006F }, /*79: o*/
+ { 12, 12, 2, (unsigned char *)&ac0070 }, /*80: p*/
+ { 12, 12, 2, (unsigned char *)&ac0071 }, /*81: q*/
+ { 12, 12, 2, (unsigned char *)&ac0072 }, /*82: r*/
+ { 11, 11, 2, (unsigned char *)&ac0073 }, /*83: s*/
+ { 11, 11, 2, (unsigned char *)&ac0074 }, /*84: t*/
+ { 12, 12, 2, (unsigned char *)&ac0075 }, /*85: u*/
+ { 12, 12, 2, (unsigned char *)&ac0076 }, /*86: v*/
+ { 13, 13, 2, (unsigned char *)&ac0077 }, /*87: w*/
+ { 12, 12, 2, (unsigned char *)&ac0078 }, /*88: x*/
+ { 12, 12, 2, (unsigned char *)&ac0079 }, /*89: y*/
+ { 11, 11, 2, (unsigned char *)&ac007A }, /*90: z*/
+ { 11, 11, 2, (unsigned char *)&ac007B }, /*91: {*/
+ { 8, 8, 2, (unsigned char *)&ac007C }, /*92: |*/
+ { 8, 8, 2, (unsigned char *)&ac007D }, /*93: }*/
+ { 12, 12, 2, (unsigned char *)&ac007E }, /*94: ~*/
+ { 10, 10, 2, (unsigned char *)&ac007F }, /*95: */
+ { 9, 9, 3, (unsigned char *)&acA1A3 }, /*96: 。*/
+ { 10, 10, 3, (unsigned char *)&acA1E3 }, /*97: °*/
+ { 22, 22, 3, (unsigned char *)&acA1E6 }, /*98: ℃*/
+ { 7, 7, 3, (unsigned char *)&acA3AC }, /*99: ,*/
+ { 21, 21, 3, (unsigned char *)&acA848 }, /*100: ℉*/
+ { 24, 24, 3, (unsigned char *)&acB0DC }, /*101: 败*/
+ { 23, 23, 3, (unsigned char *)&acB0E6 }, /*102: 版*/
+ { 23, 23, 3, (unsigned char *)&acB0FC }, /*103: 包*/
+ { 24, 24, 3, (unsigned char *)&acB1A3 }, /*104: 保*/
+ { 24, 24, 3, (unsigned char *)&acB1B8 }, /*105: 备*/
+ { 24, 24, 3, (unsigned char *)&acB1BE }, /*106: 本*/
+ { 23, 23, 3, (unsigned char *)&acB1E0 }, /*107: 编*/
+ { 24, 24, 3, (unsigned char *)&acB1E4 }, /*108: 变*/
+ { 23, 23, 3, (unsigned char *)&acB2BB }, /*109: 不*/
+ { 24, 24, 3, (unsigned char *)&acB2CB }, /*110: 菜*/
+ { 24, 24, 3, (unsigned char *)&acB2CE }, /*111: 参*/
+ { 22, 22, 3, (unsigned char *)&acB2E2 }, /*112: 测*/
+ { 24, 24, 3, (unsigned char *)&acB2E9 }, /*113: 查*/
+ { 23, 23, 3, (unsigned char *)&acB3A3 }, /*114: 常*/
+ { 23, 23, 3, (unsigned char *)&acB3A7 }, /*115: 厂*/
+ { 24, 24, 3, (unsigned char *)&acB3AC }, /*116: 超*/
+ { 24, 24, 3, (unsigned char *)&acB3C9 }, /*117: 成*/
+ { 24, 24, 3, (unsigned char *)&acB3CC }, /*118: 程*/
+ { 22, 22, 3, (unsigned char *)&acB3F6 }, /*119: 出*/
+ { 23, 23, 3, (unsigned char *)&acB4E6 }, /*120: 存*/
+ { 24, 24, 3, (unsigned char *)&acB4ED }, /*121: 错*/
+ { 23, 23, 3, (unsigned char *)&acB5A5 }, /*122: 单*/
+ { 23, 23, 3, (unsigned char *)&acB5AB }, /*123: 但*/
+ { 23, 23, 3, (unsigned char *)&acB5B1 }, /*124: 当*/
+ { 23, 23, 3, (unsigned char *)&acB5C4 }, /*125: 的*/
+ { 23, 23, 3, (unsigned char *)&acB5E7 }, /*126: 电*/
+ { 23, 23, 3, (unsigned char *)&acB6A8 }, /*127: 定*/
+ { 23, 23, 3, (unsigned char *)&acB6AF }, /*128: 动*/
+ { 24, 24, 3, (unsigned char *)&acB6C8 }, /*129: 度*/
+ { 23, 23, 3, (unsigned char *)&acB6CF }, /*130: 断*/
+ { 23, 23, 3, (unsigned char *)&acB6D4 }, /*131: 对*/
+ { 24, 24, 3, (unsigned char *)&acB7A2 }, /*132: 发*/
+ { 23, 23, 3, (unsigned char *)&acB7A7 }, /*133: 阀*/
+ { 24, 24, 3, (unsigned char *)&acB7B5 }, /*134: 返*/
+ { 24, 24, 3, (unsigned char *)&acB8B4 }, /*135: 复*/
+ { 24, 24, 3, (unsigned char *)&acB8C4 }, /*136: 改*/
+ { 23, 23, 3, (unsigned char *)&acB8F1 }, /*137: 格*/
+ { 23, 23, 3, (unsigned char *)&acB9A6 }, /*138: 功*/
+ { 23, 23, 3, (unsigned char *)&acB9AB }, /*139: 公*/
+ { 24, 24, 3, (unsigned char *)&acB9CA }, /*140: 故*/
+ { 24, 24, 3, (unsigned char *)&acB9E6 }, /*141: 规*/
+ { 23, 23, 3, (unsigned char *)&acBAC5 }, /*142: 号*/
+ { 23, 23, 3, (unsigned char *)&acBAF3 }, /*143: 后*/
+ { 23, 23, 3, (unsigned char *)&acBBA4 }, /*144: 护*/
+ { 24, 24, 3, (unsigned char *)&acBBB6 }, /*145: 欢*/
+ { 23, 23, 3, (unsigned char *)&acBBD6 }, /*146: 恢*/
+ { 22, 22, 3, (unsigned char *)&acBBD8 }, /*147: 回*/
+ { 24, 24, 3, (unsigned char *)&acBBF2 }, /*148: 或*/
+ { 23, 23, 3, (unsigned char *)&acBCAD }, /*149: 辑*/
+ { 24, 24, 3, (unsigned char *)&acBCBC }, /*150: 技*/
+ { 23, 23, 3, (unsigned char *)&acBCC6 }, /*151: 计*/
+ { 23, 23, 3, (unsigned char *)&acBCD3 }, /*152: 加*/
+ { 23, 23, 3, (unsigned char *)&acBCEC }, /*153: 检*/
+ { 24, 24, 3, (unsigned char *)&acBCFC }, /*154: 键*/
+ { 23, 23, 3, (unsigned char *)&acBCFE }, /*155: 件*/
+ { 24, 24, 3, (unsigned char *)&acBDAD }, /*156: 江*/
+ { 24, 24, 3, (unsigned char *)&acBDD7 }, /*157: 阶*/
+ { 24, 24, 3, (unsigned char *)&acBDF8 }, /*158: 进*/
+ { 23, 23, 3, (unsigned char *)&acBEDD }, /*159: 据*/
+ { 23, 23, 3, (unsigned char *)&acBEDE }, /*160: 巨*/
+ { 23, 23, 3, (unsigned char *)&acBFD8 }, /*161: 控*/
+ { 24, 24, 3, (unsigned char *)&acC0A8 }, /*162: 括*/
+ { 24, 24, 3, (unsigned char *)&acC1BF }, /*163: 量*/
+ { 24, 24, 3, (unsigned char *)&acC1F7 }, /*164: 流*/
+ { 23, 23, 3, (unsigned char *)&acC2EB }, /*165: 码*/
+ { 23, 23, 3, (unsigned char *)&acC2FA }, /*166: 满*/
+ { 22, 22, 3, (unsigned char *)&acC3C5 }, /*167: 门*/
+ { 23, 23, 3, (unsigned char *)&acC3DC }, /*168: 密*/
+ { 24, 24, 3, (unsigned char *)&acC3E6 }, /*169: 面*/
+ { 23, 23, 3, (unsigned char *)&acC3EB }, /*170: 秒*/
+ { 23, 23, 3, (unsigned char *)&acC4AC }, /*171: 默*/
+ { 20, 20, 3, (unsigned char *)&acC4BF }, /*172: 目*/
+ { 24, 24, 3, (unsigned char *)&acC4DC }, /*173: 能*/
+ { 24, 24, 3, (unsigned char *)&acC5E4 }, /*174: 配*/
+ { 24, 24, 3, (unsigned char *)&acC6C2 }, /*175: 坡*/
+ { 21, 21, 3, (unsigned char *)&acC6F4 }, /*176: 启*/
+ { 23, 23, 3, (unsigned char *)&acC6F7 }, /*177: 器*/
+ { 23, 23, 3, (unsigned char *)&acC7B0 }, /*178: 前*/
+ { 23, 23, 3, (unsigned char *)&acC7EB }, /*179: 请*/
+ { 24, 24, 3, (unsigned char *)&acC7F3 }, /*180: 求*/
+ { 24, 24, 3, (unsigned char *)&acC7FD }, /*181: 驱*/
+ { 24, 24, 3, (unsigned char *)&acC8A1 }, /*182: 取*/
+ { 23, 23, 3, (unsigned char *)&acC8CF }, /*183: 认*/
+ { 24, 24, 3, (unsigned char *)&acC8EB }, /*184: 入*/
+ { 24, 24, 3, (unsigned char *)&acC9E8 }, /*185: 设*/
+ { 23, 23, 3, (unsigned char *)&acC9FA }, /*186: 生*/
+ { 24, 24, 3, (unsigned char *)&acCAA7 }, /*187: 失*/
+ { 23, 23, 3, (unsigned char *)&acCAAF }, /*188: 石*/
+ { 23, 23, 3, (unsigned char *)&acCAB1 }, /*189: 时*/
+ { 23, 23, 3, (unsigned char *)&acCAB5 }, /*190: 实*/
+ { 24, 24, 3, (unsigned char *)&acCAB9 }, /*191: 使*/
+ { 24, 24, 3, (unsigned char *)&acCAD4 }, /*192: 试*/
+ { 23, 23, 3, (unsigned char *)&acCAD7 }, /*193: 首*/
+ { 23, 23, 3, (unsigned char *)&acCAE4 }, /*194: 输*/
+ { 23, 23, 3, (unsigned char *)&acCAF5 }, /*195: 术*/
+ { 23, 23, 3, (unsigned char *)&acCAFD }, /*196: 数*/
+ { 21, 21, 3, (unsigned char *)&acCBBE }, /*197: 司*/
+ { 23, 23, 3, (unsigned char *)&acCBD5 }, /*198: 苏*/
+ { 24, 24, 3, (unsigned char *)&acCBF9 }, /*199: 所*/
+ { 24, 24, 3, (unsigned char *)&acCCD8 }, /*200: 特*/
+ { 24, 24, 3, (unsigned char *)&acCCF5 }, /*201: 条*/
+ { 24, 24, 3, (unsigned char *)&acCEAC }, /*202: 维*/
+ { 23, 23, 3, (unsigned char *)&acCEB4 }, /*203: 未*/
+ { 24, 24, 3, (unsigned char *)&acCEBB }, /*204: 位*/
+ { 24, 24, 3, (unsigned char *)&acCEC2 }, /*205: 温*/
+ { 24, 24, 3, (unsigned char *)&acCEF3 }, /*206: 误*/
+ { 23, 23, 3, (unsigned char *)&acCFA2 }, /*207: 息*/
+ { 23, 23, 3, (unsigned char *)&acCFDE }, /*208: 限*/
+ { 23, 23, 3, (unsigned char *)&acCFEE }, /*209: 项*/
+ { 23, 23, 3, (unsigned char *)&acCFFB }, /*210: 消*/
+ { 24, 24, 3, (unsigned char *)&acD0A3 }, /*211: 校*/
+ { 23, 23, 3, (unsigned char *)&acD0B1 }, /*212: 斜*/
+ { 23, 23, 3, (unsigned char *)&acD0C5 }, /*213: 信*/
+ { 23, 23, 3, (unsigned char *)&acD0D0 }, /*214: 行*/
+ { 24, 24, 3, (unsigned char *)&acD0D4 }, /*215: 性*/
+ { 23, 23, 3, (unsigned char *)&acD0DE }, /*216: 修*/
+ { 23, 23, 3, (unsigned char *)&acD0E8 }, /*217: 需*/
+ { 23, 23, 3, (unsigned char *)&acD1A1 }, /*218: 选*/
+ { 23, 23, 3, (unsigned char *)&acD2AA }, /*219: 要*/
+ { 22, 22, 3, (unsigned char *)&acD2B3 }, /*220: 页*/
+ { 23, 23, 3, (unsigned char *)&acD2BB }, /*221: 一*/
+ { 23, 23, 3, (unsigned char *)&acD2D1 }, /*222: 已*/
+ { 24, 24, 3, (unsigned char *)&acD3AD }, /*223: 迎*/
+ { 22, 22, 3, (unsigned char *)&acD3C3 }, /*224: 用*/
+ { 23, 23, 3, (unsigned char *)&acD3D0 }, /*225: 有*/
+ { 24, 24, 3, (unsigned char *)&acD4BE }, /*226: 跃*/
+ { 24, 24, 3, (unsigned char *)&acD4D8 }, /*227: 载*/
+ { 24, 24, 3, (unsigned char *)&acD4F1 }, /*228: 择*/
+ { 24, 24, 3, (unsigned char *)&acD5CF }, /*229: 障*/
+ { 24, 24, 3, (unsigned char *)&acD5EF }, /*230: 诊*/
+ { 23, 23, 3, (unsigned char *)&acD5FB }, /*231: 整*/
+ { 23, 23, 3, (unsigned char *)&acD5FD }, /*232: 正*/
+ { 23, 23, 3, (unsigned char *)&acD6AA }, /*233: 知*/
+ { 23, 23, 3, (unsigned char *)&acD6C1 }, /*234: 至*/
+ { 24, 24, 3, (unsigned char *)&acD6C3 }, /*235: 置*/
+ { 22, 22, 3, (unsigned char *)&acD6C6 }, /*236: 制*/
+ { 22, 22, 3, (unsigned char *)&acD6C7 }, /*237: 智*/
+ { 22, 22, 3, (unsigned char *)&acD6D0 }, /*238: 中*/
+ { 23, 23, 3, (unsigned char *)&acD6D8 }, /*239: 重*/
+ { 23, 23, 3, (unsigned char *)&acD6F7 }, /*240: 主*/
+ { 23, 23, 3, (unsigned char *)&acD7BC }, /*241: 准*/
+ { 21, 21, 3, (unsigned char *)&acD7D4 }, /*242: 自*/
+ { 23, 23, 3, (unsigned char *)&acD7D6 }, /*243: 字*/
+ { 24, 24, 3, (unsigned char *)&acD7E3 }, /*244: 足*/
+};
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop148 = {
+ 0xD7E3, /*start :足*/
+ 0xD7E3, /*end :足, len=1*/
+ &Cinfo[ 244 ],
+ (void*)0
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop147 = {
+ 0xD7D6, /*start :字*/
+ 0xD7D6, /*end :字, len=1*/
+ &Cinfo[ 243 ],
+ &Prop148
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop146 = {
+ 0xD7D4, /*start :自*/
+ 0xD7D4, /*end :自, len=1*/
+ &Cinfo[ 242 ],
+ &Prop147
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop145 = {
+ 0xD7BC, /*start :准*/
+ 0xD7BC, /*end :准, len=1*/
+ &Cinfo[ 241 ],
+ &Prop146
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop144 = {
+ 0xD6F7, /*start :主*/
+ 0xD6F7, /*end :主, len=1*/
+ &Cinfo[ 240 ],
+ &Prop145
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop143 = {
+ 0xD6D8, /*start :重*/
+ 0xD6D8, /*end :重, len=1*/
+ &Cinfo[ 239 ],
+ &Prop144
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop142 = {
+ 0xD6D0, /*start :中*/
+ 0xD6D0, /*end :中, len=1*/
+ &Cinfo[ 238 ],
+ &Prop143
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop141 = {
+ 0xD6C6, /*start :制*/
+ 0xD6C7, /*end :智, len=2*/
+ &Cinfo[ 236 ],
+ &Prop142
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop140 = {
+ 0xD6C3, /*start :置*/
+ 0xD6C3, /*end :置, len=1*/
+ &Cinfo[ 235 ],
+ &Prop141
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop139 = {
+ 0xD6C1, /*start :至*/
+ 0xD6C1, /*end :至, len=1*/
+ &Cinfo[ 234 ],
+ &Prop140
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop138 = {
+ 0xD6AA, /*start :知*/
+ 0xD6AA, /*end :知, len=1*/
+ &Cinfo[ 233 ],
+ &Prop139
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop137 = {
+ 0xD5FD, /*start :正*/
+ 0xD5FD, /*end :正, len=1*/
+ &Cinfo[ 232 ],
+ &Prop138
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop136 = {
+ 0xD5FB, /*start :整*/
+ 0xD5FB, /*end :整, len=1*/
+ &Cinfo[ 231 ],
+ &Prop137
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop135 = {
+ 0xD5EF, /*start :诊*/
+ 0xD5EF, /*end :诊, len=1*/
+ &Cinfo[ 230 ],
+ &Prop136
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop134 = {
+ 0xD5CF, /*start :障*/
+ 0xD5CF, /*end :障, len=1*/
+ &Cinfo[ 229 ],
+ &Prop135
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop133 = {
+ 0xD4F1, /*start :择*/
+ 0xD4F1, /*end :择, len=1*/
+ &Cinfo[ 228 ],
+ &Prop134
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop132 = {
+ 0xD4D8, /*start :载*/
+ 0xD4D8, /*end :载, len=1*/
+ &Cinfo[ 227 ],
+ &Prop133
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop131 = {
+ 0xD4BE, /*start :跃*/
+ 0xD4BE, /*end :跃, len=1*/
+ &Cinfo[ 226 ],
+ &Prop132
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop130 = {
+ 0xD3D0, /*start :有*/
+ 0xD3D0, /*end :有, len=1*/
+ &Cinfo[ 225 ],
+ &Prop131
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop129 = {
+ 0xD3C3, /*start :用*/
+ 0xD3C3, /*end :用, len=1*/
+ &Cinfo[ 224 ],
+ &Prop130
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop128 = {
+ 0xD3AD, /*start :迎*/
+ 0xD3AD, /*end :迎, len=1*/
+ &Cinfo[ 223 ],
+ &Prop129
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop127 = {
+ 0xD2D1, /*start :已*/
+ 0xD2D1, /*end :已, len=1*/
+ &Cinfo[ 222 ],
+ &Prop128
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop126 = {
+ 0xD2BB, /*start :一*/
+ 0xD2BB, /*end :一, len=1*/
+ &Cinfo[ 221 ],
+ &Prop127
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop125 = {
+ 0xD2B3, /*start :页*/
+ 0xD2B3, /*end :页, len=1*/
+ &Cinfo[ 220 ],
+ &Prop126
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop124 = {
+ 0xD2AA, /*start :要*/
+ 0xD2AA, /*end :要, len=1*/
+ &Cinfo[ 219 ],
+ &Prop125
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop123 = {
+ 0xD1A1, /*start :选*/
+ 0xD1A1, /*end :选, len=1*/
+ &Cinfo[ 218 ],
+ &Prop124
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop122 = {
+ 0xD0E8, /*start :需*/
+ 0xD0E8, /*end :需, len=1*/
+ &Cinfo[ 217 ],
+ &Prop123
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop121 = {
+ 0xD0DE, /*start :修*/
+ 0xD0DE, /*end :修, len=1*/
+ &Cinfo[ 216 ],
+ &Prop122
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop120 = {
+ 0xD0D4, /*start :性*/
+ 0xD0D4, /*end :性, len=1*/
+ &Cinfo[ 215 ],
+ &Prop121
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop119 = {
+ 0xD0D0, /*start :行*/
+ 0xD0D0, /*end :行, len=1*/
+ &Cinfo[ 214 ],
+ &Prop120
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop118 = {
+ 0xD0C5, /*start :信*/
+ 0xD0C5, /*end :信, len=1*/
+ &Cinfo[ 213 ],
+ &Prop119
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop117 = {
+ 0xD0B1, /*start :斜*/
+ 0xD0B1, /*end :斜, len=1*/
+ &Cinfo[ 212 ],
+ &Prop118
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop116 = {
+ 0xD0A3, /*start :校*/
+ 0xD0A3, /*end :校, len=1*/
+ &Cinfo[ 211 ],
+ &Prop117
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop115 = {
+ 0xCFFB, /*start :消*/
+ 0xCFFB, /*end :消, len=1*/
+ &Cinfo[ 210 ],
+ &Prop116
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop114 = {
+ 0xCFEE, /*start :项*/
+ 0xCFEE, /*end :项, len=1*/
+ &Cinfo[ 209 ],
+ &Prop115
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop113 = {
+ 0xCFDE, /*start :限*/
+ 0xCFDE, /*end :限, len=1*/
+ &Cinfo[ 208 ],
+ &Prop114
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop112 = {
+ 0xCFA2, /*start :息*/
+ 0xCFA2, /*end :息, len=1*/
+ &Cinfo[ 207 ],
+ &Prop113
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop111 = {
+ 0xCEF3, /*start :误*/
+ 0xCEF3, /*end :误, len=1*/
+ &Cinfo[ 206 ],
+ &Prop112
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop110 = {
+ 0xCEC2, /*start :温*/
+ 0xCEC2, /*end :温, len=1*/
+ &Cinfo[ 205 ],
+ &Prop111
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop109 = {
+ 0xCEBB, /*start :位*/
+ 0xCEBB, /*end :位, len=1*/
+ &Cinfo[ 204 ],
+ &Prop110
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop108 = {
+ 0xCEB4, /*start :未*/
+ 0xCEB4, /*end :未, len=1*/
+ &Cinfo[ 203 ],
+ &Prop109
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop107 = {
+ 0xCEAC, /*start :维*/
+ 0xCEAC, /*end :维, len=1*/
+ &Cinfo[ 202 ],
+ &Prop108
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop106 = {
+ 0xCCF5, /*start :条*/
+ 0xCCF5, /*end :条, len=1*/
+ &Cinfo[ 201 ],
+ &Prop107
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop105 = {
+ 0xCCD8, /*start :特*/
+ 0xCCD8, /*end :特, len=1*/
+ &Cinfo[ 200 ],
+ &Prop106
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop104 = {
+ 0xCBF9, /*start :所*/
+ 0xCBF9, /*end :所, len=1*/
+ &Cinfo[ 199 ],
+ &Prop105
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop103 = {
+ 0xCBD5, /*start :苏*/
+ 0xCBD5, /*end :苏, len=1*/
+ &Cinfo[ 198 ],
+ &Prop104
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop102 = {
+ 0xCBBE, /*start :司*/
+ 0xCBBE, /*end :司, len=1*/
+ &Cinfo[ 197 ],
+ &Prop103
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop101 = {
+ 0xCAFD, /*start :数*/
+ 0xCAFD, /*end :数, len=1*/
+ &Cinfo[ 196 ],
+ &Prop102
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop100 = {
+ 0xCAF5, /*start :术*/
+ 0xCAF5, /*end :术, len=1*/
+ &Cinfo[ 195 ],
+ &Prop101
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop99 = {
+ 0xCAE4, /*start :输*/
+ 0xCAE4, /*end :输, len=1*/
+ &Cinfo[ 194 ],
+ &Prop100
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop98 = {
+ 0xCAD7, /*start :首*/
+ 0xCAD7, /*end :首, len=1*/
+ &Cinfo[ 193 ],
+ &Prop99
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop97 = {
+ 0xCAD4, /*start :试*/
+ 0xCAD4, /*end :试, len=1*/
+ &Cinfo[ 192 ],
+ &Prop98
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop96 = {
+ 0xCAB9, /*start :使*/
+ 0xCAB9, /*end :使, len=1*/
+ &Cinfo[ 191 ],
+ &Prop97
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop95 = {
+ 0xCAB5, /*start :实*/
+ 0xCAB5, /*end :实, len=1*/
+ &Cinfo[ 190 ],
+ &Prop96
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop94 = {
+ 0xCAB1, /*start :时*/
+ 0xCAB1, /*end :时, len=1*/
+ &Cinfo[ 189 ],
+ &Prop95
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop93 = {
+ 0xCAAF, /*start :石*/
+ 0xCAAF, /*end :石, len=1*/
+ &Cinfo[ 188 ],
+ &Prop94
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop92 = {
+ 0xCAA7, /*start :失*/
+ 0xCAA7, /*end :失, len=1*/
+ &Cinfo[ 187 ],
+ &Prop93
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop91 = {
+ 0xC9FA, /*start :生*/
+ 0xC9FA, /*end :生, len=1*/
+ &Cinfo[ 186 ],
+ &Prop92
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop90 = {
+ 0xC9E8, /*start :设*/
+ 0xC9E8, /*end :设, len=1*/
+ &Cinfo[ 185 ],
+ &Prop91
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop89 = {
+ 0xC8EB, /*start :入*/
+ 0xC8EB, /*end :入, len=1*/
+ &Cinfo[ 184 ],
+ &Prop90
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop88 = {
+ 0xC8CF, /*start :认*/
+ 0xC8CF, /*end :认, len=1*/
+ &Cinfo[ 183 ],
+ &Prop89
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop87 = {
+ 0xC8A1, /*start :取*/
+ 0xC8A1, /*end :取, len=1*/
+ &Cinfo[ 182 ],
+ &Prop88
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop86 = {
+ 0xC7FD, /*start :驱*/
+ 0xC7FD, /*end :驱, len=1*/
+ &Cinfo[ 181 ],
+ &Prop87
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop85 = {
+ 0xC7F3, /*start :求*/
+ 0xC7F3, /*end :求, len=1*/
+ &Cinfo[ 180 ],
+ &Prop86
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop84 = {
+ 0xC7EB, /*start :请*/
+ 0xC7EB, /*end :请, len=1*/
+ &Cinfo[ 179 ],
+ &Prop85
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop83 = {
+ 0xC7B0, /*start :前*/
+ 0xC7B0, /*end :前, len=1*/
+ &Cinfo[ 178 ],
+ &Prop84
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop82 = {
+ 0xC6F7, /*start :器*/
+ 0xC6F7, /*end :器, len=1*/
+ &Cinfo[ 177 ],
+ &Prop83
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop81 = {
+ 0xC6F4, /*start :启*/
+ 0xC6F4, /*end :启, len=1*/
+ &Cinfo[ 176 ],
+ &Prop82
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop80 = {
+ 0xC6C2, /*start :坡*/
+ 0xC6C2, /*end :坡, len=1*/
+ &Cinfo[ 175 ],
+ &Prop81
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop79 = {
+ 0xC5E4, /*start :配*/
+ 0xC5E4, /*end :配, len=1*/
+ &Cinfo[ 174 ],
+ &Prop80
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop78 = {
+ 0xC4DC, /*start :能*/
+ 0xC4DC, /*end :能, len=1*/
+ &Cinfo[ 173 ],
+ &Prop79
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop77 = {
+ 0xC4BF, /*start :目*/
+ 0xC4BF, /*end :目, len=1*/
+ &Cinfo[ 172 ],
+ &Prop78
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop76 = {
+ 0xC4AC, /*start :默*/
+ 0xC4AC, /*end :默, len=1*/
+ &Cinfo[ 171 ],
+ &Prop77
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop75 = {
+ 0xC3EB, /*start :秒*/
+ 0xC3EB, /*end :秒, len=1*/
+ &Cinfo[ 170 ],
+ &Prop76
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop74 = {
+ 0xC3E6, /*start :面*/
+ 0xC3E6, /*end :面, len=1*/
+ &Cinfo[ 169 ],
+ &Prop75
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop73 = {
+ 0xC3DC, /*start :密*/
+ 0xC3DC, /*end :密, len=1*/
+ &Cinfo[ 168 ],
+ &Prop74
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop72 = {
+ 0xC3C5, /*start :门*/
+ 0xC3C5, /*end :门, len=1*/
+ &Cinfo[ 167 ],
+ &Prop73
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop71 = {
+ 0xC2FA, /*start :满*/
+ 0xC2FA, /*end :满, len=1*/
+ &Cinfo[ 166 ],
+ &Prop72
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop70 = {
+ 0xC2EB, /*start :码*/
+ 0xC2EB, /*end :码, len=1*/
+ &Cinfo[ 165 ],
+ &Prop71
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop69 = {
+ 0xC1F7, /*start :流*/
+ 0xC1F7, /*end :流, len=1*/
+ &Cinfo[ 164 ],
+ &Prop70
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop68 = {
+ 0xC1BF, /*start :量*/
+ 0xC1BF, /*end :量, len=1*/
+ &Cinfo[ 163 ],
+ &Prop69
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop67 = {
+ 0xC0A8, /*start :括*/
+ 0xC0A8, /*end :括, len=1*/
+ &Cinfo[ 162 ],
+ &Prop68
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop66 = {
+ 0xBFD8, /*start :控*/
+ 0xBFD8, /*end :控, len=1*/
+ &Cinfo[ 161 ],
+ &Prop67
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop65 = {
+ 0xBEDD, /*start :据*/
+ 0xBEDE, /*end :巨, len=2*/
+ &Cinfo[ 159 ],
+ &Prop66
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop64 = {
+ 0xBDF8, /*start :进*/
+ 0xBDF8, /*end :进, len=1*/
+ &Cinfo[ 158 ],
+ &Prop65
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop63 = {
+ 0xBDD7, /*start :阶*/
+ 0xBDD7, /*end :阶, len=1*/
+ &Cinfo[ 157 ],
+ &Prop64
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop62 = {
+ 0xBDAD, /*start :江*/
+ 0xBDAD, /*end :江, len=1*/
+ &Cinfo[ 156 ],
+ &Prop63
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop61 = {
+ 0xBCFE, /*start :件*/
+ 0xBCFE, /*end :件, len=1*/
+ &Cinfo[ 155 ],
+ &Prop62
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop60 = {
+ 0xBCFC, /*start :键*/
+ 0xBCFC, /*end :键, len=1*/
+ &Cinfo[ 154 ],
+ &Prop61
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop59 = {
+ 0xBCEC, /*start :检*/
+ 0xBCEC, /*end :检, len=1*/
+ &Cinfo[ 153 ],
+ &Prop60
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop58 = {
+ 0xBCD3, /*start :加*/
+ 0xBCD3, /*end :加, len=1*/
+ &Cinfo[ 152 ],
+ &Prop59
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop57 = {
+ 0xBCC6, /*start :计*/
+ 0xBCC6, /*end :计, len=1*/
+ &Cinfo[ 151 ],
+ &Prop58
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop56 = {
+ 0xBCBC, /*start :技*/
+ 0xBCBC, /*end :技, len=1*/
+ &Cinfo[ 150 ],
+ &Prop57
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop55 = {
+ 0xBCAD, /*start :辑*/
+ 0xBCAD, /*end :辑, len=1*/
+ &Cinfo[ 149 ],
+ &Prop56
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop54 = {
+ 0xBBF2, /*start :或*/
+ 0xBBF2, /*end :或, len=1*/
+ &Cinfo[ 148 ],
+ &Prop55
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop53 = {
+ 0xBBD8, /*start :回*/
+ 0xBBD8, /*end :回, len=1*/
+ &Cinfo[ 147 ],
+ &Prop54
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop52 = {
+ 0xBBD6, /*start :恢*/
+ 0xBBD6, /*end :恢, len=1*/
+ &Cinfo[ 146 ],
+ &Prop53
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop51 = {
+ 0xBBB6, /*start :欢*/
+ 0xBBB6, /*end :欢, len=1*/
+ &Cinfo[ 145 ],
+ &Prop52
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop50 = {
+ 0xBBA4, /*start :护*/
+ 0xBBA4, /*end :护, len=1*/
+ &Cinfo[ 144 ],
+ &Prop51
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop49 = {
+ 0xBAF3, /*start :后*/
+ 0xBAF3, /*end :后, len=1*/
+ &Cinfo[ 143 ],
+ &Prop50
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop48 = {
+ 0xBAC5, /*start :号*/
+ 0xBAC5, /*end :号, len=1*/
+ &Cinfo[ 142 ],
+ &Prop49
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop47 = {
+ 0xB9E6, /*start :规*/
+ 0xB9E6, /*end :规, len=1*/
+ &Cinfo[ 141 ],
+ &Prop48
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop46 = {
+ 0xB9CA, /*start :故*/
+ 0xB9CA, /*end :故, len=1*/
+ &Cinfo[ 140 ],
+ &Prop47
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop45 = {
+ 0xB9AB, /*start :公*/
+ 0xB9AB, /*end :公, len=1*/
+ &Cinfo[ 139 ],
+ &Prop46
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop44 = {
+ 0xB9A6, /*start :功*/
+ 0xB9A6, /*end :功, len=1*/
+ &Cinfo[ 138 ],
+ &Prop45
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop43 = {
+ 0xB8F1, /*start :格*/
+ 0xB8F1, /*end :格, len=1*/
+ &Cinfo[ 137 ],
+ &Prop44
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop42 = {
+ 0xB8C4, /*start :改*/
+ 0xB8C4, /*end :改, len=1*/
+ &Cinfo[ 136 ],
+ &Prop43
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop41 = {
+ 0xB8B4, /*start :复*/
+ 0xB8B4, /*end :复, len=1*/
+ &Cinfo[ 135 ],
+ &Prop42
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop40 = {
+ 0xB7B5, /*start :返*/
+ 0xB7B5, /*end :返, len=1*/
+ &Cinfo[ 134 ],
+ &Prop41
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop39 = {
+ 0xB7A7, /*start :阀*/
+ 0xB7A7, /*end :阀, len=1*/
+ &Cinfo[ 133 ],
+ &Prop40
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop38 = {
+ 0xB7A2, /*start :发*/
+ 0xB7A2, /*end :发, len=1*/
+ &Cinfo[ 132 ],
+ &Prop39
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop37 = {
+ 0xB6D4, /*start :对*/
+ 0xB6D4, /*end :对, len=1*/
+ &Cinfo[ 131 ],
+ &Prop38
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop36 = {
+ 0xB6CF, /*start :断*/
+ 0xB6CF, /*end :断, len=1*/
+ &Cinfo[ 130 ],
+ &Prop37
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop35 = {
+ 0xB6C8, /*start :度*/
+ 0xB6C8, /*end :度, len=1*/
+ &Cinfo[ 129 ],
+ &Prop36
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop34 = {
+ 0xB6AF, /*start :动*/
+ 0xB6AF, /*end :动, len=1*/
+ &Cinfo[ 128 ],
+ &Prop35
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop33 = {
+ 0xB6A8, /*start :定*/
+ 0xB6A8, /*end :定, len=1*/
+ &Cinfo[ 127 ],
+ &Prop34
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop32 = {
+ 0xB5E7, /*start :电*/
+ 0xB5E7, /*end :电, len=1*/
+ &Cinfo[ 126 ],
+ &Prop33
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop31 = {
+ 0xB5C4, /*start :的*/
+ 0xB5C4, /*end :的, len=1*/
+ &Cinfo[ 125 ],
+ &Prop32
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop30 = {
+ 0xB5B1, /*start :当*/
+ 0xB5B1, /*end :当, len=1*/
+ &Cinfo[ 124 ],
+ &Prop31
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop29 = {
+ 0xB5AB, /*start :但*/
+ 0xB5AB, /*end :但, len=1*/
+ &Cinfo[ 123 ],
+ &Prop30
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop28 = {
+ 0xB5A5, /*start :单*/
+ 0xB5A5, /*end :单, len=1*/
+ &Cinfo[ 122 ],
+ &Prop29
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop27 = {
+ 0xB4ED, /*start :错*/
+ 0xB4ED, /*end :错, len=1*/
+ &Cinfo[ 121 ],
+ &Prop28
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop26 = {
+ 0xB4E6, /*start :存*/
+ 0xB4E6, /*end :存, len=1*/
+ &Cinfo[ 120 ],
+ &Prop27
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop25 = {
+ 0xB3F6, /*start :出*/
+ 0xB3F6, /*end :出, len=1*/
+ &Cinfo[ 119 ],
+ &Prop26
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop24 = {
+ 0xB3CC, /*start :程*/
+ 0xB3CC, /*end :程, len=1*/
+ &Cinfo[ 118 ],
+ &Prop25
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop23 = {
+ 0xB3C9, /*start :成*/
+ 0xB3C9, /*end :成, len=1*/
+ &Cinfo[ 117 ],
+ &Prop24
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop22 = {
+ 0xB3AC, /*start :超*/
+ 0xB3AC, /*end :超, len=1*/
+ &Cinfo[ 116 ],
+ &Prop23
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop21 = {
+ 0xB3A7, /*start :厂*/
+ 0xB3A7, /*end :厂, len=1*/
+ &Cinfo[ 115 ],
+ &Prop22
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop20 = {
+ 0xB3A3, /*start :常*/
+ 0xB3A3, /*end :常, len=1*/
+ &Cinfo[ 114 ],
+ &Prop21
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop19 = {
+ 0xB2E9, /*start :查*/
+ 0xB2E9, /*end :查, len=1*/
+ &Cinfo[ 113 ],
+ &Prop20
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop18 = {
+ 0xB2E2, /*start :测*/
+ 0xB2E2, /*end :测, len=1*/
+ &Cinfo[ 112 ],
+ &Prop19
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop17 = {
+ 0xB2CE, /*start :参*/
+ 0xB2CE, /*end :参, len=1*/
+ &Cinfo[ 111 ],
+ &Prop18
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop16 = {
+ 0xB2CB, /*start :菜*/
+ 0xB2CB, /*end :菜, len=1*/
+ &Cinfo[ 110 ],
+ &Prop17
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop15 = {
+ 0xB2BB, /*start :不*/
+ 0xB2BB, /*end :不, len=1*/
+ &Cinfo[ 109 ],
+ &Prop16
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop14 = {
+ 0xB1E4, /*start :变*/
+ 0xB1E4, /*end :变, len=1*/
+ &Cinfo[ 108 ],
+ &Prop15
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop13 = {
+ 0xB1E0, /*start :编*/
+ 0xB1E0, /*end :编, len=1*/
+ &Cinfo[ 107 ],
+ &Prop14
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop12 = {
+ 0xB1BE, /*start :本*/
+ 0xB1BE, /*end :本, len=1*/
+ &Cinfo[ 106 ],
+ &Prop13
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop11 = {
+ 0xB1B8, /*start :备*/
+ 0xB1B8, /*end :备, len=1*/
+ &Cinfo[ 105 ],
+ &Prop12
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop10 = {
+ 0xB1A3, /*start :保*/
+ 0xB1A3, /*end :保, len=1*/
+ &Cinfo[ 104 ],
+ &Prop11
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop9 = {
+ 0xB0FC, /*start :包*/
+ 0xB0FC, /*end :包, len=1*/
+ &Cinfo[ 103 ],
+ &Prop10
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop8 = {
+ 0xB0E6, /*start :版*/
+ 0xB0E6, /*end :版, len=1*/
+ &Cinfo[ 102 ],
+ &Prop9
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop7 = {
+ 0xB0DC, /*start :败*/
+ 0xB0DC, /*end :败, len=1*/
+ &Cinfo[ 101 ],
+ &Prop8
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop6 = {
+ 0xA848, /*start :℉*/
+ 0xA848, /*end :℉, len=1*/
+ &Cinfo[ 100 ],
+ &Prop7
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop5 = {
+ 0xA3AC, /*start :,*/
+ 0xA3AC, /*end :,, len=1*/
+ &Cinfo[ 99 ],
+ &Prop6
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop4 = {
+ 0xA1E6, /*start :℃*/
+ 0xA1E6, /*end :℃, len=1*/
+ &Cinfo[ 98 ],
+ &Prop5
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop3 = {
+ 0xA1E3, /*start :°*/
+ 0xA1E3, /*end :°, len=1*/
+ &Cinfo[ 97 ],
+ &Prop4
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop2 = {
+ 0xA1A3, /*start :。*/
+ 0xA1A3, /*end :。, len=1*/
+ &Cinfo[ 96 ],
+ &Prop3
+};
+
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop1 = {
+ 0x0020, /*start : */
+ 0x007F, /*end :, len=96*/
+ &Cinfo[ 0 ],
+ &Prop2
+};
+
+
+GUI_CONST_STORAGE GUI_FONT GUI_FontHZ24x24 = {
+ GUI_FONTTYPE_PROP_SJIS,
+ 24, /* height of font */
+ 24, /* space of font y */
+ 1,
+ 1,
+ &Prop1
+};
+
diff --git a/User/lib/lcd/font/HZ32x32.c b/User/lib/lcd/font/HZ32x32.c
new file mode 100644
index 0000000..92a4e2e
--- /dev/null
+++ b/User/lib/lcd/font/HZ32x32.c
@@ -0,0 +1,3765 @@
+/*
+**********************************************************************
+* UcGUI Font
+* Chinese GB2312 library
+* (c) Copyright 19xx-20xx, company name
+*
+*
+* 注:本字体文件由 ucGUI字体生成器v9.0 生成,作者:馋嘴猫(qq:602426967)
+* 字体:宋体,字形:粗体,大小:26,宽:32,高:32,水平偏移:0,垂直偏移:0
+*
+**********************************************************************
+*/
+
+#include "GUI.H"
+
+/* char: code:0x0020 */
+static GUI_CONST_STORAGE unsigned char ac0020[96] = {
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________};
+
+/* char: ! code:0x0021 */
+static GUI_CONST_STORAGE unsigned char ac0021[96] = {
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, XXXX____, ________,
+ _______X, XXXX____, ________,
+ _______X, XXXX____, ________,
+ _______X, XXXX____, ________,
+ _______X, XXXX____, ________,
+ _______X, XXXX____, ________,
+ ________, XXXX____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, XXX_____, ________,
+ _______X, XXXX____, ________,
+ _______X, XXXX____, ________,
+ ________, XXX_____, ________,
+ ________, ________, ________,
+ ________, ________, ________};
+
+/* char: " code:0x0022 */
+static GUI_CONST_STORAGE unsigned char ac0022[96] = {
+ ________, ________, ________,
+ ________, ________, ________,
+ ______XX, XX_XXXX_, ________,
+ ______XX, XX_XXXX_, ________,
+ _____XXX, XXXXXXX_, ________,
+ ____XXXX, _XXXX___, ________,
+ ____XXX_, _XXX____, ________,
+ ___XXX__, XXX_____, ________,
+ ___XX___, XX______, ________,
+ __XX___X, X_______, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________};
+
+/* char: # code:0x0023 */
+static GUI_CONST_STORAGE unsigned char ac0023[96] = {
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ _____XX_, _____XX_, ________,
+ _____XX_, _____XX_, ________,
+ _____XX_, _____XX_, ________,
+ _____XX_, _____XX_, ________,
+ _____XX_, _____XX_, ________,
+ _XXXXXXX, XXXXXXXX, XX______,
+ _XXXXXXX, XXXXXXXX, XX______,
+ _XXXXXXX, XXXXXXXX, XX______,
+ ____XXX_, ____XXX_, ________,
+ ____XX__, ____XX__, ________,
+ ____XX__, ____XX__, ________,
+ ____XX__, ____XX__, ________,
+ ____XX__, ____XX__, ________,
+ ____XX__, ____XX__, ________,
+ ____XX__, ____XX__, ________,
+ _XXXXXXX, XXXXXXXX, XX______,
+ _XXXXXXX, XXXXXXXX, XX______,
+ _XXXXXXX, XXXXXXXX, XX______,
+ ___XXX__, ___XXX__, ________,
+ ___XXX__, ___XXX__, ________,
+ ___XX___, ___XXX__, ________,
+ ___XX___, ___XX___, ________,
+ ___XX___, ___XX___, ________,
+ ___XX___, ___XX___, ________,
+ ________, ________, ________,
+ ________, ________, ________};
+
+/* char: $ code:0x0024 */
+static GUI_CONST_STORAGE unsigned char ac0024[96] = {
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, XX______, ________,
+ ________, XX______, ________,
+ ______XX, XXXXX___, ________,
+ _____XXX, XX__XX__, ________,
+ ____XXX_, XX___XX_, ________,
+ ___XXX__, XX___XXX, ________,
+ ___XXX__, XX___XXX, ________,
+ ___XXX__, XX__XXXX, ________,
+ ___XXX__, XX__XXXX, ________,
+ ___XXXX_, XX______, ________,
+ ____XXXX, XX______, ________,
+ _____XXX, XX______, ________,
+ ______XX, XXX_____, ________,
+ _______X, XXXX____, ________,
+ ________, XXXXX___, ________,
+ ________, XXXXXX__, ________,
+ ________, XX_XXXX_, ________,
+ ________, XX__XXXX, ________,
+ ________, XX__XXXX, ________,
+ __XXXX__, XX___XXX, ________,
+ __XXXX__, XX___XXX, ________,
+ __XXXX__, XX___XXX, ________,
+ __XXX___, XX___XX_, ________,
+ ___XX___, XX__XXX_, ________,
+ ____XX__, XX_XXX__, ________,
+ _____XXX, XXXX____, ________,
+ ________, XX______, ________,
+ ________, XX______, ________};
+
+/* char: % code:0x0025 */
+static GUI_CONST_STORAGE unsigned char ac0025[96] = {
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ __XXXX__, _____XX_, ________,
+ _XXXXXX_, ____XXX_, ________,
+ _XX__XX_, ____XX__, ________,
+ XXX__XXX, ____XX__, ________,
+ XXX__XXX, ___XX___, ________,
+ XXX__XXX, ___XX___, ________,
+ XXX__XXX, __XX____, ________,
+ XXX__XXX, __XX____, ________,
+ XXX__XXX, _XXX____, ________,
+ XXX__XXX, _XX_____, ________,
+ _XX__XX_, _XX_____, ________,
+ _XXXXXX_, XX__XXXX, ________,
+ __XXXX__, XX_XXXXX, X_______,
+ _______X, X__XX__X, X_______,
+ _______X, X_XXX__X, XX______,
+ ______XX, X_XXX__X, XX______,
+ ______XX, __XXX__X, XX______,
+ ______XX, __XXX__X, XX______,
+ _____XX_, __XXX__X, XX______,
+ _____XX_, __XXX__X, XX______,
+ ____XX__, __XXX__X, XX______,
+ ____XX__, ___XX__X, X_______,
+ ___XX___, ___XXXXX, X_______,
+ ___XX___, ____XXXX, ________,
+ ________, ________, ________,
+ ________, ________, ________};
+
+/* char: & code:0x0026 */
+static GUI_CONST_STORAGE unsigned char ac0026[96] = {
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ _____XXX, XX______, ________,
+ ____XXX_, XX______, ________,
+ ___XXX__, XXX_____, ________,
+ ___XXX__, XXX_____, ________,
+ ___XXX__, XXX_____, ________,
+ ___XXX__, XXX_____, ________,
+ ___XXX__, XXX_____, ________,
+ ___XXX__, XX______, ________,
+ ___XXXXX, XX______, ________,
+ ____XXXX, X_______, ________,
+ ____XXXX, __XXXXXX, ________,
+ ___XXXXX, ___XXX__, ________,
+ __XXXXXX, ____XX__, ________,
+ _XXX_XXX, ____XX__, ________,
+ _XX__XXX, X___XX__, ________,
+ XXX___XX, X__XXX__, ________,
+ XXX___XX, XX_XX___, ________,
+ XXX____X, XX_XX___, ________,
+ XXX____X, XXXXX___, ________,
+ XXX_____, XXXX____, ________,
+ _XXX____, _XXXX___, XX______,
+ _XXX____, _XXXXX_X, XX______,
+ __XXX___, XX_XXXXX, X_______,
+ ___XXXXX, X___XXXX, ________,
+ ________, ________, ________,
+ ________, ________, ________};
+
+/* char: ' code:0x0027 */
+static GUI_CONST_STORAGE unsigned char ac0027[96] = {
+ ________, ________, ________,
+ ________, ________, ________,
+ ___XXX__, ________, ________,
+ __XXXXX_, ________, ________,
+ __XXXXX_, ________, ________,
+ ___XXXX_, ________, ________,
+ ____XXX_, ________, ________,
+ ____XX__, ________, ________,
+ ___XXX__, ________, ________,
+ __XXX___, ________, ________,
+ _XXX____, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________};
+
+/* char: ( code:0x0028 */
+static GUI_CONST_STORAGE unsigned char ac0028[96] = {
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, _______X, X_______,
+ ________, ______XX, ________,
+ ________, _____XX_, ________,
+ ________, ____XXX_, ________,
+ ________, ____XX__, ________,
+ ________, ___XXX__, ________,
+ ________, __XXX___, ________,
+ ________, __XXX___, ________,
+ ________, _XXX____, ________,
+ ________, _XXX____, ________,
+ ________, _XXX____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, _XXX____, ________,
+ ________, _XXX____, ________,
+ ________, _XXX____, ________,
+ ________, __XXX___, ________,
+ ________, __XXX___, ________,
+ ________, ___XXX__, ________,
+ ________, ___XXX__, ________,
+ ________, ____XXX_, ________,
+ ________, _____XX_, ________,
+ ________, ______XX, ________};
+
+/* char: ) code:0x0029 */
+static GUI_CONST_STORAGE unsigned char ac0029[96] = {
+ ________, ________, ________,
+ ________, ________, ________,
+ __XX____, ________, ________,
+ ___XX___, ________, ________,
+ ____XX__, ________, ________,
+ ____XXX_, ________, ________,
+ _____XX_, ________, ________,
+ _____XXX, ________, ________,
+ ______XX, X_______, ________,
+ ______XX, X_______, ________,
+ _______X, XX______, ________,
+ _______X, XX______, ________,
+ _______X, XX______, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ _______X, XX______, ________,
+ _______X, XX______, ________,
+ _______X, XX______, ________,
+ ______XX, X_______, ________,
+ ______XX, X_______, ________,
+ _____XXX, ________, ________,
+ _____XXX, ________, ________,
+ ____XXX_, ________, ________,
+ ____XX__, ________, ________,
+ ___XX___, ________, ________};
+
+/* char: * code:0x002A */
+static GUI_CONST_STORAGE unsigned char ac002A[96] = {
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, XXX_____, ________,
+ _______X, XXX_____, ________,
+ _______X, XXX_____, ________,
+ _______X, XXX_____, ________,
+ _XXXX___, XX___XXX, X_______,
+ _XXXXX__, XX__XXXX, X_______,
+ __XXXXX_, XX_XXXXX, ________,
+ ____XXXX, XXXXXX__, ________,
+ _______X, XXX_____, ________,
+ _______X, XXX_____, ________,
+ ____XXXX, XXXXXX__, ________,
+ __XXXXX_, XX_XXXXX, ________,
+ _XXXXX__, XX__XXXX, X_______,
+ _XXXX___, XX___XXX, X_______,
+ _______X, XXX_____, ________,
+ _______X, XXX_____, ________,
+ _______X, XXX_____, ________,
+ _______X, XXX_____, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________};
+
+/* char: + code:0x002B */
+static GUI_CONST_STORAGE unsigned char ac002B[96] = {
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, _XX_____, ________,
+ ________, _XX_____, ________,
+ ________, _XX_____, ________,
+ ________, _XX_____, ________,
+ ________, _XX_____, ________,
+ ________, _XX_____, ________,
+ ________, _XX_____, ________,
+ ________, _XX_____, ________,
+ __XXXXXX, XXXXXXXX, XX______,
+ ________, _XX_____, ________,
+ ________, _XX_____, ________,
+ ________, _XX_____, ________,
+ ________, _XX_____, ________,
+ ________, _XX_____, ________,
+ ________, _XX_____, ________,
+ ________, _XX_____, ________,
+ ________, _XX_____, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________};
+
+/* char: , code:0x002C */
+static GUI_CONST_STORAGE unsigned char ac002C[96] = {
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ___XXX__, ________, ________,
+ __XXXXX_, ________, ________,
+ __XXXXX_, ________, ________,
+ ___XXXX_, ________, ________,
+ ____XXX_, ________, ________,
+ ____XX__, ________, ________,
+ ___XXX__, ________, ________};
+
+/* char: - code:0x002D */
+static GUI_CONST_STORAGE unsigned char ac002D[96] = {
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ _XXXXXXX, XXXXXXXX, X_______,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________};
+
+/* char: . code:0x002E */
+static GUI_CONST_STORAGE unsigned char ac002E[96] = {
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ___XXX__, ________, ________,
+ __XXXXX_, ________, ________,
+ __XXXXX_, ________, ________,
+ ___XXX__, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________};
+
+/* char: / code:0x002F */
+static GUI_CONST_STORAGE unsigned char ac002F[96] = {
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, XX______,
+ ________, _______X, XX______,
+ ________, _______X, X_______,
+ ________, ______XX, ________,
+ ________, ______XX, ________,
+ ________, _____XX_, ________,
+ ________, _____XX_, ________,
+ ________, ____XX__, ________,
+ ________, ____XX__, ________,
+ ________, ___XX___, ________,
+ ________, ___XX___, ________,
+ ________, __XX____, ________,
+ ________, __XX____, ________,
+ ________, _XX_____, ________,
+ ________, _XX_____, ________,
+ ________, XX______, ________,
+ ________, XX______, ________,
+ _______X, X_______, ________,
+ _______X, X_______, ________,
+ ______XX, ________, ________,
+ ______XX, ________, ________,
+ _____XX_, ________, ________,
+ _____XX_, ________, ________,
+ ____XX__, ________, ________,
+ ____XX__, ________, ________,
+ ___XX___, ________, ________,
+ ___XX___, ________, ________,
+ __XX____, ________, ________,
+ _XXX____, ________, ________};
+
+/* char: 0 code:0x0030 */
+static GUI_CONST_STORAGE unsigned char ac0030[96] = {
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ _______X, XXXX____, ________,
+ _____XXX, ___XXX__, ________,
+ ____XXX_, ____XXX_, ________,
+ ____XXX_, _____XX_, ________,
+ ___XXX__, _____XXX, ________,
+ ___XXX__, _____XXX, ________,
+ ___XXX__, ______XX, ________,
+ __XXX___, ______XX, X_______,
+ __XXX___, ______XX, X_______,
+ __XXX___, ______XX, X_______,
+ __XXX___, ______XX, X_______,
+ __XXX___, ______XX, X_______,
+ __XXX___, ______XX, X_______,
+ __XXX___, ______XX, X_______,
+ __XXX___, ______XX, X_______,
+ __XXX___, ______XX, X_______,
+ __XXX___, ______XX, X_______,
+ ___XXX__, ______XX, ________,
+ ___XXX__, _____XXX, ________,
+ ___XXX__, _____XXX, ________,
+ ____XXX_, _____XX_, ________,
+ _____XX_, ____XXX_, ________,
+ _____XXX, ___XXX__, ________,
+ _______X, XXXX____, ________,
+ ________, ________, ________,
+ ________, ________, ________};
+
+/* char: 1 code:0x0031 */
+static GUI_CONST_STORAGE unsigned char ac0031[96] = {
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, _XX_____, ________,
+ ________, XXX_____, ________,
+ ____XXXX, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ _______X, XXXX____, ________,
+ ____XXXX, XXXXXXX_, ________,
+ ________, ________, ________,
+ ________, ________, ________};
+
+/* char: 2 code:0x0032 */
+static GUI_CONST_STORAGE unsigned char ac0032[96] = {
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ______XX, XXXXX___, ________,
+ ____XXX_, ___XXXX_, ________,
+ ___XXX__, _____XXX, ________,
+ __XXX___, ______XX, X_______,
+ __XXX___, ______XX, X_______,
+ __XXXX__, ______XX, X_______,
+ __XXXX__, ______XX, X_______,
+ __XXXX__, ______XX, X_______,
+ ________, _____XXX, ________,
+ ________, _____XXX, ________,
+ ________, ____XXX_, ________,
+ ________, ____XXX_, ________,
+ ________, ___XX___, ________,
+ ________, __XX____, ________,
+ ________, _XX_____, ________,
+ ________, XX______, ________,
+ _______X, X_______, ________,
+ ______XX, ________, ________,
+ _____XX_, _______X, X_______,
+ ____XX__, _______X, X_______,
+ ___XX___, ______XX, X_______,
+ __XXX___, _____XXX, X_______,
+ __XXXXXX, XXXXXXXX, ________,
+ __XXXXXX, XXXXXXXX, ________,
+ ________, ________, ________,
+ ________, ________, ________};
+
+/* char: 3 code:0x0033 */
+static GUI_CONST_STORAGE unsigned char ac0033[96] = {
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ _____XXX, XXXX____, ________,
+ ____XX__, __XXXX__, ________,
+ ___XX___, ____XXX_, ________,
+ __XX____, ____XXXX, ________,
+ __XXX___, _____XXX, ________,
+ __XXX___, _____XXX, ________,
+ __XXX___, _____XXX, ________,
+ ________, _____XXX, ________,
+ ________, ____XXX_, ________,
+ ________, ____XXX_, ________,
+ ________, __XXX___, ________,
+ _______X, XXXX____, ________,
+ ________, ___XXX__, ________,
+ ________, _____XX_, ________,
+ ________, _____XXX, ________,
+ ________, ______XX, X_______,
+ ________, ______XX, X_______,
+ ___XXX__, ______XX, X_______,
+ __XXXX__, ______XX, X_______,
+ __XXXX__, ______XX, X_______,
+ __XXXX__, _____XXX, ________,
+ ___XXX__, _____XXX, ________,
+ ____XXX_, ___XXX__, ________,
+ ______XX, XXXXX___, ________,
+ ________, ________, ________,
+ ________, ________, ________};
+
+/* char: 4 code:0x0034 */
+static GUI_CONST_STORAGE unsigned char ac0034[96] = {
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ___XXX__, ________,
+ ________, ___XXX__, ________,
+ ________, __XXXX__, ________,
+ ________, _XXXXX__, ________,
+ ________, _XXXXX__, ________,
+ ________, XX_XXX__, ________,
+ _______X, XX_XXX__, ________,
+ _______X, X__XXX__, ________,
+ ______XX, ___XXX__, ________,
+ _____XXX, ___XXX__, ________,
+ _____XX_, ___XXX__, ________,
+ ____XX__, ___XXX__, ________,
+ ___XXX__, ___XXX__, ________,
+ ___XX___, ___XXX__, ________,
+ __XX____, ___XXX__, ________,
+ _XXX____, ___XXX__, ________,
+ _XXXXXXX, XXXXXXXX, XX______,
+ ________, ___XXX__, ________,
+ ________, ___XXX__, ________,
+ ________, ___XXX__, ________,
+ ________, ___XXX__, ________,
+ ________, ___XXX__, ________,
+ ________, ___XXX__, ________,
+ _______X, XXXXXXXX, X_______,
+ ________, ________, ________,
+ ________, ________, ________};
+
+/* char: 5 code:0x0035 */
+static GUI_CONST_STORAGE unsigned char ac0035[96] = {
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ____XXXX, XXXXXXXX, X_______,
+ ____XXXX, XXXXXXXX, X_______,
+ ____XX__, ________, ________,
+ ____XX__, ________, ________,
+ ___XXX__, ________, ________,
+ ___XX___, ________, ________,
+ ___XX___, ________, ________,
+ ___XX___, ________, ________,
+ ___XX___, ________, ________,
+ ___XX_XX, XXXXX___, ________,
+ ___XXXXX, ____XXX_, ________,
+ ___XXX__, _____XXX, ________,
+ ___XXX__, _____XXX, ________,
+ ________, ______XX, X_______,
+ ________, ______XX, X_______,
+ ________, ______XX, X_______,
+ ________, ______XX, X_______,
+ ___XXX__, ______XX, X_______,
+ __XXXX__, ______XX, X_______,
+ __XXXX__, ______XX, X_______,
+ __XXX___, _____XXX, ________,
+ ___XX___, ____XXX_, ________,
+ ____XXX_, ___XXXX_, ________,
+ ______XX, XXXXX___, ________,
+ ________, ________, ________,
+ ________, ________, ________};
+
+/* char: 6 code:0x0036 */
+static GUI_CONST_STORAGE unsigned char ac0036[96] = {
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, XXXXXX__, ________,
+ ______XX, X____XX_, ________,
+ _____XXX, _____XXX, ________,
+ ____XXX_, _____XXX, ________,
+ ____XX__, _____XXX, ________,
+ ___XXX__, ________, ________,
+ ___XX___, ________, ________,
+ ___XX___, ________, ________,
+ __XXX___, ________, ________,
+ __XXX__X, XXXXX___, ________,
+ __XXXXXX, ____XXX_, ________,
+ __XXXXX_, _____XXX, ________,
+ __XXXX__, _____XXX, ________,
+ __XXX___, ______XX, X_______,
+ __XXX___, ______XX, X_______,
+ __XXX___, ______XX, X_______,
+ __XXX___, ______XX, X_______,
+ __XXX___, ______XX, X_______,
+ ___XXX__, ______XX, X_______,
+ ___XXX__, ______XX, X_______,
+ ___XXX__, _____XXX, ________,
+ ____XXX_, _____XXX, ________,
+ _____XXX, ____XXX_, ________,
+ _______X, XXXXX___, ________,
+ ________, ________, ________,
+ ________, ________, ________};
+
+/* char: 7 code:0x0037 */
+static GUI_CONST_STORAGE unsigned char ac0037[96] = {
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ___XXXXX, XXXXXXXX, X_______,
+ ___XXXXX, XXXXXXXX, X_______,
+ ___XXX__, ______XX, ________,
+ __XXX___, _____XX_, ________,
+ __XX____, _____XX_, ________,
+ __XX____, ____XX__, ________,
+ ________, ___XXX__, ________,
+ ________, ___XX___, ________,
+ ________, __XXX___, ________,
+ ________, __XX____, ________,
+ ________, _XXX____, ________,
+ ________, _XX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XX______, ________,
+ _______X, XX______, ________,
+ _______X, XX______, ________,
+ _______X, XX______, ________,
+ ______XX, XX______, ________,
+ ______XX, XX______, ________,
+ ______XX, XX______, ________,
+ ______XX, XX______, ________,
+ ______XX, XX______, ________,
+ ______XX, XX______, ________,
+ ________, ________, ________,
+ ________, ________, ________};
+
+/* char: 8 code:0x0038 */
+static GUI_CONST_STORAGE unsigned char ac0038[96] = {
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ _______X, XXXXX___, ________,
+ _____XXX, ____XXX_, ________,
+ ____XXX_, _____XXX, ________,
+ ___XXX__, ______XX, X_______,
+ ___XXX__, ______XX, X_______,
+ ___XXX__, ______XX, X_______,
+ ___XXX__, ______XX, X_______,
+ ___XXXX_, ______XX, X_______,
+ ____XXXX, _____XXX, ________,
+ ____XXXX, X____XX_, ________,
+ _____XXX, XXXXXX__, ________,
+ ______XX, XXXXX___, ________,
+ _____XXX, _XXXXX__, ________,
+ ____XXX_, ___XXXX_, ________,
+ ___XXX__, ____XXXX, ________,
+ __XXX___, _____XXX, X_______,
+ __XXX___, ______XX, X_______,
+ __XXX___, ______XX, X_______,
+ __XXX___, ______XX, X_______,
+ __XXX___, ______XX, X_______,
+ ___XXX__, ______XX, ________,
+ ___XXX__, _____XXX, ________,
+ ____XXXX, ____XXX_, ________,
+ ______XX, XXXXX___, ________,
+ ________, ________, ________,
+ ________, ________, ________};
+
+/* char: 9 code:0x0039 */
+static GUI_CONST_STORAGE unsigned char ac0039[96] = {
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ______XX, XXXX____, ________,
+ ____XXXX, ___XXX__, ________,
+ ____XX__, ____XXX_, ________,
+ ___XXX__, _____XXX, ________,
+ ___XX___, _____XXX, ________,
+ __XXX___, ______XX, ________,
+ __XXX___, ______XX, X_______,
+ __XXX___, ______XX, X_______,
+ __XXX___, ______XX, X_______,
+ __XXX___, ______XX, X_______,
+ __XXX___, _____XXX, X_______,
+ ___XXX__, _____XXX, X_______,
+ ___XXX__, ____XXXX, X_______,
+ ____XXXX, ___XX_XX, X_______,
+ ______XX, XXXX__XX, X_______,
+ ________, ______XX, X_______,
+ ________, _____XXX, ________,
+ ________, _____XXX, ________,
+ ________, _____XXX, ________,
+ ___XXX__, ____XXX_, ________,
+ ___XXX__, ____XXX_, ________,
+ ___XXX__, ___XXX__, ________,
+ ____XX__, _XXXX___, ________,
+ _____XXX, XXX_____, ________,
+ ________, ________, ________,
+ ________, ________, ________};
+
+/* char: : code:0x003A */
+static GUI_CONST_STORAGE unsigned char ac003A[96] = {
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, XXX_____, ________,
+ _______X, XXXX____, ________,
+ _______X, XXXX____, ________,
+ ________, XXX_____, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, XXX_____, ________,
+ _______X, XXXX____, ________,
+ _______X, XXXX____, ________,
+ ________, XXX_____, ________,
+ ________, ________, ________,
+ ________, ________, ________};
+
+/* char: ; code:0x003B */
+static GUI_CONST_STORAGE unsigned char ac003B[96] = {
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ _______X, XXX_____, ________,
+ _______X, XXX_____, ________,
+ _______X, XXX_____, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ _______X, XXX_____, ________,
+ _______X, XXX_____, ________,
+ _______X, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XX______, ________};
+
+/* char: < code:0x003C */
+static GUI_CONST_STORAGE unsigned char ac003C[96] = {
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ______XX, ________,
+ ________, _____XX_, ________,
+ ________, ____XX__, ________,
+ ________, ___XX___, ________,
+ ________, __XX____, ________,
+ ________, _XX_____, ________,
+ ________, XX______, ________,
+ _______X, X_______, ________,
+ ______XX, ________, ________,
+ _____XX_, ________, ________,
+ ____XX__, ________, ________,
+ ___XX___, ________, ________,
+ ___XX___, ________, ________,
+ ____XX__, ________, ________,
+ _____XX_, ________, ________,
+ ______XX, ________, ________,
+ _______X, X_______, ________,
+ ________, XX______, ________,
+ ________, _XX_____, ________,
+ ________, __XX____, ________,
+ ________, ___XX___, ________,
+ ________, ____XX__, ________,
+ ________, _____XX_, ________,
+ ________, ______XX, ________,
+ ________, ________, ________,
+ ________, ________, ________};
+
+/* char: = code:0x003D */
+static GUI_CONST_STORAGE unsigned char ac003D[96] = {
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ _XXXXXXX, XXXXXXXX, X_______,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ _XXXXXXX, XXXXXXXX, X_______,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________};
+
+/* char: > code:0x003E */
+static GUI_CONST_STORAGE unsigned char ac003E[96] = {
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ __XX____, ________, ________,
+ ___XX___, ________, ________,
+ ____XX__, ________, ________,
+ _____XX_, ________, ________,
+ ______XX, ________, ________,
+ _______X, X_______, ________,
+ ________, XX______, ________,
+ ________, _XX_____, ________,
+ ________, __XX____, ________,
+ ________, ___XX___, ________,
+ ________, ____XX__, ________,
+ ________, _____XX_, ________,
+ ________, _____XX_, ________,
+ ________, ____XX__, ________,
+ ________, ___XX___, ________,
+ ________, __XX____, ________,
+ ________, _XX_____, ________,
+ ________, XX______, ________,
+ _______X, X_______, ________,
+ ______XX, ________, ________,
+ _____XX_, ________, ________,
+ ____XX__, ________, ________,
+ ___XX___, ________, ________,
+ __XX____, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________};
+
+/* char: ? code:0x003F */
+static GUI_CONST_STORAGE unsigned char ac003F[96] = {
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ______XX, XXXXX___, ________,
+ _____XXX, ____XXX_, ________,
+ ____XX__, _____XXX, ________,
+ ___XX___, ______XX, ________,
+ __XXX___, ______XX, X_______,
+ __XXX___, ______XX, X_______,
+ __XXXX__, ______XX, X_______,
+ __XXXX__, ______XX, X_______,
+ ___XXX__, _____XXX, X_______,
+ ________, _____XXX, ________,
+ ________, ___XXXXX, ________,
+ ________, __XXXX__, ________,
+ ________, _XXX____, ________,
+ ________, XXX_____, ________,
+ ________, XX______, ________,
+ ________, XX______, ________,
+ ________, XX______, ________,
+ ________, XX______, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, XXX_____, ________,
+ _______X, XXXX____, ________,
+ _______X, XXXX____, ________,
+ ________, XXX_____, ________,
+ ________, ________, ________,
+ ________, ________, ________};
+
+/* char: @ code:0x0040 */
+static GUI_CONST_STORAGE unsigned char ac0040[96] = {
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ _______X, XXXXX___, ________,
+ _____XXX, X___XXX_, ________,
+ ____XXX_, ______XX, ________,
+ ___XXX__, _______X, X_______,
+ ___XX___, _XXXXXXX, X_______,
+ __XXX___, XXX_XXX_, XX______,
+ __XXX__X, XX__XXX_, XX______,
+ __XX___X, XX__XXX_, XX______,
+ _XXX__XX, X___XX__, XX______,
+ _XXX__XX, X___XX__, XX______,
+ _XXX_XXX, ___XXX__, XX______,
+ _XXX_XXX, ___XXX__, XX______,
+ _XXX_XXX, ___XXX__, XX______,
+ _XXX_XXX, ___XXX__, XX______,
+ _XXX_XXX, ___XXX_X, X_______,
+ _XXX_XXX, __XXX__X, X_______,
+ _XXX__XX, _XXXX_XX, ________,
+ __XXX_XX, XX__XXX_, ________,
+ __XXX___, ________, XX______,
+ ___XX___, _______X, X_______,
+ ___XXX__, ______XX, X_______,
+ ____XXX_, _____XXX, ________,
+ _____XXX, ____XXX_, ________,
+ _______X, XXXXX___, ________,
+ ________, ________, ________,
+ ________, ________, ________};
+
+/* char: A code:0x0041 */
+static GUI_CONST_STORAGE unsigned char ac0041[96] = {
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ _______X, XXX_____, ________,
+ _______X, XXX_____, ________,
+ _______X, XXX_____, ________,
+ _______X, XXX_____, ________,
+ ______XX, _XXX____, ________,
+ ______XX, _XXX____, ________,
+ ______XX, _XXX____, ________,
+ ______XX, _XXX____, ________,
+ _____XX_, __XXX___, ________,
+ _____XX_, __XXX___, ________,
+ _____XX_, __XXX___, ________,
+ _____XX_, __XXX___, ________,
+ ____XX__, ___XXX__, ________,
+ ____XX__, ___XXX__, ________,
+ ____XXXX, XXXXXX__, ________,
+ ___XXX__, ___XXX__, ________,
+ ___XX___, ___XXXX_, ________,
+ ___XX___, ____XXX_, ________,
+ ___XX___, ____XXX_, ________,
+ __XXX___, ____XXX_, ________,
+ __XX____, ____XXXX, ________,
+ __XX____, _____XXX, ________,
+ __XXX___, _____XXX, ________,
+ XXXXXX__, ___XXXXX, XX______,
+ ________, ________, ________,
+ ________, ________, ________};
+
+/* char: B code:0x0042 */
+static GUI_CONST_STORAGE unsigned char ac0042[96] = {
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ _XXXXXXX, XXXXXX__, ________,
+ ___XXX__, ___XXXXX, ________,
+ ___XXX__, _____XXX, ________,
+ ___XXX__, ______XX, X_______,
+ ___XXX__, ______XX, X_______,
+ ___XXX__, ______XX, X_______,
+ ___XXX__, ______XX, X_______,
+ ___XXX__, ______XX, X_______,
+ ___XXX__, _____XXX, ________,
+ ___XXX__, _____XXX, ________,
+ ___XXX__, ___XXX__, ________,
+ ___XXXXX, XXXXX___, ________,
+ ___XXX__, ____XXX_, ________,
+ ___XXX__, ______XX, ________,
+ ___XXX__, ______XX, X_______,
+ ___XXX__, _______X, XX______,
+ ___XXX__, _______X, XX______,
+ ___XXX__, _______X, XX______,
+ ___XXX__, _______X, XX______,
+ ___XXX__, _______X, XX______,
+ ___XXX__, ______XX, X_______,
+ ___XXX__, ______XX, X_______,
+ ___XXX__, ____XXXX, ________,
+ _XXXXXXX, XXXXXX__, ________,
+ ________, ________, ________,
+ ________, ________, ________};
+
+/* char: C code:0x0043 */
+static GUI_CONST_STORAGE unsigned char ac0043[96] = {
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ _______X, XXXXXX_X, X_______,
+ _____XXX, ____XXXX, X_______,
+ ____XXX_, ______XX, X_______,
+ ___XXX__, _______X, X_______,
+ ___XXX__, ________, XX______,
+ __XXX___, ________, XX______,
+ __XXX___, ________, ________,
+ __XX____, ________, ________,
+ _XXX____, ________, ________,
+ _XXX____, ________, ________,
+ _XXX____, ________, ________,
+ _XXX____, ________, ________,
+ _XXX____, ________, ________,
+ _XXX____, ________, ________,
+ _XXX____, ________, ________,
+ _XXX____, ________, ________,
+ _XXX____, ________, ________,
+ __XXX___, ________, XX______,
+ __XXX___, ________, XX______,
+ __XXX___, _______X, X_______,
+ ___XXX__, _______X, X_______,
+ ____XXX_, ______XX, ________,
+ _____XXX, ____XXX_, ________,
+ _______X, XXXXX___, ________,
+ ________, ________, ________,
+ ________, ________, ________};
+
+/* char: D code:0x0044 */
+static GUI_CONST_STORAGE unsigned char ac0044[96] = {
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ _XXXXXXX, XXXX____, ________,
+ ___XXX__, __XXXX__, ________,
+ ___XXX__, ____XXX_, ________,
+ ___XXX__, _____XXX, ________,
+ ___XXX__, ______XX, X_______,
+ ___XXX__, ______XX, X_______,
+ ___XXX__, ______XX, X_______,
+ ___XXX__, _______X, XX______,
+ ___XXX__, _______X, XX______,
+ ___XXX__, _______X, XX______,
+ ___XXX__, _______X, XX______,
+ ___XXX__, _______X, XX______,
+ ___XXX__, _______X, XX______,
+ ___XXX__, _______X, XX______,
+ ___XXX__, _______X, XX______,
+ ___XXX__, _______X, XX______,
+ ___XXX__, _______X, XX______,
+ ___XXX__, ______XX, X_______,
+ ___XXX__, ______XX, X_______,
+ ___XXX__, ______XX, ________,
+ ___XXX__, _____XXX, ________,
+ ___XXX__, ____XXX_, ________,
+ ___XXX__, __XXXX__, ________,
+ _XXXXXXX, XXXX____, ________,
+ ________, ________, ________,
+ ________, ________, ________};
+
+/* char: E code:0x0045 */
+static GUI_CONST_STORAGE unsigned char ac0045[96] = {
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ _XXXXXXX, XXXXXXXX, X_______,
+ ___XXX__, _____XXX, X_______,
+ ___XXX__, ______XX, X_______,
+ ___XXX__, _______X, XX______,
+ ___XXX__, ________, XX______,
+ ___XXX__, ________, ________,
+ ___XXX__, ________, ________,
+ ___XXX__, ____XX__, ________,
+ ___XXX__, ____XX__, ________,
+ ___XXX__, ____XX__, ________,
+ ___XXX__, ___XXX__, ________,
+ ___XXXXX, XXXXXX__, ________,
+ ___XXX__, ___XXX__, ________,
+ ___XXX__, ____XX__, ________,
+ ___XXX__, ____XX__, ________,
+ ___XXX__, ____XX__, ________,
+ ___XXX__, ________, ________,
+ ___XXX__, ________, ________,
+ ___XXX__, ________, XX______,
+ ___XXX__, ________, XX______,
+ ___XXX__, _______X, X_______,
+ ___XXX__, ______XX, X_______,
+ ___XXX__, _____XXX, X_______,
+ _XXXXXXX, XXXXXXXX, X_______,
+ ________, ________, ________,
+ ________, ________, ________};
+
+/* char: F code:0x0046 */
+static GUI_CONST_STORAGE unsigned char ac0046[96] = {
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ _XXXXXXX, XXXXXXXX, X_______,
+ ___XXX__, _____XXX, X_______,
+ ___XXX__, ______XX, X_______,
+ ___XXX__, _______X, XX______,
+ ___XXX__, ________, XX______,
+ ___XXX__, ________, ________,
+ ___XXX__, ________, ________,
+ ___XXX__, ________, ________,
+ ___XXX__, ____XX__, ________,
+ ___XXX__, ____XX__, ________,
+ ___XXX__, ___XXX__, ________,
+ ___XXXXX, XXXXXX__, ________,
+ ___XXX__, ___XXX__, ________,
+ ___XXX__, ____XX__, ________,
+ ___XXX__, ____XX__, ________,
+ ___XXX__, ____XX__, ________,
+ ___XXX__, ________, ________,
+ ___XXX__, ________, ________,
+ ___XXX__, ________, ________,
+ ___XXX__, ________, ________,
+ ___XXX__, ________, ________,
+ ___XXX__, ________, ________,
+ ___XXX__, ________, ________,
+ _XXXXXXX, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________};
+
+/* char: G code:0x0047 */
+static GUI_CONST_STORAGE unsigned char ac0047[96] = {
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ _______X, XXXX____, ________,
+ _____XXX, ___XXXX_, ________,
+ ____XXX_, ____XXX_, ________,
+ ___XXX__, _____XXX, ________,
+ ___XX___, ______XX, ________,
+ __XXX___, ______XX, ________,
+ __XXX___, ________, ________,
+ __XX____, ________, ________,
+ _XXX____, ________, ________,
+ _XXX____, ________, ________,
+ _XXX____, ________, ________,
+ _XXX____, ________, ________,
+ _XXX____, ________, ________,
+ _XXX____, ___XXXXX, XX______,
+ _XXX____, _____XXX, ________,
+ _XXX____, _____XXX, ________,
+ _XXX____, _____XXX, ________,
+ __XXX___, _____XXX, ________,
+ __XXX___, _____XXX, ________,
+ ___XX___, _____XXX, ________,
+ ___XXX__, _____XXX, ________,
+ ____XXX_, _____XXX, ________,
+ _____XXX, ____XX__, ________,
+ ______XX, XXXXX___, ________,
+ ________, ________, ________,
+ ________, ________, ________};
+
+/* char: H code:0x0048 */
+static GUI_CONST_STORAGE unsigned char ac0048[96] = {
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ XXXXXXX_, ___XXXXX, XX______,
+ __XXX___, _____XXX, ________,
+ __XXX___, _____XXX, ________,
+ __XXX___, _____XXX, ________,
+ __XXX___, _____XXX, ________,
+ __XXX___, _____XXX, ________,
+ __XXX___, _____XXX, ________,
+ __XXX___, _____XXX, ________,
+ __XXX___, _____XXX, ________,
+ __XXX___, _____XXX, ________,
+ __XXX___, _____XXX, ________,
+ __XXXXXX, XXXXXXXX, ________,
+ __XXX___, _____XXX, ________,
+ __XXX___, _____XXX, ________,
+ __XXX___, _____XXX, ________,
+ __XXX___, _____XXX, ________,
+ __XXX___, _____XXX, ________,
+ __XXX___, _____XXX, ________,
+ __XXX___, _____XXX, ________,
+ __XXX___, _____XXX, ________,
+ __XXX___, _____XXX, ________,
+ __XXX___, _____XXX, ________,
+ __XXX___, _____XXX, ________,
+ XXXXXXX_, ___XXXXX, XX______,
+ ________, ________, ________,
+ ________, ________, ________};
+
+/* char: I code:0x0049 */
+static GUI_CONST_STORAGE unsigned char ac0049[96] = {
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ____XXXX, XXXXXXX_, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ____XXXX, XXXXXXX_, ________,
+ ________, ________, ________,
+ ________, ________, ________};
+
+/* char: J code:0x004A */
+static GUI_CONST_STORAGE unsigned char ac004A[96] = {
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ______XX, XXXXXXXX, XXX_____,
+ ________, ___XXX__, ________,
+ ________, ___XXX__, ________,
+ ________, ___XXX__, ________,
+ ________, ___XXX__, ________,
+ ________, ___XXX__, ________,
+ ________, ___XXX__, ________,
+ ________, ___XXX__, ________,
+ ________, ___XXX__, ________,
+ ________, ___XXX__, ________,
+ ________, ___XXX__, ________,
+ ________, ___XXX__, ________,
+ ________, ___XXX__, ________,
+ ________, ___XXX__, ________,
+ ________, ___XXX__, ________,
+ ________, ___XXX__, ________,
+ ________, ___XXX__, ________,
+ ________, ___XXX__, ________,
+ ________, ___XXX__, ________,
+ ________, ___XXX__, ________,
+ ________, ___XXX__, ________,
+ ________, ___XXX__, ________,
+ ________, ___XXX__, ________,
+ ________, ___XXX__, ________,
+ _XXXX___, ___XX___, ________,
+ _XXXX___, __XXX___, ________};
+
+/* char: K code:0x004B */
+static GUI_CONST_STORAGE unsigned char ac004B[96] = {
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ _XXXXXXX, __XXXXXX, X_______,
+ ___XXX__, ____XXX_, ________,
+ ___XXX__, ____XX__, ________,
+ ___XXX__, ___XX___, ________,
+ ___XXX__, __XXX___, ________,
+ ___XXX__, __XX____, ________,
+ ___XXX__, _XX_____, ________,
+ ___XXX__, XX______, ________,
+ ___XXX__, XX______, ________,
+ ___XXX_X, XX______, ________,
+ ___XXXXX, XX______, ________,
+ ___XXXXX, XXX_____, ________,
+ ___XXXX_, XXX_____, ________,
+ ___XXX__, _XXX____, ________,
+ ___XXX__, _XXX____, ________,
+ ___XXX__, __XXX___, ________,
+ ___XXX__, __XXX___, ________,
+ ___XXX__, ___XXX__, ________,
+ ___XXX__, ___XXX__, ________,
+ ___XXX__, ___XXXX_, ________,
+ ___XXX__, ____XXX_, ________,
+ ___XXX__, ____XXXX, ________,
+ ___XXX__, _____XXX, ________,
+ _XXXXXXX, ___XXXXX, XX______,
+ ________, ________, ________,
+ ________, ________, ________};
+
+/* char: L code:0x004C */
+static GUI_CONST_STORAGE unsigned char ac004C[96] = {
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ _XXXXXXX, ________, ________,
+ ___XXX__, ________, ________,
+ ___XXX__, ________, ________,
+ ___XXX__, ________, ________,
+ ___XXX__, ________, ________,
+ ___XXX__, ________, ________,
+ ___XXX__, ________, ________,
+ ___XXX__, ________, ________,
+ ___XXX__, ________, ________,
+ ___XXX__, ________, ________,
+ ___XXX__, ________, ________,
+ ___XXX__, ________, ________,
+ ___XXX__, ________, ________,
+ ___XXX__, ________, ________,
+ ___XXX__, ________, ________,
+ ___XXX__, ________, ________,
+ ___XXX__, ________, ________,
+ ___XXX__, ________, ________,
+ ___XXX__, ________, XX______,
+ ___XXX__, ________, XX______,
+ ___XXX__, _______X, X_______,
+ ___XXX__, ______XX, X_______,
+ ___XXX__, _____XXX, X_______,
+ _XXXXXXX, XXXXXXXX, X_______,
+ ________, ________, ________,
+ ________, ________, ________};
+
+/* char: M code:0x004D */
+static GUI_CONST_STORAGE unsigned char ac004D[96] = {
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ XXXXXX__, _____XXX, XXX_____,
+ __XXXX__, _____XXX, X_______,
+ __XXXX__, _____XXX, X_______,
+ __XXXX__, _____XXX, X_______,
+ __XXXXX_, ____XXXX, X_______,
+ __XXXXX_, ____XXXX, X_______,
+ __XXXXX_, ____XXXX, X_______,
+ __XXXXX_, ____XXXX, X_______,
+ __XXXXX_, ___XXXXX, X_______,
+ __XXXXXX, ___XX_XX, X_______,
+ __XX_XXX, ___XX_XX, X_______,
+ __XX_XXX, ___XX_XX, X_______,
+ __XX_XXX, __XXX_XX, X_______,
+ __XX_XXX, X_XX__XX, X_______,
+ __XX__XX, X_XX__XX, X_______,
+ __XX__XX, X_XX__XX, X_______,
+ __XX__XX, XXXX__XX, X_______,
+ __XX__XX, XXX___XX, X_______,
+ __XX___X, XXX___XX, X_______,
+ __XX___X, XXX___XX, X_______,
+ __XX___X, XXX___XX, X_______,
+ __XX___X, XX____XX, X_______,
+ __XX___X, XX____XX, X_______,
+ XXXXXX__, XX__XXXX, XXX_____,
+ ________, ________, ________,
+ ________, ________, ________};
+
+/* char: N code:0x004E */
+static GUI_CONST_STORAGE unsigned char ac004E[96] = {
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ _XXXXX__, ____XXXX, XX______,
+ ___XXXX_, ______XX, ________,
+ ___XXXX_, ______XX, ________,
+ ___XXXXX, ______XX, ________,
+ ___XXXXX, ______XX, ________,
+ ___XXXXX, X_____XX, ________,
+ ___XX_XX, X_____XX, ________,
+ ___XX_XX, X_____XX, ________,
+ ___XX__X, XX____XX, ________,
+ ___XX__X, XX____XX, ________,
+ ___XX___, XXX___XX, ________,
+ ___XX___, XXX___XX, ________,
+ ___XX___, _XXX__XX, ________,
+ ___XX___, _XXX__XX, ________,
+ ___XX___, __XXX_XX, ________,
+ ___XX___, __XXX_XX, ________,
+ ___XX___, ___XXXXX, ________,
+ ___XX___, ___XXXXX, ________,
+ ___XX___, ___XXXXX, ________,
+ ___XX___, ____XXXX, ________,
+ ___XX___, ____XXXX, ________,
+ ___XX___, _____XXX, ________,
+ ___XX___, _____XXX, ________,
+ _XXXXXX_, ______XX, ________,
+ ________, ________, ________,
+ ________, ________, ________};
+
+/* char: O code:0x004F */
+static GUI_CONST_STORAGE unsigned char ac004F[96] = {
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ______XX, XXXXX___, ________,
+ _____XXX, ___XXX__, ________,
+ ____XXX_, _____XX_, ________,
+ ___XXX__, _____XXX, ________,
+ ___XX___, ______XX, ________,
+ __XXX___, ______XX, X_______,
+ __XXX___, ______XX, X_______,
+ _XXX____, _______X, X_______,
+ _XXX____, _______X, XX______,
+ _XXX____, _______X, XX______,
+ _XXX____, _______X, XX______,
+ _XXX____, _______X, XX______,
+ _XXX____, _______X, XX______,
+ _XXX____, _______X, XX______,
+ _XXX____, _______X, XX______,
+ _XXX____, _______X, XX______,
+ _XXX____, _______X, XX______,
+ __XXX___, _______X, X_______,
+ __XXX___, ______XX, X_______,
+ ___XX___, ______XX, ________,
+ ___XXX__, _____XXX, ________,
+ ____XXX_, _____XX_, ________,
+ _____XXX, ___XXX__, ________,
+ _______X, XXXXX___, ________,
+ ________, ________, ________,
+ ________, ________, ________};
+
+/* char: P code:0x0050 */
+static GUI_CONST_STORAGE unsigned char ac0050[96] = {
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ _XXXXXXX, XXXXXX__, ________,
+ ___XXX__, ____XXXX, ________,
+ ___XXX__, ______XX, X_______,
+ ___XXX__, ______XX, X_______,
+ ___XXX__, _______X, XX______,
+ ___XXX__, _______X, XX______,
+ ___XXX__, _______X, XX______,
+ ___XXX__, _______X, XX______,
+ ___XXX__, _______X, XX______,
+ ___XXX__, ______XX, X_______,
+ ___XXX__, _____XXX, X_______,
+ ___XXX__, ____XXXX, ________,
+ ___XXXXX, XXXXXX__, ________,
+ ___XXX__, ________, ________,
+ ___XXX__, ________, ________,
+ ___XXX__, ________, ________,
+ ___XXX__, ________, ________,
+ ___XXX__, ________, ________,
+ ___XXX__, ________, ________,
+ ___XXX__, ________, ________,
+ ___XXX__, ________, ________,
+ ___XXX__, ________, ________,
+ ___XXX__, ________, ________,
+ _XXXXXXX, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________};
+
+/* char: Q code:0x0051 */
+static GUI_CONST_STORAGE unsigned char ac0051[96] = {
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ______XX, XXXXX___, ________,
+ _____XXX, ___XXX__, ________,
+ ____XXX_, _____XX_, ________,
+ ___XXX__, _____XXX, ________,
+ __XXX___, ______XX, X_______,
+ __XXX___, ______XX, X_______,
+ __XXX___, _______X, X_______,
+ _XXX____, _______X, XX______,
+ _XXX____, _______X, XX______,
+ _XXX____, _______X, XX______,
+ _XXX____, _______X, XX______,
+ _XXX____, _______X, XX______,
+ _XXX____, _______X, XX______,
+ _XXX____, _______X, XX______,
+ _XXX____, _______X, XX______,
+ _XXX____, _______X, XX______,
+ _XXX____, _______X, XX______,
+ __XX_XXX, XXX____X, X_______,
+ __XXXXX_, _XXX__XX, X_______,
+ __XXXX__, __XXX_XX, X_______,
+ ___XXX__, __XXX_XX, ________,
+ ____XX__, __XXXXX_, ________,
+ _____XXX, ___XXXX_, ________,
+ ______XX, XXXXXX__, ________,
+ ________, ___XXXX_, XX______,
+ ________, ____XXXX, X_______};
+
+/* char: R code:0x0052 */
+static GUI_CONST_STORAGE unsigned char ac0052[96] = {
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ _XXXXXXX, XXXXX___, ________,
+ ___XXX__, ___XXXX_, ________,
+ ___XXX__, _____XXX, ________,
+ ___XXX__, _____XXX, X_______,
+ ___XXX__, ______XX, X_______,
+ ___XXX__, ______XX, X_______,
+ ___XXX__, ______XX, X_______,
+ ___XXX__, ______XX, X_______,
+ ___XXX__, _____XXX, ________,
+ ___XXX__, _____XXX, ________,
+ ___XXX__, ___XXXX_, ________,
+ ___XXXXX, XXXXX___, ________,
+ ___XXX__, _XXX____, ________,
+ ___XXX__, _XXX____, ________,
+ ___XXX__, _XXXX___, ________,
+ ___XXX__, __XXX___, ________,
+ ___XXX__, __XXXX__, ________,
+ ___XXX__, ___XXX__, ________,
+ ___XXX__, ___XXX__, ________,
+ ___XXX__, ___XXXX_, ________,
+ ___XXX__, ____XXX_, ________,
+ ___XXX__, ____XXXX, ________,
+ ___XXX__, _____XXX, ________,
+ _XXXXXXX, _____XXX, XX______,
+ ________, ________, ________,
+ ________, ________, ________};
+
+/* char: S code:0x0053 */
+static GUI_CONST_STORAGE unsigned char ac0053[96] = {
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ______XX, XXXX____, ________,
+ ____XXX_, ___XXXXX, ________,
+ ___XXX__, ____XXXX, ________,
+ ___XX___, _____XXX, ________,
+ __XXX___, ______XX, ________,
+ __XXX___, ______XX, ________,
+ __XXX___, ________, ________,
+ __XXXX__, ________, ________,
+ ___XXXX_, ________, ________,
+ ___XXXXX, ________, ________,
+ _____XXX, XX______, ________,
+ _______X, XXXXX___, ________,
+ ________, _XXXXX__, ________,
+ ________, ___XXXX_, ________,
+ ________, ____XXXX, ________,
+ ________, _____XXX, X_______,
+ ________, ______XX, X_______,
+ __XX____, ______XX, X_______,
+ __XX____, ______XX, X_______,
+ __XXX___, ______XX, X_______,
+ ___XX___, ______XX, ________,
+ ___XXX__, _____XXX, ________,
+ ___XXXXX, ____XXX_, ________,
+ ___XX__X, XXXXX___, ________,
+ ________, ________, ________,
+ ________, ________, ________};
+
+/* char: T code:0x0054 */
+static GUI_CONST_STORAGE unsigned char ac0054[96] = {
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ __XXXXXX, XXXXXXXX, X_______,
+ __XXX___, XXX___XX, X_______,
+ __XX____, XXX____X, X_______,
+ _XXX____, XXX_____, XX______,
+ _XX_____, XXX_____, XX______,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ______XX, XXXXX___, ________,
+ ________, ________, ________,
+ ________, ________, ________};
+
+/* char: U code:0x0055 */
+static GUI_CONST_STORAGE unsigned char ac0055[96] = {
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ XXXXXXX_, ____XXXX, XX______,
+ __XXX___, ______XX, ________,
+ __XXX___, ______XX, ________,
+ __XXX___, ______XX, ________,
+ __XXX___, ______XX, ________,
+ __XXX___, ______XX, ________,
+ __XXX___, ______XX, ________,
+ __XXX___, ______XX, ________,
+ __XXX___, ______XX, ________,
+ __XXX___, ______XX, ________,
+ __XXX___, ______XX, ________,
+ __XXX___, ______XX, ________,
+ __XXX___, ______XX, ________,
+ __XXX___, ______XX, ________,
+ __XXX___, ______XX, ________,
+ __XXX___, ______XX, ________,
+ __XXX___, ______XX, ________,
+ __XXX___, ______XX, ________,
+ __XXX___, ______XX, ________,
+ __XXX___, ______XX, ________,
+ __XXX___, _____XXX, ________,
+ ___XXX__, _____XX_, ________,
+ ____XXX_, ___XXX__, ________,
+ ______XX, XXXX____, ________,
+ ________, ________, ________,
+ ________, ________, ________};
+
+/* char: V code:0x0056 */
+static GUI_CONST_STORAGE unsigned char ac0056[96] = {
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ _XXXXXXX, ____XXXX, XX______,
+ ___XXX__, ______XX, ________,
+ ___XXX__, ______XX, ________,
+ ___XXXX_, _____XXX, ________,
+ ____XXX_, _____XX_, ________,
+ ____XXX_, _____XX_, ________,
+ ____XXX_, _____XX_, ________,
+ ____XXXX, ____XX__, ________,
+ _____XXX, ____XX__, ________,
+ _____XXX, ____XX__, ________,
+ _____XXX, ____XX__, ________,
+ _____XXX, ___XX___, ________,
+ _____XXX, X__XX___, ________,
+ ______XX, X__XX___, ________,
+ ______XX, X__XX___, ________,
+ ______XX, X_XX____, ________,
+ ______XX, XXXX____, ________,
+ _______X, XXXX____, ________,
+ _______X, XXXX____, ________,
+ _______X, XXX_____, ________,
+ _______X, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XX______, ________,
+ ________, XX______, ________,
+ ________, ________, ________,
+ ________, ________, ________};
+
+/* char: W code:0x0057 */
+static GUI_CONST_STORAGE unsigned char ac0057[96] = {
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ XXXXXX_X, XXXXX_XX, XXX_____,
+ _XXXX___, XXX____X, XX______,
+ __XXX___, XXX____X, X_______,
+ __XXX___, XXX____X, X_______,
+ __XXX___, XXXX___X, X_______,
+ __XXX___, _XXX___X, X_______,
+ __XXX___, XXXX__XX, ________,
+ __XXX___, XXXX__XX, ________,
+ __XXX___, XXXX__XX, ________,
+ ___XXX__, XXXX__XX, ________,
+ ___XXX__, XXXX__XX, ________,
+ ___XXX_X, XXXXX_XX, ________,
+ ___XXX_X, X_XXXXX_, ________,
+ ___XXX_X, X_XXXXX_, ________,
+ ___XXX_X, X_XXXXX_, ________,
+ ____XXXX, X_XXXXX_, ________,
+ ____XXXX, __XXXXX_, ________,
+ ____XXXX, __XXXXX_, ________,
+ ____XXXX, ___XXX__, ________,
+ ____XXXX, ___XXX__, ________,
+ ____XXXX, ___XXX__, ________,
+ _____XX_, ___XXX__, ________,
+ _____XX_, ___XXX__, ________,
+ _____XX_, ___XX___, ________,
+ ________, ________, ________,
+ ________, ________, ________};
+
+/* char: X code:0x0058 */
+static GUI_CONST_STORAGE unsigned char ac0058[96] = {
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ _XXXXXXX, ___XXXXX, X_______,
+ ___XXXX_, _____XXX, ________,
+ ____XXX_, _____XX_, ________,
+ ____XXX_, ____XX__, ________,
+ _____XXX, ____XX__, ________,
+ _____XXX, ___XX___, ________,
+ ______XX, X__XX___, ________,
+ ______XX, X_XXX___, ________,
+ ______XX, XXXX____, ________,
+ _______X, XXXX____, ________,
+ _______X, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ _______X, XXXX____, ________,
+ _______X, XXXX____, ________,
+ ______XX, X_XXX___, ________,
+ ______XX, __XXX___, ________,
+ ______XX, __XXXX__, ________,
+ _____XX_, ___XXX__, ________,
+ _____XX_, ___XXXX_, ________,
+ ____XX__, ____XXX_, ________,
+ ____XX__, ____XXXX, ________,
+ ___XXX__, _____XXX, ________,
+ _XXXXXX_, ___XXXXX, XX______,
+ ________, ________, ________,
+ ________, ________, ________};
+
+/* char: Y code:0x0059 */
+static GUI_CONST_STORAGE unsigned char ac0059[96] = {
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ _XXXXXXX, ____XXXX, XX______,
+ __XXXX__, _____XXX, ________,
+ ___XXX__, _____XXX, ________,
+ ___XXXX_, _____XX_, ________,
+ ____XXX_, _____XX_, ________,
+ ____XXX_, ____XX__, ________,
+ _____XXX, ____XX__, ________,
+ _____XXX, ___XXX__, ________,
+ _____XXX, X__XX___, ________,
+ ______XX, X__XX___, ________,
+ ______XX, X_XX____, ________,
+ _______X, XXXX____, ________,
+ _______X, XXXX____, ________,
+ _______X, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ______XX, XXXXX___, ________,
+ ________, ________, ________,
+ ________, ________, ________};
+
+/* char: Z code:0x005A */
+static GUI_CONST_STORAGE unsigned char ac005A[96] = {
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ___XXXXX, XXXXXXXX, X_______,
+ ___XXXX_, _____XXX, ________,
+ ___XXX__, ____XXXX, ________,
+ __XXX___, ____XXX_, ________,
+ __XX____, ___XXXX_, ________,
+ ________, ___XXX__, ________,
+ ________, __XXXX__, ________,
+ ________, __XXX___, ________,
+ ________, _XXX____, ________,
+ ________, _XXX____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ _______X, XX______, ________,
+ _______X, XX______, ________,
+ ______XX, X_______, ________,
+ ______XX, X_______, ________,
+ _____XXX, ________, ________,
+ ____XXXX, ________, ________,
+ ____XXX_, _______X, X_______,
+ ___XXXX_, _______X, X_______,
+ ___XXX__, ______XX, ________,
+ __XXXX__, _____XXX, ________,
+ __XXX___, ____XXXX, ________,
+ _XXXXXXX, XXXXXXXX, ________,
+ ________, ________, ________,
+ ________, ________, ________};
+
+/* char: [ code:0x005B */
+static GUI_CONST_STORAGE unsigned char ac005B[96] = {
+ ________, ________, ________,
+ ________, ________, ________,
+ _______X, XXXXXXXX, ________,
+ _______X, X_______, ________,
+ _______X, X_______, ________,
+ _______X, X_______, ________,
+ _______X, X_______, ________,
+ _______X, X_______, ________,
+ _______X, X_______, ________,
+ _______X, X_______, ________,
+ _______X, X_______, ________,
+ _______X, X_______, ________,
+ _______X, X_______, ________,
+ _______X, X_______, ________,
+ _______X, X_______, ________,
+ _______X, X_______, ________,
+ _______X, X_______, ________,
+ _______X, X_______, ________,
+ _______X, X_______, ________,
+ _______X, X_______, ________,
+ _______X, X_______, ________,
+ _______X, X_______, ________,
+ _______X, X_______, ________,
+ _______X, X_______, ________,
+ _______X, X_______, ________,
+ _______X, X_______, ________,
+ _______X, X_______, ________,
+ _______X, X_______, ________,
+ _______X, X_______, ________,
+ _______X, X_______, ________,
+ _______X, X_______, ________,
+ _______X, X_______, ________};
+
+/* char: \ code:0x005C */
+static GUI_CONST_STORAGE unsigned char ac005C[96] = {
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ___XXX__, ________, ________,
+ ____XX__, ________, ________,
+ ____XXX_, ________, ________,
+ ____XXX_, ________, ________,
+ _____XX_, ________, ________,
+ _____XXX, ________, ________,
+ _____XXX, ________, ________,
+ ______XX, X_______, ________,
+ ______XX, X_______, ________,
+ _______X, X_______, ________,
+ _______X, XX______, ________,
+ _______X, XX______, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, _XXX____, ________,
+ ________, _XXX____, ________,
+ ________, __XX____, ________,
+ ________, __XXX___, ________,
+ ________, __XXX___, ________,
+ ________, ___XXX__, ________,
+ ________, ___XXX__, ________,
+ ________, ____XX__, ________,
+ ________, ____XXX_, ________,
+ ________, ____XXX_, ________,
+ ________, _____XXX, ________,
+ ________, _____XXX, ________};
+
+/* char: ] code:0x005D */
+static GUI_CONST_STORAGE unsigned char ac005D[96] = {
+ ________, ________, ________,
+ ________, ________, ________,
+ __XXXXXX, XXXX____, ________,
+ ________, _XXX____, ________,
+ ________, _XXX____, ________,
+ ________, _XXX____, ________,
+ ________, _XXX____, ________,
+ ________, _XXX____, ________,
+ ________, _XXX____, ________,
+ ________, _XXX____, ________,
+ ________, _XXX____, ________,
+ ________, _XXX____, ________,
+ ________, _XXX____, ________,
+ ________, _XXX____, ________,
+ ________, _XXX____, ________,
+ ________, _XXX____, ________,
+ ________, _XXX____, ________,
+ ________, _XXX____, ________,
+ ________, _XXX____, ________,
+ ________, _XXX____, ________,
+ ________, _XXX____, ________,
+ ________, _XXX____, ________,
+ ________, _XXX____, ________,
+ ________, _XXX____, ________,
+ ________, _XXX____, ________,
+ ________, _XXX____, ________,
+ ________, _XXX____, ________,
+ ________, _XXX____, ________,
+ ________, _XXX____, ________,
+ ________, _XXX____, ________,
+ ________, _XXX____, ________,
+ ________, _XXX____, ________};
+
+/* char: ^ code:0x005E */
+static GUI_CONST_STORAGE unsigned char ac005E[96] = {
+ ________, ________, ________,
+ ________, ________, ________,
+ _______X, XXXX____, ________,
+ ______XX, XXXX____, ________,
+ _____XXX, __XXX___, ________,
+ ____XX__, ____XX__, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________};
+
+/* char: _ code:0x005F */
+static GUI_CONST_STORAGE unsigned char ac005F[96] = {
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________};
+
+/* char: ` code:0x0060 */
+static GUI_CONST_STORAGE unsigned char ac0060[96] = {
+ ________, ________, ________,
+ ___XXXXX, ________, ________,
+ _____XXX, X_______, ________,
+ _______X, XX______, ________,
+ ________, _XX_____, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________};
+
+/* char: a code:0x0061 */
+static GUI_CONST_STORAGE unsigned char ac0061[96] = {
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ______XX, XXXXX___, ________,
+ ____XXX_, ___XXX__, ________,
+ ___XXX__, ____XXX_, ________,
+ ___XXX__, ____XXX_, ________,
+ ___XXX__, ____XXX_, ________,
+ ________, ____XXX_, ________,
+ _______X, XXXXXXX_, ________,
+ _____XXX, X___XXX_, ________,
+ ___XXXX_, ____XXX_, ________,
+ ___XXX__, ____XXX_, ________,
+ __XXX___, ____XXX_, ________,
+ __XXX___, ____XXX_, ________,
+ __XXX___, ____XXX_, XX______,
+ __XXX___, ___XXXX_, XX______,
+ ___XXX__, __XXXXX_, XX______,
+ ____XXXX, XXX__XXX, X_______,
+ ________, ________, ________,
+ ________, ________, ________};
+
+/* char: b code:0x0062 */
+static GUI_CONST_STORAGE unsigned char ac0062[96] = {
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ____XX__, ________, ________,
+ _XXXXX__, ________, ________,
+ ___XXX__, ________, ________,
+ ___XXX__, ________, ________,
+ ___XXX__, ________, ________,
+ ___XXX__, ________, ________,
+ ___XXX__, ________, ________,
+ ___XXX__, ________, ________,
+ ___XXX__, ________, ________,
+ ___XXX__, XXXXXX__, ________,
+ ___XXXXX, X___XXX_, ________,
+ ___XXXXX, _____XXX, ________,
+ ___XXXX_, _____XXX, ________,
+ ___XXX__, ______XX, X_______,
+ ___XXX__, ______XX, X_______,
+ ___XXX__, ______XX, X_______,
+ ___XXX__, ______XX, X_______,
+ ___XXX__, ______XX, X_______,
+ ___XXX__, ______XX, X_______,
+ ___XXX__, ______XX, X_______,
+ ___XXX__, ______XX, X_______,
+ ___XXX__, _____XXX, ________,
+ ___XXXX_, _____XXX, ________,
+ ___XXXXX, ____XXX_, ________,
+ ___XX__X, XXXXX___, ________,
+ ________, ________, ________,
+ ________, ________, ________};
+
+/* char: c code:0x0063 */
+static GUI_CONST_STORAGE unsigned char ac0063[96] = {
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ _______X, XXXXXX__, ________,
+ _____XXX, X___XXX_, ________,
+ ____XXX_, _____XXX, ________,
+ ___XXX__, _____XXX, ________,
+ ___XXX__, _____XXX, ________,
+ __XXX___, ________, ________,
+ __XXX___, ________, ________,
+ __XXX___, ________, ________,
+ __XXX___, ________, ________,
+ __XXX___, ________, ________,
+ __XXX___, ________, ________,
+ ___XX___, _______X, X_______,
+ ___XXX__, ______XX, ________,
+ ____XXX_, ______XX, ________,
+ _____XXX, ____XXX_, ________,
+ ______XX, XXXXX___, ________,
+ ________, ________, ________,
+ ________, ________, ________};
+
+/* char: d code:0x0064 */
+static GUI_CONST_STORAGE unsigned char ac0064[96] = {
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ______XX, ________,
+ ________, ___XXXXX, ________,
+ ________, _____XXX, ________,
+ ________, _____XXX, ________,
+ ________, _____XXX, ________,
+ ________, _____XXX, ________,
+ ________, _____XXX, ________,
+ ________, _____XXX, ________,
+ ________, _____XXX, ________,
+ ______XX, XXXX_XXX, ________,
+ _____XXX, ___XXXXX, ________,
+ ____XXX_, ____XXXX, ________,
+ ___XXX__, _____XXX, ________,
+ ___XXX__, _____XXX, ________,
+ __XXX___, _____XXX, ________,
+ __XXX___, _____XXX, ________,
+ __XXX___, _____XXX, ________,
+ __XXX___, _____XXX, ________,
+ __XXX___, _____XXX, ________,
+ __XXX___, _____XXX, ________,
+ __XXX___, _____XXX, ________,
+ ___XXX__, ____XXXX, ________,
+ ___XXX__, ____XXXX, ________,
+ ____XXX_, ___XXXXX, XX______,
+ ______XX, XXXX_XX_, ________,
+ ________, ________, ________,
+ ________, ________, ________};
+
+/* char: e code:0x0065 */
+static GUI_CONST_STORAGE unsigned char ac0065[96] = {
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ _______X, XXXXX___, ________,
+ _____XXX, ____XXX_, ________,
+ ____XXX_, _____XXX, ________,
+ ___XXX__, _____XXX, ________,
+ ___XX___, ______XX, X_______,
+ __XXX___, ______XX, X_______,
+ __XXX___, ______XX, X_______,
+ __XXXXXX, XXXXXXXX, X_______,
+ __XXX___, ________, ________,
+ __XXX___, ________, ________,
+ __XXX___, ________, ________,
+ ___XX___, _______X, X_______,
+ ___XXX__, _______X, X_______,
+ ____XXX_, ______XX, ________,
+ _____XXX, ____XXX_, ________,
+ _______X, XXXXXX__, ________,
+ ________, ________, ________,
+ ________, ________, ________};
+
+/* char: f code:0x0066 */
+static GUI_CONST_STORAGE unsigned char ac0066[96] = {
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, _XXXXXXX, ________,
+ ________, XXX____X, XX______,
+ _______X, XX_____X, XX______,
+ ______XX, X______X, XX______,
+ ______XX, X_______, ________,
+ ______XX, X_______, ________,
+ ______XX, X_______, ________,
+ ______XX, X_______, ________,
+ __XXXXXX, XXXXXXX_, ________,
+ ______XX, X_______, ________,
+ ______XX, X_______, ________,
+ ______XX, X_______, ________,
+ ______XX, X_______, ________,
+ ______XX, X_______, ________,
+ ______XX, X_______, ________,
+ ______XX, X_______, ________,
+ ______XX, X_______, ________,
+ ______XX, X_______, ________,
+ ______XX, X_______, ________,
+ ______XX, X_______, ________,
+ ______XX, X_______, ________,
+ ______XX, X_______, ________,
+ ______XX, X_______, ________,
+ __XXXXXX, XXXXXX__, ________,
+ ________, ________, ________,
+ ________, ________, ________};
+
+/* char: g code:0x0067 */
+static GUI_CONST_STORAGE unsigned char ac0067[96] = {
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ______XX, XXXX__XX, XX______,
+ _____XXX, __XXXXXX, XX______,
+ ____XXX_, ___XXX__, ________,
+ ___XXX__, ____XXX_, ________,
+ ___XXX__, ____XXX_, ________,
+ ___XXX__, ____XXX_, ________,
+ ___XXX__, ____XXX_, ________,
+ ____XXX_, ___XXX__, ________,
+ _____XXX, ___XXX__, ________,
+ ____XXXX, XXXX____, ________,
+ ___XXX__, ________, ________,
+ ___XXX__, ________, ________,
+ ___XXXXX, XXX_____, ________,
+ _____XXX, XXXXXXX_, ________,
+ ___XXX__, ___XXXXX, ________,
+ __XXX___, ______XX, X_______,
+ __XXX___, ______XX, X_______,
+ __XXX___, ______XX, X_______};
+
+/* char: h code:0x0068 */
+static GUI_CONST_STORAGE unsigned char ac0068[96] = {
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ____XX__, ________, ________,
+ _XXXXX__, ________, ________,
+ ___XXX__, ________, ________,
+ ___XXX__, ________, ________,
+ ___XXX__, ________, ________,
+ ___XXX__, ________, ________,
+ ___XXX__, ________, ________,
+ ___XXX__, ________, ________,
+ ___XXX__, ________, ________,
+ ___XXX__, XXXXXX__, ________,
+ ___XXXXX, X___XXX_, ________,
+ ___XXXX_, _____XXX, ________,
+ ___XXX__, _____XXX, ________,
+ ___XXX__, _____XXX, ________,
+ ___XXX__, _____XXX, ________,
+ ___XXX__, _____XXX, ________,
+ ___XXX__, _____XXX, ________,
+ ___XXX__, _____XXX, ________,
+ ___XXX__, _____XXX, ________,
+ ___XXX__, _____XXX, ________,
+ ___XXX__, _____XXX, ________,
+ ___XXX__, _____XXX, ________,
+ ___XXX__, _____XXX, ________,
+ ___XXX__, _____XXX, ________,
+ _XXXXXXX, ___XXXXX, XX______,
+ ________, ________, ________,
+ ________, ________, ________};
+
+/* char: i code:0x0069 */
+static GUI_CONST_STORAGE unsigned char ac0069[96] = {
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, XXX_____, ________,
+ _______X, XXXX____, ________,
+ ________, XXX_____, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, _XX_____, ________,
+ ____XXXX, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ____XXXX, XXXXXXX_, ________,
+ ________, ________, ________,
+ ________, ________, ________};
+
+/* char: j code:0x006A */
+static GUI_CONST_STORAGE unsigned char ac006A[96] = {
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ____XXXX, ________,
+ ________, ___XXXXX, ________,
+ ________, ____XXX_, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, _____XX_, ________,
+ ________, XXXXXXX_, ________,
+ ________, ____XXX_, ________,
+ ________, ____XXX_, ________,
+ ________, ____XXX_, ________,
+ ________, ____XXX_, ________,
+ ________, ____XXX_, ________,
+ ________, ____XXX_, ________,
+ ________, ____XXX_, ________,
+ ________, ____XXX_, ________,
+ ________, ____XXX_, ________,
+ ________, ____XXX_, ________,
+ ________, ____XXX_, ________,
+ ________, ____XXX_, ________,
+ ________, ____XXX_, ________,
+ ________, ____XXX_, ________,
+ ________, ____XXX_, ________,
+ ________, ____XXX_, ________,
+ ___XXX__, ____XX__, ________};
+
+/* char: k code:0x006B */
+static GUI_CONST_STORAGE unsigned char ac006B[96] = {
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ____XX__, ________, ________,
+ _XXXXX__, ________, ________,
+ ___XXX__, ________, ________,
+ ___XXX__, ________, ________,
+ ___XXX__, ________, ________,
+ ___XXX__, ________, ________,
+ ___XXX__, ________, ________,
+ ___XXX__, ________, ________,
+ ___XXX__, ________, ________,
+ ___XXX__, __XXXXXX, X_______,
+ ___XXX__, ___XXXX_, ________,
+ ___XXX__, ___XX___, ________,
+ ___XXX__, __XXX___, ________,
+ ___XXX__, _XXX____, ________,
+ ___XXX__, XXX_____, ________,
+ ___XXX_X, XXX_____, ________,
+ ___XXXXX, XXXX____, ________,
+ ___XXXXX, _XXX____, ________,
+ ___XXXX_, _XXXX___, ________,
+ ___XXX__, __XXXX__, ________,
+ ___XXX__, ___XXX__, ________,
+ ___XXX__, ___XXXX_, ________,
+ ___XXX__, ____XXXX, ________,
+ ___XXX__, _____XXX, ________,
+ _XXXXXXX, ___XXXXX, XX______,
+ ________, ________, ________,
+ ________, ________, ________};
+
+/* char: l code:0x006C */
+static GUI_CONST_STORAGE unsigned char ac006C[96] = {
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, _XX_____, ________,
+ ____XXXX, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ________, XXX_____, ________,
+ ____XXXX, XXXXXXX_, ________,
+ ________, ________, ________,
+ ________, ________, ________};
+
+/* char: m code:0x006D */
+static GUI_CONST_STORAGE unsigned char ac006D[96] = {
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ___XX___, ________, ________,
+ _XXXXXXX, XX_XXXXX, ________,
+ __XXXX__, XXXX__XX, X_______,
+ __XXXX__, XXX___XX, X_______,
+ __XXX___, XXX___XX, X_______,
+ __XXX___, XXX___XX, X_______,
+ __XXX___, XXX___XX, X_______,
+ __XXX___, XXX___XX, X_______,
+ __XXX___, XXX___XX, X_______,
+ __XXX___, XXX___XX, X_______,
+ __XXX___, XXX___XX, X_______,
+ __XXX___, XXX___XX, X_______,
+ __XXX___, XXX___XX, X_______,
+ __XXX___, XXX___XX, X_______,
+ __XXX___, XXX___XX, X_______,
+ __XXX___, XXX___XX, X_______,
+ _XXXXX_X, XXXX_XXX, XX______,
+ ________, ________, ________,
+ ________, ________, ________};
+
+/* char: n code:0x006E */
+static GUI_CONST_STORAGE unsigned char ac006E[96] = {
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ____XX__, XXXXXX__, ________,
+ _XXXXXXX, X___XXX_, ________,
+ ___XXXXX, _____XXX, ________,
+ ___XXXX_, _____XXX, ________,
+ ___XXX__, _____XXX, ________,
+ ___XXX__, _____XXX, ________,
+ ___XXX__, _____XXX, ________,
+ ___XXX__, _____XXX, ________,
+ ___XXX__, _____XXX, ________,
+ ___XXX__, _____XXX, ________,
+ ___XXX__, _____XXX, ________,
+ ___XXX__, _____XXX, ________,
+ ___XXX__, _____XXX, ________,
+ ___XXX__, _____XXX, ________,
+ ___XXX__, _____XXX, ________,
+ _XXXXXXX, ___XXXXX, XX______,
+ ________, ________, ________,
+ ________, ________, ________};
+
+/* char: o code:0x006F */
+static GUI_CONST_STORAGE unsigned char ac006F[96] = {
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ______XX, XXXXX___, ________,
+ _____XXX, ___XXX__, ________,
+ ____XXX_, ____XXX_, ________,
+ ___XXX__, _____XXX, ________,
+ ___XXX__, _____XXX, ________,
+ __XXX___, ______XX, X_______,
+ __XXX___, ______XX, X_______,
+ __XXX___, ______XX, X_______,
+ __XXX___, ______XX, X_______,
+ __XXX___, ______XX, X_______,
+ __XXX___, ______XX, X_______,
+ ___XX___, ______XX, ________,
+ ___XXX__, _____XXX, ________,
+ ____XXX_, ____XXX_, ________,
+ _____XXX, ___XXX__, ________,
+ ______XX, XXXXX___, ________,
+ ________, ________, ________,
+ ________, ________, ________};
+
+/* char: p code:0x0070 */
+static GUI_CONST_STORAGE unsigned char ac0070[96] = {
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ____XX_X, XXXXX___, ________,
+ _XXXXXXX, X___XXX_, ________,
+ ___XXXX_, _____XXX, ________,
+ ___XXX__, _____XXX, ________,
+ ___XXX__, ______XX, X_______,
+ ___XXX__, ______XX, X_______,
+ ___XXX__, ______XX, X_______,
+ ___XXX__, ______XX, X_______,
+ ___XXX__, ______XX, X_______,
+ ___XXX__, ______XX, X_______,
+ ___XXX__, ______XX, X_______,
+ ___XXX__, _____XXX, ________,
+ ___XXX__, _____XXX, ________,
+ ___XXXX_, ____XXX_, ________,
+ ___XXXXX, ___XXX__, ________,
+ ___XXX_X, XXXXX___, ________,
+ ___XXX__, ________, ________,
+ ___XXX__, ________, ________};
+
+/* char: q code:0x0071 */
+static GUI_CONST_STORAGE unsigned char ac0071[96] = {
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ______XX, XXXX__XX, ________,
+ _____XXX, ___XXXXX, ________,
+ ____XXX_, ____XXXX, ________,
+ ___XXX__, _____XXX, ________,
+ ___XXX__, _____XXX, ________,
+ __XXX___, _____XXX, ________,
+ __XXX___, _____XXX, ________,
+ __XXX___, _____XXX, ________,
+ __XXX___, _____XXX, ________,
+ __XXX___, _____XXX, ________,
+ __XXX___, _____XXX, ________,
+ __XXX___, _____XXX, ________,
+ ___XXX__, _____XXX, ________,
+ ___XXX__, ____XXXX, ________,
+ ____XXX_, ___XXXXX, ________,
+ ______XX, XXXX_XXX, ________,
+ ________, _____XXX, ________,
+ ________, _____XXX, ________};
+
+/* char: r code:0x0072 */
+static GUI_CONST_STORAGE unsigned char ac0072[96] = {
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ _____XXX, ___XXXXX, ________,
+ _XXXXXXX, __XX__XX, X_______,
+ _____XXX, XXX___XX, X_______,
+ _____XXX, XX____XX, X_______,
+ _____XXX, X_______, ________,
+ _____XXX, ________, ________,
+ _____XXX, ________, ________,
+ _____XXX, ________, ________,
+ _____XXX, ________, ________,
+ _____XXX, ________, ________,
+ _____XXX, ________, ________,
+ _____XXX, ________, ________,
+ _____XXX, ________, ________,
+ _____XXX, ________, ________,
+ _____XXX, ________, ________,
+ _XXXXXXX, XXXX____, ________,
+ ________, ________, ________,
+ ________, ________, ________};
+
+/* char: s code:0x0073 */
+static GUI_CONST_STORAGE unsigned char ac0073[96] = {
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ _______X, XXXXX_XX, ________,
+ _____XXX, ____XXXX, ________,
+ ____XXX_, _____XXX, ________,
+ ____XXX_, ______XX, ________,
+ ____XXX_, ______XX, ________,
+ ____XXXX, ________, ________,
+ _____XXX, XX______, ________,
+ ______XX, XXXX____, ________,
+ ________, XXXXXX__, ________,
+ ________, ___XXXX_, ________,
+ ________, ____XXXX, ________,
+ ___XX___, _____XXX, ________,
+ ___XX___, _____XXX, ________,
+ ___XXX__, _____XXX, ________,
+ ___XXXXX, ____XXX_, ________,
+ ___XX__X, XXXXX___, ________,
+ ________, ________, ________,
+ ________, ________, ________};
+
+/* char: t code:0x0074 */
+static GUI_CONST_STORAGE unsigned char ac0074[96] = {
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ _______X, X_______, ________,
+ _______X, X_______, ________,
+ _______X, X_______, ________,
+ ______XX, X_______, ________,
+ _____XXX, X_______, ________,
+ __XXXXXX, XXXXXXX_, ________,
+ ______XX, X_______, ________,
+ ______XX, X_______, ________,
+ ______XX, X_______, ________,
+ ______XX, X_______, ________,
+ ______XX, X_______, ________,
+ ______XX, X_______, ________,
+ ______XX, X_______, ________,
+ ______XX, X_______, ________,
+ ______XX, X_______, ________,
+ ______XX, X_______, ________,
+ ______XX, X_______, ________,
+ ______XX, X_____XX, ________,
+ ______XX, X____XX_, ________,
+ _______X, XX___XX_, ________,
+ ________, XXXXXX__, ________,
+ ________, ________, ________,
+ ________, ________, ________};
+
+/* char: u code:0x0075 */
+static GUI_CONST_STORAGE unsigned char ac0075[96] = {
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ____XX__, ______XX, ________,
+ _XXXXX__, ___XXXXX, ________,
+ ___XXX__, _____XXX, ________,
+ ___XXX__, _____XXX, ________,
+ ___XXX__, _____XXX, ________,
+ ___XXX__, _____XXX, ________,
+ ___XXX__, _____XXX, ________,
+ ___XXX__, _____XXX, ________,
+ ___XXX__, _____XXX, ________,
+ ___XXX__, _____XXX, ________,
+ ___XXX__, _____XXX, ________,
+ ___XXX__, _____XXX, ________,
+ ___XXX__, _____XXX, ________,
+ ___XXX__, _____XXX, ________,
+ ___XXX__, ____XXXX, ________,
+ ____XXX_, ___XXXXX, XX______,
+ _____XXX, XXXX_XX_, ________,
+ ________, ________, ________,
+ ________, ________, ________};
+
+/* char: v code:0x0076 */
+static GUI_CONST_STORAGE unsigned char ac0076[96] = {
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ _XXXXXXX, ___XXXXX, X_______,
+ ___XXX__, _____XX_, ________,
+ ___XXX__, _____XX_, ________,
+ ____XXX_, ____XX__, ________,
+ ____XXX_, ____XX__, ________,
+ ____XXX_, ____XX__, ________,
+ _____XXX, ___XX___, ________,
+ _____XXX, ___XX___, ________,
+ _____XXX, __XXX___, ________,
+ ______XX, X_XX____, ________,
+ ______XX, X_XX____, ________,
+ ______XX, XXX_____, ________,
+ _______X, XXX_____, ________,
+ _______X, XXX_____, ________,
+ _______X, XX______, ________,
+ ________, XX______, ________,
+ ________, ________, ________,
+ ________, ________, ________};
+
+/* char: w code:0x0077 */
+static GUI_CONST_STORAGE unsigned char ac0077[96] = {
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ XXXXXX_X, XXXX_XXX, XXX_____,
+ _XXXX___, XXX____X, X_______,
+ __XXX___, XXX____X, X_______,
+ __XXX___, XXX____X, X_______,
+ __XXX___, XXXX__XX, ________,
+ ___XX___, XXXX__XX, ________,
+ ___XXX__, XXXX__XX, ________,
+ ___XXX_X, XXXX__XX, ________,
+ ___XXX_X, X_XXXXX_, ________,
+ ____XX_X, X_XXXXX_, ________,
+ ____XXXX, X_XXXXX_, ________,
+ ____XXXX, __XXXXX_, ________,
+ ____XXXX, ___XXX__, ________,
+ _____XXX, ___XXX__, ________,
+ _____XX_, ___XXX__, ________,
+ _____XX_, ___XX___, ________,
+ ________, ________, ________,
+ ________, ________, ________};
+
+/* char: x code:0x0078 */
+static GUI_CONST_STORAGE unsigned char ac0078[96] = {
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ __XXXXXX, X_XXXXXX, ________,
+ ____XXXX, ____XX__, ________,
+ _____XXX, ___XX___, ________,
+ _____XXX, ___XX___, ________,
+ ______XX, X_XX____, ________,
+ ______XX, XXXX____, ________,
+ _______X, XXX_____, ________,
+ ________, XXX_____, ________,
+ _______X, XXX_____, ________,
+ _______X, XXXX____, ________,
+ ______XX, __XXX___, ________,
+ _____XXX, __XXX___, ________,
+ _____XX_, ___XXX__, ________,
+ ____XX__, ___XXX__, ________,
+ ___XXX__, ____XXX_, ________,
+ _XXXXXX_, __XXXXXX, X_______,
+ ________, ________, ________,
+ ________, ________, ________};
+
+/* char: y code:0x0079 */
+static GUI_CONST_STORAGE unsigned char ac0079[96] = {
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ __XXXXXX, X__XXXXX, XX______,
+ ____XXX_, _____XXX, ________,
+ ____XXX_, _____XX_, ________,
+ _____XXX, _____XX_, ________,
+ _____XXX, ____XXX_, ________,
+ ______XX, ____XX__, ________,
+ ______XX, X___XX__, ________,
+ ______XX, X__XXX__, ________,
+ _______X, XX_XX___, ________,
+ _______X, XX_XX___, ________,
+ _______X, XXXXX___, ________,
+ ________, XXXX____, ________,
+ ________, XXXX____, ________,
+ ________, _XXX____, ________,
+ ________, _XX_____, ________,
+ ________, _XX_____, ________,
+ ________, XX______, ________,
+ ________, XX______, ________};
+
+/* char: z code:0x007A */
+static GUI_CONST_STORAGE unsigned char ac007A[96] = {
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ___XXXXX, XXXXXXXX, ________,
+ __XXXX__, ____XXXX, ________,
+ __XXX___, ___XXXX_, ________,
+ __XX____, ___XXX__, ________,
+ __XX____, __XXX___, ________,
+ ________, _XXXX___, ________,
+ ________, XXXX____, ________,
+ ________, XXX_____, ________,
+ _______X, XX______, ________,
+ ______XX, XX______, ________,
+ _____XXX, X______X, X_______,
+ _____XXX, _______X, X_______,
+ ____XXX_, ______XX, X_______,
+ ___XXX__, ______XX, ________,
+ __XXXX__, ____XXXX, ________,
+ __XXXXXX, XXXXXXXX, ________,
+ ________, ________, ________,
+ ________, ________, ________};
+
+/* char: { code:0x007B */
+static GUI_CONST_STORAGE unsigned char ac007B[96] = {
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, _____XXX, ________,
+ ________, ____XX__, ________,
+ ________, ___XX___, ________,
+ ________, ___XX___, ________,
+ ________, ___XX___, ________,
+ ________, ___XX___, ________,
+ ________, ___XX___, ________,
+ ________, ___XX___, ________,
+ ________, ___XX___, ________,
+ ________, ___XX___, ________,
+ ________, ___XX___, ________,
+ ________, ___XX___, ________,
+ ________, ___XX___, ________,
+ ________, ___XX___, ________,
+ ________, _XXX____, ________,
+ ________, XX______, ________,
+ ________, _XXX____, ________,
+ ________, ___XX___, ________,
+ ________, ___XX___, ________,
+ ________, ___XX___, ________,
+ ________, ___XX___, ________,
+ ________, ___XX___, ________,
+ ________, ___XX___, ________,
+ ________, ___XX___, ________,
+ ________, ___XX___, ________,
+ ________, ___XX___, ________,
+ ________, ___XX___, ________,
+ ________, ___XX___, ________,
+ ________, ___XX___, ________,
+ ________, ____XX__, ________};
+
+/* char: | code:0x007C */
+static GUI_CONST_STORAGE unsigned char ac007C[96] = {
+ ________, XX______, ________,
+ ________, XX______, ________,
+ ________, XX______, ________,
+ ________, XX______, ________,
+ ________, XX______, ________,
+ ________, XX______, ________,
+ ________, XX______, ________,
+ ________, XX______, ________,
+ ________, XX______, ________,
+ ________, XX______, ________,
+ ________, XX______, ________,
+ ________, XX______, ________,
+ ________, XX______, ________,
+ ________, XX______, ________,
+ ________, XX______, ________,
+ ________, XX______, ________,
+ ________, XX______, ________,
+ ________, XX______, ________,
+ ________, XX______, ________,
+ ________, XX______, ________,
+ ________, XX______, ________,
+ ________, XX______, ________,
+ ________, XX______, ________,
+ ________, XX______, ________,
+ ________, XX______, ________,
+ ________, XX______, ________,
+ ________, XX______, ________,
+ ________, XX______, ________,
+ ________, XX______, ________,
+ ________, XX______, ________,
+ ________, XX______, ________,
+ ________, XX______, ________};
+
+/* char: } code:0x007D */
+static GUI_CONST_STORAGE unsigned char ac007D[96] = {
+ ________, ________, ________,
+ ________, ________, ________,
+ ___XXX__, ________, ________,
+ _____XX_, ________, ________,
+ ______XX, ________, ________,
+ ______XX, ________, ________,
+ ______XX, ________, ________,
+ ______XX, ________, ________,
+ ______XX, ________, ________,
+ ______XX, ________, ________,
+ ______XX, ________, ________,
+ ______XX, ________, ________,
+ ______XX, ________, ________,
+ ______XX, ________, ________,
+ ______XX, ________, ________,
+ ______XX, ________, ________,
+ _______X, XX______, ________,
+ ________, XXX_____, ________,
+ _______X, X_______, ________,
+ ______XX, ________, ________,
+ ______XX, ________, ________,
+ ______XX, ________, ________,
+ ______XX, ________, ________,
+ ______XX, ________, ________,
+ ______XX, ________, ________,
+ ______XX, ________, ________,
+ ______XX, ________, ________,
+ ______XX, ________, ________,
+ ______XX, ________, ________,
+ ______XX, ________, ________,
+ ______XX, ________, ________,
+ _____XX_, ________, ________};
+
+/* char: ~ code:0x007E */
+static GUI_CONST_STORAGE unsigned char ac007E[96] = {
+ ___XXXXX, ________, ________,
+ __XX__XX, XX______, ________,
+ _XX____X, XXX_____, XX______,
+ _XX_____, XXXX____, XX______,
+ ________, __XXX__X, X_______,
+ ________, ___XXXXX, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________};
+
+/* char: code:0x007F */
+static GUI_CONST_STORAGE unsigned char ac007F[96] = {
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________,
+ ________, ________, ________};
+
+/* char: 度 code:0xB6C8 */
+static GUI_CONST_STORAGE unsigned char acB6C8[128] = {
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ XX______,
+ ________,
+ ________,
+ ________,
+ _XXX____,
+ ________,
+ ________,
+ ________,
+ _XXXX___,
+ ________,
+ ________,
+ ________,
+ __XXX___,
+ ________,
+ _____XX_,
+ ________,
+ __XXX___,
+ _____XXX,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ ______XX,
+ X_____XX,
+ X______X,
+ XX______,
+ ______XX,
+ X_____XX,
+ X______X,
+ XXX_____,
+ ______XX,
+ X_____XX,
+ X______X,
+ XX______,
+ ______XX,
+ X_____XX,
+ X_______,
+ XX___XXX,
+ ______XX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ ______XX,
+ X_____XX,
+ X_______,
+ XX______,
+ ______XX,
+ ______XX,
+ X_______,
+ XX______,
+ _____XXX,
+ ______XX,
+ X_______,
+ XX______,
+ _____XXX,
+ ______XX,
+ X_______,
+ XX______,
+ _____XXX,
+ ______XX,
+ XXXXXXXX,
+ XX______,
+ _____XXX,
+ ______XX,
+ X_______,
+ XX______,
+ _____XXX,
+ ________,
+ ________,
+ ________,
+ _____XXX,
+ ________,
+ ________,
+ _XXX____,
+ _____XXX,
+ ___XXXXX,
+ XXXXXXXX,
+ XXXXX___,
+ _____XXX,
+ ______XX,
+ ________,
+ XXXX____,
+ _____XXX,
+ _______X,
+ X_______,
+ XXX_____,
+ _____XX_,
+ ________,
+ XX_____X,
+ XX______,
+ ____XXX_,
+ ________,
+ XXX___XX,
+ X_______,
+ ____XXX_,
+ ________,
+ _XXX_XXX,
+ ________,
+ ____XX__,
+ ________,
+ __XXXXX_,
+ ________,
+ ____XX__,
+ ________,
+ ___XXXX_,
+ ________,
+ ___XX___,
+ ________,
+ _XXXXXXX,
+ X_______,
+ ___XX___,
+ _______X,
+ XXX___XX,
+ XXXX____,
+ __XX____,
+ _____XXX,
+ X_______,
+ XXXXXXXX,
+ __XX____,
+ _XXXXX__,
+ ________,
+ __XXXXXX,
+};
+
+/* char: 进 code:0xBDF8 */
+static GUI_CONST_STORAGE unsigned char acBDF8[128] = {
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ _XX_____,
+ XX______,
+ _____XX_,
+ ________,
+ _XXXX___,
+ XXXX____,
+ ______XX,
+ X_______,
+ _XXX____,
+ XXX_____,
+ ______XX,
+ XX______,
+ _XXX____,
+ XXX_____,
+ _______X,
+ XX______,
+ _XXX____,
+ XXX_____,
+ _______X,
+ XXX_____,
+ _XXX____,
+ XXX_____,
+ ________,
+ XX______,
+ _XXX____,
+ XXX__XXX,
+ ________,
+ ___XXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ ________,
+ ________,
+ _XXX____,
+ XXX_____,
+ ________,
+ ________,
+ _XXX____,
+ XXX_____,
+ ________,
+ ________,
+ _XXX____,
+ XXX_____,
+ _______X,
+ XX______,
+ _XXX____,
+ XXX_____,
+ _XXXXXXX,
+ XXX_____,
+ _XXX____,
+ XXX_____,
+ _______X,
+ XX______,
+ _XXX____,
+ XXX_____,
+ _______X,
+ XX______,
+ _XXX____,
+ XXX___XX,
+ _______X,
+ XX_XXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ _______X,
+ XX______,
+ _XXX____,
+ XXX_____,
+ _______X,
+ XX______,
+ _XXX____,
+ XXX_____,
+ _______X,
+ XX______,
+ _XX_____,
+ XXX_____,
+ _______X,
+ XX______,
+ XXX_____,
+ XXX_____,
+ _______X,
+ XX______,
+ XXX_____,
+ XXX_____,
+ _______X,
+ XX_____X,
+ XX______,
+ XXX_____,
+ _______X,
+ XX_____X,
+ X_______,
+ XXX_____,
+ _______X,
+ XX____XX,
+ ________,
+ XXX_____,
+ ______XX,
+ XX___XX_,
+ ________,
+ XXX_____,
+ _____XX_,
+ _XXXXX__,
+ ________,
+ XXX_____,
+ ___XXXX_,
+ __XXX___,
+ ________,
+ XX______,
+ __XXXX__,
+ ____XXXX,
+ X_______,
+ _______X,
+ __XXX___,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ ________,
+ ________,
+ XXXXXXXX,
+ XXXXXXXX,
+};
+
+static GUI_CONST_STORAGE GUI_CHARINFO Cinfo[98] = {
+ {14, 14, 3, (unsigned char *)&ac0020}, /*0: */
+ {12, 12, 3, (unsigned char *)&ac0021}, /*1: !*/
+ {15, 15, 3, (unsigned char *)&ac0022}, /*2: "*/
+ {18, 18, 3, (unsigned char *)&ac0023}, /*3: #*/
+ {16, 16, 3, (unsigned char *)&ac0024}, /*4: $*/
+ {18, 18, 3, (unsigned char *)&ac0025}, /*5: %*/
+ {18, 18, 3, (unsigned char *)&ac0026}, /*6: &*/
+ {7, 7, 3, (unsigned char *)&ac0027}, /*7: '*/
+ {17, 17, 3, (unsigned char *)&ac0028}, /*8: (*/
+ {11, 11, 3, (unsigned char *)&ac0029}, /*9: )*/
+ {17, 17, 3, (unsigned char *)&ac002A}, /*10: **/
+ {18, 18, 3, (unsigned char *)&ac002B}, /*11: +*/
+ {7, 7, 3, (unsigned char *)&ac002C}, /*12: ,*/
+ {17, 17, 3, (unsigned char *)&ac002D}, /*13: -*/
+ {7, 7, 3, (unsigned char *)&ac002E}, /*14: .*/
+ {18, 18, 3, (unsigned char *)&ac002F}, /*15: /*/
+ {17, 17, 3, (unsigned char *)&ac0030}, /*16: 0*/
+ {15, 15, 3, (unsigned char *)&ac0031}, /*17: 1*/
+ {17, 17, 3, (unsigned char *)&ac0032}, /*18: 2*/
+ {17, 17, 3, (unsigned char *)&ac0033}, /*19: 3*/
+ {18, 18, 3, (unsigned char *)&ac0034}, /*20: 4*/
+ {17, 17, 3, (unsigned char *)&ac0035}, /*21: 5*/
+ {17, 17, 3, (unsigned char *)&ac0036}, /*22: 6*/
+ {17, 17, 3, (unsigned char *)&ac0037}, /*23: 7*/
+ {17, 17, 3, (unsigned char *)&ac0038}, /*24: 8*/
+ {17, 17, 3, (unsigned char *)&ac0039}, /*25: 9*/
+ {12, 12, 3, (unsigned char *)&ac003A}, /*26: :*/
+ {11, 11, 3, (unsigned char *)&ac003B}, /*27: ;*/
+ {16, 16, 3, (unsigned char *)&ac003C}, /*28: <*/
+ {17, 17, 3, (unsigned char *)&ac003D}, /*29: =*/
+ {15, 15, 3, (unsigned char *)&ac003E}, /*30: >*/
+ {17, 17, 3, (unsigned char *)&ac003F}, /*31: ?*/
+ {18, 18, 3, (unsigned char *)&ac0040}, /*32: @*/
+ {18, 18, 3, (unsigned char *)&ac0041}, /*33: A*/
+ {18, 18, 3, (unsigned char *)&ac0042}, /*34: B*/
+ {18, 18, 3, (unsigned char *)&ac0043}, /*35: C*/
+ {18, 18, 3, (unsigned char *)&ac0044}, /*36: D*/
+ {18, 18, 3, (unsigned char *)&ac0045}, /*37: E*/
+ {18, 18, 3, (unsigned char *)&ac0046}, /*38: F*/
+ {18, 18, 3, (unsigned char *)&ac0047}, /*39: G*/
+ {18, 18, 3, (unsigned char *)&ac0048}, /*40: H*/
+ {15, 15, 3, (unsigned char *)&ac0049}, /*41: I*/
+ {19, 19, 3, (unsigned char *)&ac004A}, /*42: J*/
+ {18, 18, 3, (unsigned char *)&ac004B}, /*43: K*/
+ {18, 18, 3, (unsigned char *)&ac004C}, /*44: L*/
+ {19, 19, 3, (unsigned char *)&ac004D}, /*45: M*/
+ {18, 18, 3, (unsigned char *)&ac004E}, /*46: N*/
+ {18, 18, 3, (unsigned char *)&ac004F}, /*47: O*/
+ {18, 18, 3, (unsigned char *)&ac0050}, /*48: P*/
+ {18, 18, 3, (unsigned char *)&ac0051}, /*49: Q*/
+ {18, 18, 3, (unsigned char *)&ac0052}, /*50: R*/
+ {17, 17, 3, (unsigned char *)&ac0053}, /*51: S*/
+ {18, 18, 3, (unsigned char *)&ac0054}, /*52: T*/
+ {18, 18, 3, (unsigned char *)&ac0055}, /*53: U*/
+ {18, 18, 3, (unsigned char *)&ac0056}, /*54: V*/
+ {19, 19, 3, (unsigned char *)&ac0057}, /*55: W*/
+ {18, 18, 3, (unsigned char *)&ac0058}, /*56: X*/
+ {18, 18, 3, (unsigned char *)&ac0059}, /*57: Y*/
+ {17, 17, 3, (unsigned char *)&ac005A}, /*58: Z*/
+ {16, 16, 3, (unsigned char *)&ac005B}, /*59: [*/
+ {16, 16, 3, (unsigned char *)&ac005C}, /*60: \*/
+ {12, 12, 3, (unsigned char *)&ac005D}, /*61: ]*/
+ {14, 14, 3, (unsigned char *)&ac005E}, /*62: ^*/
+ {14, 14, 3, (unsigned char *)&ac005F}, /*63: _*/
+ {11, 11, 3, (unsigned char *)&ac0060}, /*64: `*/
+ {18, 18, 3, (unsigned char *)&ac0061}, /*65: a*/
+ {17, 17, 3, (unsigned char *)&ac0062}, /*66: b*/
+ {17, 17, 3, (unsigned char *)&ac0063}, /*67: c*/
+ {18, 18, 3, (unsigned char *)&ac0064}, /*68: d*/
+ {17, 17, 3, (unsigned char *)&ac0065}, /*69: e*/
+ {18, 18, 3, (unsigned char *)&ac0066}, /*70: f*/
+ {18, 18, 3, (unsigned char *)&ac0067}, /*71: g*/
+ {18, 18, 3, (unsigned char *)&ac0068}, /*72: h*/
+ {15, 15, 3, (unsigned char *)&ac0069}, /*73: i*/
+ {16, 16, 3, (unsigned char *)&ac006A}, /*74: j*/
+ {18, 18, 3, (unsigned char *)&ac006B}, /*75: k*/
+ {15, 15, 3, (unsigned char *)&ac006C}, /*76: l*/
+ {18, 18, 3, (unsigned char *)&ac006D}, /*77: m*/
+ {18, 18, 3, (unsigned char *)&ac006E}, /*78: n*/
+ {17, 17, 3, (unsigned char *)&ac006F}, /*79: o*/
+ {17, 17, 3, (unsigned char *)&ac0070}, /*80: p*/
+ {16, 16, 3, (unsigned char *)&ac0071}, /*81: q*/
+ {17, 17, 3, (unsigned char *)&ac0072}, /*82: r*/
+ {16, 16, 3, (unsigned char *)&ac0073}, /*83: s*/
+ {16, 16, 3, (unsigned char *)&ac0074}, /*84: t*/
+ {18, 18, 3, (unsigned char *)&ac0075}, /*85: u*/
+ {17, 17, 3, (unsigned char *)&ac0076}, /*86: v*/
+ {19, 19, 3, (unsigned char *)&ac0077}, /*87: w*/
+ {17, 17, 3, (unsigned char *)&ac0078}, /*88: x*/
+ {18, 18, 3, (unsigned char *)&ac0079}, /*89: y*/
+ {17, 17, 3, (unsigned char *)&ac007A}, /*90: z*/
+ {16, 16, 3, (unsigned char *)&ac007B}, /*91: {*/
+ {10, 10, 3, (unsigned char *)&ac007C}, /*92: |*/
+ {11, 11, 3, (unsigned char *)&ac007D}, /*93: }*/
+ {18, 18, 3, (unsigned char *)&ac007E}, /*94: ~*/
+ {14, 14, 3, (unsigned char *)&ac007F}, /*95: */
+ {32, 32, 4, (unsigned char *)&acB6C8}, /*96: 度*/
+ {32, 32, 4, (unsigned char *)&acBDF8}, /*97: 进*/
+};
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop3 = {
+ 0xBDF8, /*start :进*/
+ 0xBDF8, /*end :进, len=1*/
+ &Cinfo[97],
+ (void *)0};
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop2 = {
+ 0xB6C8, /*start :度*/
+ 0xB6C8, /*end :度, len=1*/
+ &Cinfo[96],
+ &Prop3};
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop1 = {
+ 0x0020, /*start : */
+ 0x007F, /*end :, len=96*/
+ &Cinfo[0],
+ &Prop2};
+
+GUI_CONST_STORAGE GUI_FONT GUI_FontHZ32x32 = {
+ GUI_FONTTYPE_PROP_SJIS,
+ 32, /* height of font */
+ 32, /* space of font y */
+ 1,
+ 1,
+ &Prop1};
diff --git a/User/lib/lcd/font/LOGO.c b/User/lib/lcd/font/LOGO.c
new file mode 100644
index 0000000..b0e5481
--- /dev/null
+++ b/User/lib/lcd/font/LOGO.c
@@ -0,0 +1,10040 @@
+/*
+**********************************************************************
+* UcGUI Font
+* Chinese GB2312 library
+* (c) Copyright 19xx-20xx, company name
+*
+*
+* 注:本字体文件由 ucGUI字体生成器v9.0 生成,作者:馋嘴猫(qq:602426967)
+*
+**********************************************************************
+*/
+
+#include "GUI.H"
+
+/* char: code:0x0030 */
+static GUI_CONST_STORAGE unsigned char ac0030[5000] = {
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XX____XX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXX_,
+ ________,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXX__,
+ ________,
+ __XXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXX___,
+ ________,
+ ___XXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXX____,
+ ________,
+ ___XXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXX_____,
+ ________,
+ ____XXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXX_____,
+ ________,
+ ____XXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXX_____,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXX_____,
+ ________,
+ ________,
+ _XXXXXXX,
+ XXX_____,
+ ________,
+ ____XXXX,
+ XX______,
+ ________,
+ _____XXX,
+ XXX_____,
+ ________,
+ _______X,
+ XXXXXXXX,
+ XXXXX___,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXX____,
+ ________,
+ ________,
+ ________,
+ _XXXXXXX,
+ XXX_____,
+ ________,
+ ____XXXX,
+ XX______,
+ ________,
+ _____XXX,
+ XXX_____,
+ ________,
+ ________,
+ ____XXXX,
+ XXXXXX__,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ XXXXXXXX,
+ XXXXXXXX,
+ X_______,
+ ________,
+ ________,
+ ________,
+ _XXXXXXX,
+ XXX_____,
+ ________,
+ ____XXXX,
+ XX______,
+ ________,
+ _____XXX,
+ XXX_____,
+ ________,
+ ________,
+ _______X,
+ XXXXXXX_,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ XXXXXXXX,
+ XXXXXX__,
+ ________,
+ ________,
+ ________,
+ ________,
+ _XXXXXXX,
+ XX______,
+ ________,
+ ____XXXX,
+ XXX_____,
+ ________,
+ _____XXX,
+ XXX_____,
+ ________,
+ ________,
+ ________,
+ _XXXXXXX,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ XXXXXXXX,
+ XXXX____,
+ ________,
+ ________,
+ ________,
+ ________,
+ _XXXXXXX,
+ XX______,
+ ________,
+ ____XXXX,
+ XXX_____,
+ ________,
+ ____XXXX,
+ XXX_____,
+ ________,
+ ________,
+ ________,
+ ___XXXXX,
+ X_______,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ XXXXXXXX,
+ XXX_____,
+ ________,
+ ________,
+ ________,
+ ________,
+ _XXXXXXX,
+ XX______,
+ ________,
+ ____XXXX,
+ XXX_____,
+ ________,
+ ____XXXX,
+ XXX_____,
+ ________,
+ ________,
+ ________,
+ ____XXXX,
+ XX______,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ XXXXXXXX,
+ X_______,
+ ________,
+ ________,
+ ________,
+ ________,
+ _XXXXXXX,
+ XX______,
+ ________,
+ ____XXXX,
+ XXXX____,
+ ________,
+ ___XXXXX,
+ XX______,
+ ________,
+ ________,
+ ________,
+ _____XXX,
+ XXX_____,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ XXXXXXXX,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ _XXXXXXX,
+ XXX_____,
+ ________,
+ ____XXXX,
+ XXXXX___,
+ ________,
+ ___XXXXX,
+ XX______,
+ ________,
+ ________,
+ ________,
+ ______XX,
+ XXXX____,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ XXXXXXX_,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ _XXXXXXX,
+ XXX_____,
+ ________,
+ _____XXX,
+ XXXXXX__,
+ ________,
+ __XXXXXX,
+ XX______,
+ ________,
+ ________,
+ ________,
+ _______X,
+ XXXXX___,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ XXXXXX__,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ _XXXXXXX,
+ XXX_____,
+ ________,
+ _____XXX,
+ XXXXXXX_,
+ ________,
+ XXXXXXXX,
+ X_______,
+ ________,
+ ________,
+ ________,
+ ________,
+ XXXXX___,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ XXXXX___,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ _XXXXXXX,
+ XXX_____,
+ ________,
+ ______XX,
+ XXXXXXXX,
+ X_____XX,
+ XXXXXXXX,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ XXXXXX__,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ XXXX____,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ _XXXXXXX,
+ XXXX____,
+ ________,
+ _______X,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ _XXXXX__,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ XXXX____,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ _XXXXXXX,
+ XXXX____,
+ ________,
+ _______X,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXX_,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ __XXXXX_,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ XXX_____,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ _XXXXXXX,
+ XXXXX___,
+ ________,
+ ________,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXX__,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ __XXXXX_,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ XXX_____,
+ ________,
+ ________,
+ ___XXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXX___,
+ ________,
+ ________,
+ _XXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXX___,
+ ________,
+ ________,
+ ___XXXXX,
+ XXXXXXXX,
+ XXXX____,
+ ________,
+ _______X,
+ XXXXXXXX,
+ XXXXXXXX,
+ XX______,
+ ________,
+ ________,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXX__,
+ ________,
+ ________,
+ __XXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ ________,
+ ________,
+ ___XXXXX,
+ XXXXXXXX,
+ XXXX____,
+ ________,
+ _______X,
+ XXXXXXXX,
+ XXXXXXXX,
+ XX______,
+ ________,
+ ______XX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXX__,
+ ________,
+ ________,
+ __XXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ X_______,
+ ________,
+ ____XXXX,
+ XXXXXXXX,
+ XXXX____,
+ ________,
+ _______X,
+ XXXXXXXX,
+ XXXXXXXX,
+ X_______,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXX_,
+ ________,
+ ________,
+ ___XXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XX______,
+ ________,
+ ____XXXX,
+ XXXXXXXX,
+ XXXX____,
+ ________,
+ _______X,
+ XXXXXXXX,
+ XXXXXXXX,
+ X_______,
+ ________,
+ ____XXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ ________,
+ ________,
+ ____XXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXX_____,
+ ________,
+ ____XXXX,
+ XXXXXXXX,
+ XXXX____,
+ ________,
+ _______X,
+ XXXXXXXX,
+ XXXXXXXX,
+ X_______,
+ ________,
+ ___XXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ X_______,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXX____,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXX____,
+ ________,
+ _______X,
+ XXXXXXXX,
+ XXXXXXXX,
+ ________,
+ ________,
+ __XXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XX______,
+ ________,
+ ______XX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXX____,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXX____,
+ ________,
+ _______X,
+ XXXXXXXX,
+ XXXXXXXX,
+ ________,
+ ________,
+ __XXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XX______,
+ ________,
+ _______X,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXX___,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXX____,
+ ________,
+ _______X,
+ XXXXXXXX,
+ XXXXXXXX,
+ ________,
+ ________,
+ _XXXXXXX,
+ XX______,
+ ________,
+ ________,
+ _XXXXXXX,
+ XXXXXXXX,
+ XXX_____,
+ ________,
+ _______X,
+ XXXXXXXX,
+ XXXX____,
+ ________,
+ ___XXXXX,
+ XXXXXXXX,
+ XXXXX___,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXX____,
+ ________,
+ _______X,
+ XXXXXXXX,
+ XXXXXXXX,
+ ________,
+ ________,
+ _XXXXXXX,
+ XX______,
+ ________,
+ ________,
+ _XXXXXXX,
+ XXXXXXXX,
+ XXXX____,
+ ________,
+ ________,
+ XXXXXXXX,
+ XXXX____,
+ ________,
+ ___XXXXX,
+ XXXXXXXX,
+ XXXXX___,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXX____,
+ ________,
+ _______X,
+ XXXXXXXX,
+ XXXXXXXX,
+ ________,
+ ________,
+ XXXXXXXX,
+ XX______,
+ ________,
+ ________,
+ _XXXXXXX,
+ XXXXXXXX,
+ XXXXX___,
+ ________,
+ ________,
+ _XXXXXXX,
+ XXXX____,
+ ________,
+ ___XXXXX,
+ XXXXXXXX,
+ XXXXXX__,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXX____,
+ ________,
+ _______X,
+ XXXXXXXX,
+ XXXXXXXX,
+ ________,
+ ________,
+ XXXXXXXX,
+ XX______,
+ ________,
+ ________,
+ _XXXXXXX,
+ XXXXXXXX,
+ XXXXXX__,
+ ________,
+ ________,
+ __XXXXXX,
+ XXXX____,
+ ________,
+ ___XXXXX,
+ XXXXXXXX,
+ XXXXXX__,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXX____,
+ ________,
+ _______X,
+ XXXXXXXX,
+ XXXXXXXX,
+ ________,
+ ________,
+ XXXXXXXX,
+ XX______,
+ ________,
+ ________,
+ _XXXXXXX,
+ XXXXXXXX,
+ XXXXXXX_,
+ ________,
+ ________,
+ __XXXXXX,
+ XXXX____,
+ ________,
+ ___XXXXX,
+ XXXXXXXX,
+ XXXXXX__,
+ ________,
+ ______XX,
+ XXXXXXXX,
+ XXXX____,
+ ________,
+ _______X,
+ XXXXXXXX,
+ XXXXXXXX,
+ ________,
+ ________,
+ XXXXXXXX,
+ XX______,
+ ________,
+ ________,
+ _XXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ ________,
+ ________,
+ ___XXXXX,
+ XXXX____,
+ ________,
+ ___XXXXX,
+ XXXXXXXX,
+ XXXXXX__,
+ ________,
+ ______XX,
+ XXXXXXXX,
+ XXXX____,
+ ________,
+ _______X,
+ XXXXXXXX,
+ XXXXXXXX,
+ ________,
+ ________,
+ XXXXXXXX,
+ XX______,
+ ________,
+ ________,
+ _XXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ ________,
+ ________,
+ ____XXXX,
+ XXXX____,
+ ________,
+ ___XXXXX,
+ XXXXXXXX,
+ XXXXXX__,
+ ________,
+ ______XX,
+ XXXXXXXX,
+ XXXX____,
+ ________,
+ _______X,
+ XXXXXXXX,
+ XXXXXXXX,
+ ________,
+ ________,
+ XXXXXXXX,
+ XX______,
+ ________,
+ ________,
+ _XXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ X_______,
+ ________,
+ ____XXXX,
+ XXXX____,
+ ________,
+ ___XXXXX,
+ XXXXXXXX,
+ XXXXXX__,
+ ________,
+ ______XX,
+ XXXXXXXX,
+ XXXX____,
+ ________,
+ _______X,
+ XXXXXXXX,
+ XXXXXXXX,
+ ________,
+ ________,
+ XXXXXXXX,
+ XX______,
+ ________,
+ ________,
+ _XXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XX______,
+ ________,
+ _____XXX,
+ XXXX____,
+ ________,
+ ___XXXXX,
+ XXXXXXXX,
+ XXXXXX__,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXX____,
+ ________,
+ _______X,
+ XXXXXXXX,
+ XXXXXXXX,
+ ________,
+ ________,
+ XXXXXXXX,
+ XX______,
+ ________,
+ ________,
+ _XXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXX_____,
+ ________,
+ _____XXX,
+ XXXX____,
+ ________,
+ ___XXXXX,
+ XXXXXXXX,
+ XXXXX___,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXX____,
+ ________,
+ _______X,
+ XXXXXXXX,
+ XXXXXXXX,
+ ________,
+ ________,
+ _XXXXXXX,
+ XX______,
+ ________,
+ ________,
+ _XXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXX_____,
+ ________,
+ ______XX,
+ XXXX____,
+ ________,
+ ___XXXXX,
+ XXXXXXXX,
+ XXXXX___,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXX____,
+ ________,
+ _______X,
+ XXXXXXXX,
+ XXXXXXXX,
+ ________,
+ ________,
+ _XXXXXXX,
+ X_______,
+ ________,
+ ________,
+ _XXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXX____,
+ ________,
+ ______XX,
+ XXXX____,
+ ________,
+ ___XXXXX,
+ XXXXXXXX,
+ XXXXX___,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXX____,
+ ________,
+ _______X,
+ XXXXXXXX,
+ XXXXXXXX,
+ X_______,
+ ________,
+ _XXXXXXX,
+ XXXXXXXX,
+ XX______,
+ ________,
+ _XXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXX____,
+ ________,
+ ______XX,
+ XXXX____,
+ ________,
+ ___XXXXX,
+ XXXXXXXX,
+ XXXXX___,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXX____,
+ ________,
+ _______X,
+ XXXXXXXX,
+ XXXXXXXX,
+ X_______,
+ ________,
+ __XXXXXX,
+ XXXXXXXX,
+ XX______,
+ ________,
+ _XXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXX___,
+ ________,
+ ______XX,
+ XXXX____,
+ ________,
+ ___XXXXX,
+ XXXXXXXX,
+ XXXX____,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXX____,
+ ________,
+ _______X,
+ XXXXXXXX,
+ XXXXXXXX,
+ X_______,
+ ________,
+ __XXXXXX,
+ XXXXXXXX,
+ XX______,
+ ________,
+ _XXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXX___,
+ ________,
+ ______XX,
+ XXXX____,
+ ________,
+ ___XXXXX,
+ XXXXXXXX,
+ XXX_____,
+ ________,
+ ____XXXX,
+ XXXXXXXX,
+ XXXX____,
+ ________,
+ _______X,
+ XXXXXXXX,
+ XXXXXXXX,
+ XX______,
+ ________,
+ ___XXXXX,
+ XXXXXXXX,
+ XX______,
+ ________,
+ _XXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXX____,
+ ________,
+ ______XX,
+ XXXX____,
+ ________,
+ ___XXXXX,
+ XXXXXXXX,
+ XXX_____,
+ ________,
+ ____XXXX,
+ XXXXXXXX,
+ XXXX____,
+ ________,
+ _______X,
+ XXXXXXXX,
+ XXXXXXXX,
+ XX______,
+ ________,
+ ____XXXX,
+ XXXXXXXX,
+ XX______,
+ ________,
+ _XXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXX____,
+ ________,
+ ______XX,
+ XXXX____,
+ ________,
+ ___XXXXX,
+ XXXXXXXX,
+ XX______,
+ ________,
+ ____XXXX,
+ XXXXXXXX,
+ XXXX____,
+ ________,
+ _______X,
+ XXXXXXXX,
+ XXXXXXXX,
+ XX______,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XX______,
+ ________,
+ _XXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXX____,
+ ________,
+ ______XX,
+ XXXX____,
+ ________,
+ ___XXXXX,
+ XXXXXXXX,
+ ________,
+ ________,
+ ___XXXXX,
+ XXXXXXXX,
+ XXXX____,
+ ________,
+ _______X,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXX_____,
+ ________,
+ _______X,
+ XXXXXXXX,
+ XX______,
+ ________,
+ _XXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XX______,
+ ________,
+ ______XX,
+ XXXX____,
+ ________,
+ ___XXXXX,
+ XXXXXXX_,
+ ________,
+ ________,
+ ___XXXXX,
+ XXXXXXXX,
+ XXXX____,
+ ________,
+ _______X,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXX_____,
+ ________,
+ ________,
+ _XXXXXXX,
+ XX______,
+ ________,
+ _XXXXXX_,
+ ________,
+ ________,
+ ________,
+ ________,
+ ______XX,
+ XXXX____,
+ ________,
+ ___XXXXX,
+ XX______,
+ ________,
+ ________,
+ __XXXXXX,
+ XXXXXXXX,
+ XXXX____,
+ ________,
+ _______X,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXX____,
+ ________,
+ ________,
+ _____XXX,
+ XX______,
+ ________,
+ _XXXXXX_,
+ ________,
+ ________,
+ ________,
+ ________,
+ ______XX,
+ XXXX____,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ __XXXXXX,
+ XXXXXXXX,
+ XXXX____,
+ ________,
+ _______X,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXX___,
+ ________,
+ ________,
+ ______XX,
+ XX______,
+ ________,
+ _XXXXXX_,
+ ________,
+ ________,
+ ________,
+ ________,
+ ______XX,
+ XXXX____,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ _XXXXXXX,
+ XXXXXXXX,
+ XXXX____,
+ ________,
+ _______X,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXX___,
+ ________,
+ ________,
+ ______XX,
+ XX______,
+ ________,
+ _XXXXXX_,
+ ________,
+ ________,
+ ________,
+ ________,
+ _____XXX,
+ XXXX____,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ _XXXXXXX,
+ XXXXXXXX,
+ XXXX____,
+ ________,
+ _______X,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXX__,
+ ________,
+ ________,
+ ______XX,
+ XX______,
+ ________,
+ _XXXXXX_,
+ ________,
+ ________,
+ ________,
+ ________,
+ _____XXX,
+ XXXX____,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXX____,
+ ________,
+ _______X,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXX_,
+ ________,
+ ________,
+ ______XX,
+ XX______,
+ ________,
+ _XXXXXX_,
+ ________,
+ ________,
+ ________,
+ ________,
+ ____XXXX,
+ XXXX____,
+ ________,
+ ________,
+ ________,
+ ________,
+ _______X,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXX____,
+ ________,
+ _______X,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ ________,
+ ________,
+ ______XX,
+ XX______,
+ ________,
+ _XXXXXX_,
+ ________,
+ ________,
+ ________,
+ ________,
+ ___XXXXX,
+ XXXX____,
+ ________,
+ ________,
+ ________,
+ ________,
+ _______X,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXX____,
+ ________,
+ _______X,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ X_______,
+ ________,
+ ______XX,
+ XX______,
+ ________,
+ _XXXXXX_,
+ ________,
+ ________,
+ ________,
+ ________,
+ ___XXXXX,
+ XXXX____,
+ ________,
+ ________,
+ ________,
+ ________,
+ ______XX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXX____,
+ ________,
+ _______X,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XX______,
+ ________,
+ ______XX,
+ XX______,
+ ________,
+ _XXXXXX_,
+ ________,
+ ________,
+ ________,
+ ________,
+ __XXXXXX,
+ XXXX____,
+ ________,
+ ________,
+ ________,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXX____,
+ ________,
+ _______X,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXX____,
+ ________,
+ ______XX,
+ XX______,
+ ________,
+ _XXXXXX_,
+ ________,
+ ________,
+ ________,
+ ________,
+ XXXXXXXX,
+ XXXX____,
+ ________,
+ ________,
+ ________,
+ ________,
+ ___XXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXX____,
+ ________,
+ _______X,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXX___,
+ ________,
+ ______XX,
+ XX______,
+ ________,
+ XXXXXXX_,
+ ________,
+ ________,
+ ________,
+ _______X,
+ XXXXXXXX,
+ XXXX____,
+ ________,
+ ________,
+ ________,
+ ________,
+ __XXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXX____,
+ ________,
+ _______X,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXX_,
+ ________,
+ ______XX,
+ XX______,
+ _______X,
+ XXXXXXX_,
+ ________,
+ ________,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXX____,
+ ________,
+ ________,
+ ________,
+ ________,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXX____,
+ ________,
+ _______X,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XX______,
+ ______XX,
+ XX______,
+ _____XXX,
+ XXXXXXX_,
+ ________,
+ ________,
+ ________,
+ ___XXXXX,
+ XXXXXXXX,
+ XXXX____,
+ ________,
+ ________,
+ ________,
+ ______XX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXX____,
+ ________,
+ _______X,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXX___,
+ ______XX,
+ XX______,
+ __XXXXXX,
+ XXXXXX__,
+ ________,
+ ________,
+ ________,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXX____,
+ ________,
+ ________,
+ ________,
+ __XXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXX____,
+ ________,
+ _______X,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XX____XX,
+ XX____XX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+};
+
+/* char: code:0x0031 */
+static GUI_CONST_STORAGE unsigned char ac0031[5000] = {
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXX____,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ __XXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XX______,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ___XXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ X_______,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ____XXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ X_______,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ X_______,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ ________,
+ ____XXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ X_______,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ ________,
+ ____XXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ X_______,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ ________,
+ ____XXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ X_______,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ ________,
+ ____XXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ X_______,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ ________,
+ ____XXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ X_______,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ ________,
+ ____XXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ X_______,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ ________,
+ ____XXXX,
+ XXXX____,
+ ________,
+ ____XXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ X_______,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ ________,
+ ____XXXX,
+ XXXX____,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ X_______,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ ________,
+ ____XXXX,
+ XXX_____,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ X_______,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ ________,
+ ____XXXX,
+ XXX_____,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ X_______,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ ________,
+ ____XXXX,
+ XXX_____,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ X_______,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ ________,
+ ____XXXX,
+ XXX_____,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ X_______,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ ________,
+ ____XXXX,
+ XXX_____,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ X_______,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ ________,
+ ____XXXX,
+ XXX_____,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ X_______,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ ________,
+ ____XXXX,
+ XXX_____,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ X_______,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ ________,
+ ____XXXX,
+ XXX_____,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ X_______,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ ________,
+ ____XXXX,
+ XXX_____,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ X_______,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ ________,
+ ____XXXX,
+ XXX_____,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ X_______,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ ________,
+ ____XXXX,
+ XXX_____,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ X_______,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ ________,
+ ____XXXX,
+ XXX_____,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ X_______,
+ _____XXX,
+ XXXX_XXX,
+ XXXXXXXX,
+ ________,
+ ____XXXX,
+ XXX_____,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ X_______,
+ _____XXX,
+ XXXX___X,
+ XXXXXXXX,
+ ________,
+ ____XXXX,
+ XXX_____,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ X_______,
+ _____XXX,
+ XXXX____,
+ _XXXXXXX,
+ ________,
+ ____XXXX,
+ XXX_____,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ X_______,
+ _____XXX,
+ XXXX____,
+ ___XXXXX,
+ ________,
+ ____XXXX,
+ XXX_____,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ X_______,
+ _____XXX,
+ XXXX____,
+ ____XXXX,
+ ________,
+ ____XXXX,
+ XXX_____,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ X_______,
+ _____XXX,
+ XXXX____,
+ ______XX,
+ ________,
+ ____XXXX,
+ XXX_____,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ X_______,
+ _____XXX,
+ XXXX____,
+ ________,
+ ________,
+ ____XXXX,
+ XXX_____,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ X_______,
+ _____XXX,
+ XXXX____,
+ ________,
+ ________,
+ ____XXXX,
+ XXX_____,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ X_______,
+ _____XXX,
+ XXXX____,
+ ________,
+ ________,
+ ____XXXX,
+ XXX_____,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ X_______,
+ _____XXX,
+ XXXX____,
+ ________,
+ ________,
+ ____XXXX,
+ XXX_____,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ X_______,
+ _____XXX,
+ XXXX____,
+ ________,
+ ________,
+ ____XXXX,
+ XXX_____,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ X_______,
+ _____XXX,
+ XXXX____,
+ ________,
+ ________,
+ ____XXXX,
+ XXX_____,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ X_______,
+ _____XXX,
+ XXXX____,
+ ________,
+ ________,
+ ____XXXX,
+ XXX_____,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ X_______,
+ _____XXX,
+ XXXX____,
+ ________,
+ ________,
+ ____XXXX,
+ XXX_____,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ X_______,
+ _____XXX,
+ XXXX____,
+ ________,
+ ________,
+ ____XXXX,
+ XXX_____,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ X_______,
+ _____XXX,
+ XXXX____,
+ ________,
+ ________,
+ ____XXXX,
+ XXX_____,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ X_______,
+ _____XXX,
+ XXXX____,
+ ________,
+ ________,
+ ____XXXX,
+ XXX_____,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ X_______,
+ _____XXX,
+ XXXX____,
+ ________,
+ ________,
+ ____XXXX,
+ XXX_____,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ X_______,
+ _____XXX,
+ XXXX____,
+ ________,
+ ________,
+ ____XXXX,
+ XXX_____,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ X_______,
+ _____XXX,
+ XXXX____,
+ ________,
+ ________,
+ ____XXXX,
+ XXX_____,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ X_______,
+ _____XXX,
+ XXXX____,
+ ________,
+ ________,
+ ____XXXX,
+ XXX_____,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ X_______,
+ _____XXX,
+ XXXX____,
+ ________,
+ ________,
+ ____XXXX,
+ XXX_____,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ X_______,
+ _____XXX,
+ XXXX____,
+ ________,
+ ________,
+ ____XXXX,
+ XXX_____,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ X_______,
+ _____XXX,
+ XXXX____,
+ ________,
+ ________,
+ ____XXXX,
+ XXX_____,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ X_______,
+ _____XXX,
+ XXXX____,
+ ________,
+ ________,
+ ____XXXX,
+ XXX_____,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ X_______,
+ _____XXX,
+ XXXX____,
+ ________,
+ ________,
+ ____XXXX,
+ XXX_____,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ X_______,
+ _____XXX,
+ XXXX____,
+ ________,
+ ________,
+ ____XXXX,
+ XXX_____,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ X_______,
+ _____XXX,
+ XXXX____,
+ ________,
+ ________,
+ ____XXXX,
+ XXX_____,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ X_______,
+ _____XXX,
+ XXXX____,
+ ________,
+ ________,
+ ____XXXX,
+ XXX_____,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ X_______,
+ _____XXX,
+ XXXX____,
+ ________,
+ ________,
+ ____XXXX,
+ XXX_____,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ X_______,
+ _____XXX,
+ XXXX____,
+ ________,
+ ________,
+ ____XXXX,
+ XXX_____,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ X_______,
+ _____XXX,
+ XXXX____,
+ ________,
+ ________,
+ ____XXXX,
+ XXX_____,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ X_______,
+ _____XXX,
+ XXXX____,
+ ________,
+ ________,
+ ____XXXX,
+ XXX_____,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ X_______,
+ _____XXX,
+ XXXX____,
+ ________,
+ ________,
+ ____XXXX,
+ XXX_____,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ X_______,
+ _____XXX,
+ XXXX____,
+ ________,
+ ________,
+ ____XXXX,
+ XXX_____,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ X_______,
+ _____XXX,
+ XXXX____,
+ ________,
+ ________,
+ ____XXXX,
+ XXX_____,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ X_______,
+ _____XXX,
+ XXXX____,
+ ________,
+ ________,
+ ____XXXX,
+ XXX_____,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ X_______,
+ _____XXX,
+ XXXX____,
+ ________,
+ ________,
+ ____XXXX,
+ XXX_____,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ X_______,
+ _____XXX,
+ XXXX____,
+ ________,
+ ________,
+ ____XXXX,
+ XXX_____,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ X_______,
+ _____XXX,
+ XXXX____,
+ ________,
+ ________,
+ ____XXXX,
+ XXX_____,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ X_______,
+ _____XXX,
+ XXXX____,
+ ________,
+ ________,
+ ____XXXX,
+ XXX_____,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ X_______,
+ _____XXX,
+ XXXX____,
+ ________,
+ ________,
+ ____XXXX,
+ XXX_____,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ X_______,
+ _____XXX,
+ XXXX____,
+ ______XX,
+ ________,
+ ____XXXX,
+ XXX_____,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ X_______,
+ _____XXX,
+ XXXX____,
+ ____XXXX,
+ ________,
+ ____XXXX,
+ XXX_____,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ X_______,
+ _____XXX,
+ XXXX____,
+ ___XXXXX,
+ ________,
+ ____XXXX,
+ XXX_____,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ X_______,
+ _____XXX,
+ XXXX____,
+ _XXXXXXX,
+ ________,
+ ____XXXX,
+ XXX_____,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ X_______,
+ _____XXX,
+ XXXX___X,
+ XXXXXXXX,
+ ________,
+ ____XXXX,
+ XXX_____,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ X_______,
+ _____XXX,
+ XXXX_XXX,
+ XXXXXXXX,
+ ________,
+ ____XXXX,
+ XXX_____,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ X_______,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ ________,
+ ____XXXX,
+ XXX_____,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ X_______,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ ________,
+ ____XXXX,
+ XXX_____,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ X_______,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ ________,
+ ____XXXX,
+ XXX_____,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ X_______,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ ________,
+ ____XXXX,
+ XXX_____,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ X_______,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ ________,
+ ____XXXX,
+ XXX_____,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ X_______,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ ________,
+ ____XXXX,
+ XXX_____,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ X_______,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ ________,
+ ____XXXX,
+ XXX_____,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ X_______,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ ________,
+ ____XXXX,
+ XXX_____,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ X_______,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ ________,
+ ____XXXX,
+ XXX_____,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ X_______,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ ________,
+ ____XXXX,
+ XXX_____,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ X_______,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ ________,
+ ____XXXX,
+ XXXX____,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ X_______,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ ________,
+ ____XXXX,
+ XXXX____,
+ ________,
+ ____XXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ X_______,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ ________,
+ ____XXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ X_______,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ ________,
+ ____XXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ X_______,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ ________,
+ ____XXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ X_______,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ ________,
+ ____XXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ X_______,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ ________,
+ ____XXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ X_______,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ ________,
+ ____XXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ X_______,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ X_______,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ X_______,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ _____XXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ X_______,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ____XXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XX______,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ___XXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXX____,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ ________,
+ __XXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+ XXXXXXXX,
+};
+
+static GUI_CONST_STORAGE GUI_CHARINFO Cinfo[2] = {
+ {200, 200, 25, (unsigned char *)&ac0030}, /*0: */
+ {200, 200, 25, (unsigned char *)&ac0031}, /*1: */
+};
+
+static GUI_CONST_STORAGE GUI_FONT_PROP Prop1 = {
+ 0x0030, /*start :*/
+ 0x0031, /*end :, len=2*/
+ &Cinfo[0],
+ (void *)0};
+
+GUI_CONST_STORAGE GUI_FONT GUI_FontHZ200x200 = {
+ GUI_FONTTYPE_PROP_SJIS,
+ 200, /* height of font */
+ 200, /* space of font y */
+ 1,
+ 1,
+ &Prop1};
diff --git a/User/lib/lcd/gui/Core/GUI.h b/User/lib/lcd/gui/Core/GUI.h
index cb12354..185106c 100644
--- a/User/lib/lcd/gui/Core/GUI.h
+++ b/User/lib/lcd/gui/Core/GUI.h
@@ -306,6 +306,7 @@ extern "C"
extern GUI_CONST_STORAGE GUI_FONT GUI_FontHZ18x18;
extern GUI_CONST_STORAGE GUI_FONT GUI_FontHZ20x20;
extern GUI_CONST_STORAGE GUI_FONT GUI_FontHZ24x24;
+ extern GUI_CONST_STORAGE GUI_FONT GUI_FontHZ32x32;
/* Proportional fonts */
extern GUI_CONST_STORAGE GUI_FONT GUI_Font8_ASCII, GUI_Font8_1;
diff --git a/User/lib/lcd/gui/Core/GUI2DLib.c b/User/lib/lcd/gui/Core/GUI2DLib.c
index 5f24e38..bc67448 100644
--- a/User/lib/lcd/gui/Core/GUI2DLib.c
+++ b/User/lib/lcd/gui/Core/GUI2DLib.c
@@ -17,30 +17,31 @@ Purpose : Main part of the 2D graphics library
---------------------------END-OF-HEADER------------------------------
*/
-#include /* needed for definition of NULL */
+#include /* needed for definition of NULL */
#include "GUI_Protected.h"
#include "GUIDebug.h"
/*********************************************************************
-*
-* defines
-*
-**********************************************************************
-*/
+ *
+ * defines
+ *
+ **********************************************************************
+ */
-#define ABS(v) ((v>0) ? v : -v)
+#define ABS(v) ((v > 0) ? v : -v)
/*********************************************************************
-*
-* static code, helper functions
-*
-**********************************************************************
-*/
+ *
+ * static code, helper functions
+ *
+ **********************************************************************
+ */
/*********************************************************************
-*
-* _SwapInt
-*/
-static void _SwapInt(int* pa, int* pb) {
+ *
+ * _SwapInt
+ */
+static void _SwapInt(int *pa, int *pb)
+{
int t;
t = *pa;
*pa = *pb;
@@ -48,73 +49,77 @@ static void _SwapInt(int* pa, int* pb) {
}
/*********************************************************************
-*
-* Abs
-*/
-static int Abs(int v) {
+ *
+ * Abs
+ */
+static int Abs(int v)
+{
return ABS(v);
}
/*********************************************************************
-*
-* trigonometric functions
-*
-* NOTE:
-* All trigonometric functions are for internal usage only and
-* use the following conventions:
-*
-* Angles: 4096 <==> 360
-*
-**********************************************************************
-*/
+ *
+ * trigonometric functions
+ *
+ * NOTE:
+ * All trigonometric functions are for internal usage only and
+ * use the following conventions:
+ *
+ * Angles: 4096 <==> 360
+ *
+ **********************************************************************
+ */
#if GUI_45DEG != 512
- #error Wrong define for this library !
+#error Wrong define for this library !
#endif
/*********************************************************************
-*
-* sin / cos (internal)
-*
-* Angle : 90/1024
-* Data : 1/1024
-*/
+ *
+ * sin / cos (internal)
+ *
+ * Angle : 90/1024
+ * Data : 1/1024
+ */
static const U16 aSin[] = {
- 0, /* 1/16 *90 */
- 100, /* 1/16 *90 */
- 200, /* 2/16 *90 */
- 297, /* 3/16 *90 */
- 392, /* 4/16 *90 */
- 483, /* 5/16 *90 */
- 569, /* 6/16 *90 */
- 650, /* 7/16 *90 */
- 724, /* 8/16 *90 */
- 792, /* 9/16 *90 */
- 851, /* 10/16 *90 */
- 903, /* 11/16 *90 */
- 946, /* 12/16 *90 */
- 980, /* 13/16 *90 */
- 1004, /* 14/16 *90 */
- 1019, /* 15/16 *90 */
- 1024 /* 16/16 *90 */
+ 0, /* 1/16 *90 */
+ 100, /* 1/16 *90 */
+ 200, /* 2/16 *90 */
+ 297, /* 3/16 *90 */
+ 392, /* 4/16 *90 */
+ 483, /* 5/16 *90 */
+ 569, /* 6/16 *90 */
+ 650, /* 7/16 *90 */
+ 724, /* 8/16 *90 */
+ 792, /* 9/16 *90 */
+ 851, /* 10/16 *90 */
+ 903, /* 11/16 *90 */
+ 946, /* 12/16 *90 */
+ 980, /* 13/16 *90 */
+ 1004, /* 14/16 *90 */
+ 1019, /* 15/16 *90 */
+ 1024 /* 16/16 *90 */
};
/*********************************************************************
-*
-* GUI_sin
-*/
-int GUI_sin(int angle) {
- char IsNeg =0;
+ *
+ * GUI_sin
+ */
+int GUI_sin(int angle)
+{
+ char IsNeg = 0;
int i;
- U16 Faktor;
+ U16 Faktor;
U32 t;
- angle &= ((1<<12)-1); /* reduce to 0-360 degrees */
- if (angle> 2* GUI_90DEG) {
- angle -= 2* GUI_90DEG;
- IsNeg =1;
+ angle &= ((1 << 12) - 1); /* reduce to 0-360 degrees */
+ if (angle > 2 * GUI_90DEG)
+ {
+ angle -= 2 * GUI_90DEG;
+ IsNeg = 1;
}
- if (angle> GUI_90DEG) { /* between 90-180 */
- angle = 2*GUI_90DEG-angle; /* use sine symetry */
+ if (angle > GUI_90DEG)
+ { /* between 90-180 */
+ angle = 2 * GUI_90DEG - angle; /* use sine symetry */
}
/* Now angle is reduced to 0 <= <= 90 */
#if 0
@@ -127,149 +132,162 @@ int GUI_sin(int angle) {
}
r = (r+(1<<3)) >>4; /* divide,incl. rounding */
#else
- i = angle>>6;
+ i = angle >> 6;
{
- Faktor = (U16)((1<<6)-(angle&((1<<6)-1)));
- t = aSin[i]*(U32)Faktor;
- if (Faktor !=(1<<6)) {
- t += aSin[i+1]*((1<<6)-Faktor);
+ Faktor = (U16)((1 << 6) - (angle & ((1 << 6) - 1)));
+ t = aSin[i] * (U32)Faktor;
+ if (Faktor != (1 << 6))
+ {
+ t += aSin[i + 1] * ((1 << 6) - Faktor);
}
- }
- t = (t+(1<<5)) >>6; /* divide,incl. rounding */
+ }
+ t = (t + (1 << 5)) >> 6; /* divide,incl. rounding */
#endif
- return (IsNeg) ? 0-t : t;
+ return (IsNeg) ? 0 - t : t;
}
/*********************************************************************
-*
-* GUI_cos
-*/
-int GUI_cos(int angle) {
- return GUI_sin(angle+GUI_90DEG);
+ *
+ * GUI_cos
+ */
+int GUI_cos(int angle)
+{
+ return GUI_sin(angle + GUI_90DEG);
}
/*********************************************************************
-*
-* atan() (internal)
-*
-* Angle : 360/4096
-*/
+ *
+ * atan() (internal)
+ *
+ * Angle : 360/4096
+ */
const I16 aTan[] = {
- 0, /* atan(0/16) */
- 41, /* atan(1/16) */
- 81, /* atan(2/16) */
- 121, /* atan(3/16) */
- 160, /* atan(4/16) */
- 197, /* atan(5/16) */
- 234, /* atan(6/16) */
- 269, /* atan(7/16) */
- 302, /* atan(8/16) */
- 334, /* atan(9/16) */
- 364, /* atan(10/16) */
- 393, /* atan(11/16) */
- 419, /* atan(12/16) */
- 445, /* atan(13/16) */
- 469, /* atan(14/16) */
- 491, /* atan(15/16) */
- 512 /* atan(1) = 45 = 512/1024 */
+ 0, /* atan(0/16) */
+ 41, /* atan(1/16) */
+ 81, /* atan(2/16) */
+ 121, /* atan(3/16) */
+ 160, /* atan(4/16) */
+ 197, /* atan(5/16) */
+ 234, /* atan(6/16) */
+ 269, /* atan(7/16) */
+ 302, /* atan(8/16) */
+ 334, /* atan(9/16) */
+ 364, /* atan(10/16) */
+ 393, /* atan(11/16) */
+ 419, /* atan(12/16) */
+ 445, /* atan(13/16) */
+ 469, /* atan(14/16) */
+ 491, /* atan(15/16) */
+ 512 /* atan(1) = 45 = 512/1024 */
};
/*********************************************************************
-*
-* _atan0_45
-*
-* Calculate arctan of q, where q is any where between 0 and 1024
-*/
-static int _atan0_45(int q) {
+ *
+ * _atan0_45
+ *
+ * Calculate arctan of q, where q is any where between 0 and 1024
+ */
+static int _atan0_45(int q)
+{
int r;
int i, Faktor;
/* Now angle is reduced to 0 <= <= 90 ==> 0 <= <= 256*/
- q >>=2; /* make sure we do not exceed 16 bits in calculations */
- i = q>>4;
- Faktor = (1<<4)-(q&((1<<4)-1));
- r = aTan[i]*Faktor;
- if (Faktor !=(1<<4)) {
- r += aTan[i+1]*((1<<4)-Faktor);
+ q >>= 2; /* make sure we do not exceed 16 bits in calculations */
+ i = q >> 4;
+ Faktor = (1 << 4) - (q & ((1 << 4) - 1));
+ r = aTan[i] * Faktor;
+ if (Faktor != (1 << 4))
+ {
+ r += aTan[i + 1] * ((1 << 4) - Faktor);
}
- r = (r+(1<<3))/(1<<4); /* divide incl. rounding */
+ r = (r + (1 << 3)) / (1 << 4); /* divide incl. rounding */
return r;
}
/*********************************************************************
-*
-* _atan2
-*/
-static int _atan2(I32 x, I32 y) {
- U8 q =0;
+ *
+ * _atan2
+ */
+static int _atan2(I32 x, I32 y)
+{
+ U8 q = 0;
int angle;
-/* first make sure we are in angle between 0 and 45 */
- if (x<0) {
- q=1;
- x=-x;
+ /* first make sure we are in angle between 0 and 45 */
+ if (x < 0)
+ {
+ q = 1;
+ x = -x;
}
- if (y<0) {
- q |= (1<<1);
- y=-y;
+ if (y < 0)
+ {
+ q |= (1 << 1);
+ y = -y;
}
- if (y>x) {
+ if (y > x)
+ {
int t = y;
- y=x;
- x=t;
- q |= (1<<2);
+ y = x;
+ x = t;
+ q |= (1 << 2);
}
- y <<=10;
- y += (x/2);
+ y <<= 10;
+ y += (x / 2);
y /= x;
angle = _atan0_45(y);
- if (q&(1<<2)) { /* y/x reverse ? */
- angle = GUI_90DEG-angle;
+ if (q & (1 << 2))
+ { /* y/x reverse ? */
+ angle = GUI_90DEG - angle;
}
- if (q&1) { /* xreverse ? */
- angle = GUI_180DEG-angle;
+ if (q & 1)
+ { /* xreverse ? */
+ angle = GUI_180DEG - angle;
}
- if (q&(1<<1)) { /* y-reverse ? */
- angle = GUI_360DEG-angle;
+ if (q & (1 << 1))
+ { /* y-reverse ? */
+ angle = GUI_360DEG - angle;
}
return angle;
}
/*********************************************************************
-*
-* _SetLineColor
-*/
-static int _SetLineColor(int i) {
- switch (GUI_Context.LineStyle) {
+ *
+ * _SetLineColor
+ */
+static int _SetLineColor(int i)
+{
+ switch (GUI_Context.LineStyle)
+ {
case GUI_LS_DASH:
- i = (i+6)%16;
- return (i<12);
+ i = (i + 6) % 16;
+ return (i < 12);
case GUI_LS_DOT:
i %= 4;
- return (i<2);
+ return (i < 2);
case GUI_LS_DASHDOT:
i %= 20;
- if (i<12)
+ if (i < 12)
return 1;
- else if ((i>=16) && (i<18))
+ else if ((i >= 16) && (i < 18))
return 1;
return 0;
case GUI_LS_DASHDOTDOT:
i %= 24;
- if (i<12)
+ if (i < 12)
return 1;
- else if ((i>=16) && (i<18))
+ else if ((i >= 16) && (i < 18))
return 1;
- else if ((i>=20) && (i<22))
+ else if ((i >= 20) && (i < 22))
return 1;
- else
+ else
return 0;
}
return 0;
}
/*********************************************************************
-*
-* _atan2
-*/
+ *
+ * _atan2
+ */
#if 0
int _atan2(int xDiff, int yDiff) {
double atanf = atan2(xDiff, yDiff);
@@ -278,11 +296,12 @@ int _atan2(int xDiff, int yDiff) {
#endif
/*********************************************************************
-*
-* _CalcOrto
-*/
-static void _CalcOrto(int xDiff, int yDiff, I32 r, int*px, int*py) {
- I32 x,y;
+ *
+ * _CalcOrto
+ */
+static void _CalcOrto(int xDiff, int yDiff, I32 r, int *px, int *py)
+{
+ I32 x, y;
/*
int Angle = _atan2(xDiff, yDiff);
*/
@@ -292,33 +311,35 @@ static void _CalcOrto(int xDiff, int yDiff, I32 r, int*px, int*py) {
y = (int)(r*sin(Angle));
#else
int Angle = _atan2(xDiff, yDiff);
- Angle+= GUI_90DEG;
- x = ( r*(I32)GUI_cos(Angle));
- y = ( r*(I32)GUI_sin(Angle));
+ Angle += GUI_90DEG;
+ x = (r * (I32)GUI_cos(Angle));
+ y = (r * (I32)GUI_sin(Angle));
#endif
- x = (x<0) ? -((-x+512)>>10) : ((x+512)>>10);
- y = (y<0) ? -((-y+512)>>10) : ((y+512)>>10);
+ x = (x < 0) ? -((-x + 512) >> 10) : ((x + 512) >> 10);
+ y = (y < 0) ? -((-y + 512) >> 10) : ((y + 512) >> 10);
*px = x;
*py = y;
}
/*********************************************************************
-*
-* DrawLine, public
-*
-* Draw end points of the line.
-* In most cases, this is a circle.
-*
-**********************************************************************
-*/
+ *
+ * DrawLine, public
+ *
+ * Draw end points of the line.
+ * In most cases, this is a circle.
+ *
+ **********************************************************************
+ */
/*********************************************************************
-*
-* _DrawLineEnd
-*/
-static void _DrawLineEnd(int x0, int y0) {
- switch (GUI_Context.PenShape) {
+ *
+ * _DrawLineEnd
+ */
+static void _DrawLineEnd(int x0, int y0)
+{
+ switch (GUI_Context.PenShape)
+ {
case GUI_PS_ROUND:
- GL_DrawPoint(x0,y0);
+ GL_DrawPoint(x0, y0);
break;
case GUI_PS_FLAT:
break;
@@ -326,184 +347,219 @@ static void _DrawLineEnd(int x0, int y0) {
}
/*********************************************************************
-*
-* DrawLine, public
-*
-**********************************************************************
-*/
-/*********************************************************************
-*
-* GL_DrawLine
-*/
-void GL_DrawLine(int x0, int y0, int x1, int y1) {
- if (GUI_Context.PenSize ==1) {
- GL_DrawLine1(x0,y0,x1,y1);
- } else {
+ *
+ * DrawLine, public
+ *
+ **********************************************************************
+ */
+
+/**
+ * @brief ????
+ *
+ * ????????????????????
+ *
+ * @param x0 ?????
+ * @param y0 ?????
+ * @param x1 ?????
+ * @param y1 ?????
+ */
+void GL_DrawLine(int x0, int y0, int x1, int y1)
+{
+ if (GUI_Context.PenSize == 1)
+ {
+ GL_DrawLine1(x0, y0, x1, y1);
+ }
+ else
+ {
int xdiff, ydiff;
- xdiff = x0-x1;
- ydiff = y0-y1;
- if (xdiff | ydiff) {
+ xdiff = x0 - x1;
+ ydiff = y0 - y1;
+ if (xdiff | ydiff)
+ {
GUI_POINT Poly[4];
int xOff, yOff;
int xOffP, yOffP, xOffM, yOffM;
- _CalcOrto(x0-x1,y0-y1, (I32)(GUI_Context.PenSize-1), &xOff, &yOff);
- /* Do rounding for offsets */
- if (xOff >0) {
- xOffP = (xOff+1)/2;
- xOffM = xOff /2;
- } else {
- xOffP = xOff/2;
- xOffM = (xOff-1) /2;
+ _CalcOrto(x0 - x1, y0 - y1, (I32)(GUI_Context.PenSize - 1), &xOff, &yOff);
+ /* Do rounding for offsets */
+ if (xOff > 0)
+ {
+ xOffP = (xOff + 1) / 2;
+ xOffM = xOff / 2;
}
- if (yOff >0) {
- yOffP = (yOff+1)/2;
- yOffM = yOff /2;
- } else {
- yOffP = yOff/2;
- yOffM = (yOff-1) /2;
+ else
+ {
+ xOffP = xOff / 2;
+ xOffM = (xOff - 1) / 2;
}
- Poly[0].x = x0+xOffP;
- Poly[0].y = y0+yOffP;
- Poly[1].x = x0-xOffM;
- Poly[1].y = y0-yOffM;
- Poly[2].x = x1-xOffM;
- Poly[2].y = y1-yOffM;
- Poly[3].x = x1+xOffP;
- Poly[3].y = y1+yOffP;
- GL_FillPolygon(&Poly[0], 4, 0,0);
- _DrawLineEnd(x0,y0);
- _DrawLineEnd(x1,y1);
+ if (yOff > 0)
+ {
+ yOffP = (yOff + 1) / 2;
+ yOffM = yOff / 2;
+ }
+ else
+ {
+ yOffP = yOff / 2;
+ yOffM = (yOff - 1) / 2;
+ }
+ Poly[0].x = x0 + xOffP;
+ Poly[0].y = y0 + yOffP;
+ Poly[1].x = x0 - xOffM;
+ Poly[1].y = y0 - yOffM;
+ Poly[2].x = x1 - xOffM;
+ Poly[2].y = y1 - yOffM;
+ Poly[3].x = x1 + xOffP;
+ Poly[3].y = y1 + yOffP;
+ GL_FillPolygon(&Poly[0], 4, 0, 0);
+ _DrawLineEnd(x0, y0);
+ _DrawLineEnd(x1, y1);
}
}
}
/*********************************************************************
-*
-* GUI_DrawLine
-*/
-void GUI_DrawLine(int x0, int y0, int x1, int y1) {
+ *
+ * GUI_DrawLine
+ */
+void GUI_DrawLine(int x0, int y0, int x1, int y1)
+{
GUI_LOCK();
- #if (GUI_WINSUPPORT)
- WM_ADDORG(x0,y0);
- WM_ADDORG(x1,y1);
- WM_ITERATE_START(NULL); {
- #endif
- GL_DrawLine (x0, y0, x1, y1);
- #if (GUI_WINSUPPORT)
- } WM_ITERATE_END();
- #endif
+#if (GUI_WINSUPPORT)
+ WM_ADDORG(x0, y0);
+ WM_ADDORG(x1, y1);
+ WM_ITERATE_START(NULL);
+ {
+#endif
+ GL_DrawLine(x0, y0, x1, y1);
+#if (GUI_WINSUPPORT)
+ }
+ WM_ITERATE_END();
+#endif
GUI_UNLOCK();
}
/*********************************************************************
-*
-* GL_DrawPolygon
-*/
-void GL_DrawPolygon(const GUI_POINT*pPoints, int NumPoints, int x0, int y0) {
- const GUI_POINT* pPoint = pPoints;
- GL_MoveTo(pPoint->x+x0, pPoint->y+y0);
- while (--NumPoints >0) {
+ *
+ * GL_DrawPolygon
+ */
+void GL_DrawPolygon(const GUI_POINT *pPoints, int NumPoints, int x0, int y0)
+{
+ const GUI_POINT *pPoint = pPoints;
+ GL_MoveTo(pPoint->x + x0, pPoint->y + y0);
+ while (--NumPoints > 0)
+ {
pPoint++;
- GL_DrawLineTo(pPoint->x+x0, pPoint->y+y0);
+ GL_DrawLineTo(pPoint->x + x0, pPoint->y + y0);
}
/* Now draw closing line unless it has already been closed */
- if ( (pPoint->x != pPoints->x)
- ||(pPoint->y != pPoints->y))
+ if ((pPoint->x != pPoints->x) || (pPoint->y != pPoints->y))
{
- GL_DrawLineTo(pPoints->x+x0, pPoints->y+y0);
+ GL_DrawLineTo(pPoints->x + x0, pPoints->y + y0);
}
}
/*********************************************************************
-*
-* GUI_DrawPolygon
-*/
-void GUI_DrawPolygon(const GUI_POINT* pPoints, int NumPoints, int x0, int y0) {
+ *
+ * GUI_DrawPolygon
+ */
+void GUI_DrawPolygon(const GUI_POINT *pPoints, int NumPoints, int x0, int y0)
+{
GUI_LOCK();
- #if (GUI_WINSUPPORT)
- WM_ADDORG(x0,y0);
- WM_ITERATE_START(NULL); {
- #endif
- GL_DrawPolygon (pPoints, NumPoints, x0, y0);
- #if (GUI_WINSUPPORT)
- } WM_ITERATE_END();
- #endif
+#if (GUI_WINSUPPORT)
+ WM_ADDORG(x0, y0);
+ WM_ITERATE_START(NULL);
+ {
+#endif
+ GL_DrawPolygon(pPoints, NumPoints, x0, y0);
+#if (GUI_WINSUPPORT)
+ }
+ WM_ITERATE_END();
+#endif
GUI_UNLOCK();
}
/*********************************************************************
-*
-* Draw Line to group
-*
-**********************************************************************
-*/
+ *
+ * Draw Line to group
+ *
+ **********************************************************************
+ */
/*********************************************************************
-*
-* GL_DrawLineRelNM
-*/
-static void GL_DrawLineRelNM(int dx, int dy) {
- GL_DrawLine (GUI_Context.DrawPosX, GUI_Context.DrawPosY,
- GUI_Context.DrawPosX+dx, GUI_Context.DrawPosY+dy);
+ *
+ * GL_DrawLineRelNM
+ */
+static void GL_DrawLineRelNM(int dx, int dy)
+{
+ GL_DrawLine(GUI_Context.DrawPosX, GUI_Context.DrawPosY,
+ GUI_Context.DrawPosX + dx, GUI_Context.DrawPosY + dy);
}
/*********************************************************************
-*
-* GUI_DrawLineRel
-*/
-void GUI_DrawLineRel(int dx, int dy) {
+ *
+ * GUI_DrawLineRel
+ */
+void GUI_DrawLineRel(int dx, int dy)
+{
GUI_LOCK();
- #if (GUI_WINSUPPORT)
- WM_ITERATE_START(NULL); {
- #endif
- GL_DrawLineRelNM(dx,dy);
- #if (GUI_WINSUPPORT)
- } WM_ITERATE_END();
- #endif
- GUI_MoveRel(dx,dy);
+#if (GUI_WINSUPPORT)
+ WM_ITERATE_START(NULL);
+ {
+#endif
+ GL_DrawLineRelNM(dx, dy);
+#if (GUI_WINSUPPORT)
+ }
+ WM_ITERATE_END();
+#endif
+ GUI_MoveRel(dx, dy);
GUI_UNLOCK();
}
/*********************************************************************
-*
-* GL_DrawLineTo
-*/
-void GL_DrawLineTo(int x, int y) {
- GL_DrawLine (GUI_Context.DrawPosX, GUI_Context.DrawPosY, x, y);
+ *
+ * GL_DrawLineTo
+ */
+void GL_DrawLineTo(int x, int y)
+{
+ GL_DrawLine(GUI_Context.DrawPosX, GUI_Context.DrawPosY, x, y);
GUI_Context.DrawPosX = x;
GUI_Context.DrawPosY = y;
}
/*********************************************************************
-*
-* GL_DrawLineToNM
-*/
-static void GL_DrawLineToNM(int x, int y) {
- GL_DrawLine (GUI_Context.DrawPosX, GUI_Context.DrawPosY, x, y);
+ *
+ * GL_DrawLineToNM
+ */
+static void GL_DrawLineToNM(int x, int y)
+{
+ GL_DrawLine(GUI_Context.DrawPosX, GUI_Context.DrawPosY, x, y);
}
/*********************************************************************
-*
-* GUI_DrawLineTo
-*/
-void GUI_DrawLineTo(int x, int y) {
+ *
+ * GUI_DrawLineTo
+ */
+void GUI_DrawLineTo(int x, int y)
+{
GUI_LOCK();
- #if (GUI_WINSUPPORT)
- WM_ADDORG(x,y);
- WM_ITERATE_START(NULL); {
- #endif
- GL_DrawLineToNM(x,y);
- #if (GUI_WINSUPPORT)
- } WM_ITERATE_END();
- #endif
- GL_MoveTo(x,y);
+#if (GUI_WINSUPPORT)
+ WM_ADDORG(x, y);
+ WM_ITERATE_START(NULL);
+ {
+#endif
+ GL_DrawLineToNM(x, y);
+#if (GUI_WINSUPPORT)
+ }
+ WM_ITERATE_END();
+#endif
+ GL_MoveTo(x, y);
GUI_UNLOCK();
}
/*********************************************************************
-*
-* GUI_MoveRel
-*/
-void GUI_MoveRel(int dx, int dy) { /*tbd: GL_LinePos. */
+ *
+ * GUI_MoveRel
+ */
+void GUI_MoveRel(int dx, int dy)
+{ /*tbd: GL_LinePos. */
GUI_LOCK();
GUI_Context.DrawPosX += dx;
GUI_Context.DrawPosY += dy;
@@ -511,38 +567,41 @@ void GUI_MoveRel(int dx, int dy) { /*tbd: GL_LinePos. */
}
/*********************************************************************
-*
-* GL_MoveTo
-*/
-void GL_MoveTo(int x, int y) {
+ *
+ * GL_MoveTo
+ */
+void GL_MoveTo(int x, int y)
+{
GUI_Context.DrawPosX = x;
GUI_Context.DrawPosY = y;
}
/*********************************************************************
-*
-* GUI_MoveTo
-*/
-void GUI_MoveTo(int x, int y) {
+ *
+ * GUI_MoveTo
+ */
+void GUI_MoveTo(int x, int y)
+{
GUI_LOCK();
- #if (GUI_WINSUPPORT)
- WM_ADDORG(x,y);
- #endif
- GL_MoveTo(x,y);
+#if (GUI_WINSUPPORT)
+ WM_ADDORG(x, y);
+#endif
+ GL_MoveTo(x, y);
GUI_UNLOCK();
}
/*********************************************************************
-*
-* Rectangle filling / inverting
-*
-**********************************************************************
-*/
+ *
+ * Rectangle filling / inverting
+ *
+ **********************************************************************
+ */
/*********************************************************************
-*
-* _DrawRect
-*/
-static void _DrawRect(int x0, int y0, int x1, int y1) {
+ *
+ * _DrawRect
+ */
+static void _DrawRect(int x0, int y0, int x1, int y1)
+{
LCD_DrawHLine(x0, y0, x1);
LCD_DrawHLine(x0, y1, x1);
LCD_DrawVLine(x0, y0 + 1, y1 - 1);
@@ -550,51 +609,56 @@ static void _DrawRect(int x0, int y0, int x1, int y1) {
}
/*********************************************************************
-*
-* GUI_DrawRect
-*/
-void GUI_DrawRect(int x0, int y0, int x1, int y1) {
- #if (GUI_WINSUPPORT)
- int Off;
- GUI_RECT r;
- #endif
+ *
+ * GUI_DrawRect
+ */
+void GUI_DrawRect(int x0, int y0, int x1, int y1)
+{
+#if (GUI_WINSUPPORT)
+ int Off;
+ GUI_RECT r;
+#endif
GUI_LOCK();
- #if (GUI_WINSUPPORT)
- Off = GUI_Context.PenSize -1;
- WM_ADDORG(x0,y0);
- WM_ADDORG(x1,y1);
- r.x0 = x0 - Off;
- r.x1 = x1 + Off;
- r.y0 = y0 - Off;
- r.y1 = y1 + Off;
- WM_ITERATE_START(&r); {
- #endif
- _DrawRect(x0, y0, x1, y1);
- #if (GUI_WINSUPPORT)
- } WM_ITERATE_END();
- #endif
+#if (GUI_WINSUPPORT)
+ Off = GUI_Context.PenSize - 1;
+ WM_ADDORG(x0, y0);
+ WM_ADDORG(x1, y1);
+ r.x0 = x0 - Off;
+ r.x1 = x1 + Off;
+ r.y0 = y0 - Off;
+ r.y1 = y1 + Off;
+ WM_ITERATE_START(&r);
+ {
+#endif
+ _DrawRect(x0, y0, x1, y1);
+#if (GUI_WINSUPPORT)
+ }
+ WM_ITERATE_END();
+#endif
GUI_UNLOCK();
}
/*********************************************************************
-*
-* DrawLine, internal, 1 pixel
-*
-**********************************************************************
-*/
+ *
+ * DrawLine, internal, 1 pixel
+ *
+ **********************************************************************
+ */
/*********************************************************************
-*
-* GL_DrawLine1
-*/
-void GL_DrawLine1(int x0, int y0, int x1, int y1) {
- int xdiff = x1-x0;
- int ydiff = y1-y0;
+ *
+ * GL_DrawLine1
+ */
+void GL_DrawLine1(int x0, int y0, int x1, int y1)
+{
+ int xdiff = x1 - x0;
+ int ydiff = y1 - y0;
int xdiffby2;
int i;
- char Swapped =0;
-/* check if no line */
- if (!(xdiff|ydiff)) {
- GL_DrawPoint(x0,y0);
+ char Swapped = 0;
+ /* check if no line */
+ if (!(xdiff | ydiff))
+ {
+ GL_DrawPoint(x0, y0);
return;
}
#if 0
@@ -609,80 +673,95 @@ void GL_DrawLine1(int x0, int y0, int x1, int y1) {
return;
}
#endif
-/* check if we swap x and y for calculation */
- if (Abs(xdiff) < Abs(ydiff)) {
- _SwapInt(&xdiff,&ydiff);
- _SwapInt(&x0,&y0);
- _SwapInt(&x1,&y1);
- Swapped =1;
+ /* check if we swap x and y for calculation */
+ if (Abs(xdiff) < Abs(ydiff))
+ {
+ _SwapInt(&xdiff, &ydiff);
+ _SwapInt(&x0, &y0);
+ _SwapInt(&x1, &y1);
+ Swapped = 1;
}
-/* make sure line direction is positive */
- if (xdiff!=Abs(xdiff)) {
+ /* make sure line direction is positive */
+ if (xdiff != Abs(xdiff))
+ {
xdiff = -xdiff;
ydiff = -ydiff;
- _SwapInt(&x0,&x1);
- _SwapInt(&y0,&y1);
+ _SwapInt(&x0, &x1);
+ _SwapInt(&y0, &y1);
}
- xdiffby2 = xdiff/2;
- if (ydiff<0)
+ xdiffby2 = xdiff / 2;
+ if (ydiff < 0)
xdiffby2 = -xdiffby2;
-/* Draw pixel by pixel solid*/
- if (GUI_Context.LineStyle == GUI_LS_SOLID) {
- for (i=0; i<=xdiff; i++) {
- I32 l = ((I32)ydiff)*i+xdiffby2;
- int y = (ABS(l)<32767) ? (y0 + ((int)l)/xdiff) : (y0 + l/xdiff);
+ /* Draw pixel by pixel solid*/
+ if (GUI_Context.LineStyle == GUI_LS_SOLID)
+ {
+ for (i = 0; i <= xdiff; i++)
+ {
+ I32 l = ((I32)ydiff) * i + xdiffby2;
+ int y = (ABS(l) < 32767) ? (y0 + ((int)l) / xdiff) : (y0 + l / xdiff);
if (!Swapped)
- LCD_HL_DrawPixel(x0+i, y);
+ LCD_HL_DrawPixel(x0 + i, y);
else
- LCD_HL_DrawPixel(y, x0+i);
+ LCD_HL_DrawPixel(y, x0 + i);
}
-/* Draw pixel by pixel with fill style */
- } else {
- for (i=0; i<=xdiff; i++) {
- long l = ((long)ydiff)*i+xdiffby2;
- int y = (ABS(l)<32767) ? (y0 + ((int)l)/xdiff) : (y0 + l/xdiff);
- if (!_SetLineColor(i)) {
+ /* Draw pixel by pixel with fill style */
+ }
+ else
+ {
+ for (i = 0; i <= xdiff; i++)
+ {
+ long l = ((long)ydiff) * i + xdiffby2;
+ int y = (ABS(l) < 32767) ? (y0 + ((int)l) / xdiff) : (y0 + l / xdiff);
+ if (!_SetLineColor(i))
+ {
if (!Swapped)
- LCD_HL_DrawPixel(x0+i, y);
+ LCD_HL_DrawPixel(x0 + i, y);
else
- LCD_HL_DrawPixel(y, x0+i);
+ LCD_HL_DrawPixel(y, x0 + i);
}
}
}
}
/*********************************************************************
-*
-* Draw point
-*
-**********************************************************************
-*/
+ *
+ * Draw point
+ *
+ **********************************************************************
+ */
/*********************************************************************
-*
-* GL_DrawPoint
-*/
-void GL_DrawPoint(int x, int y) {
- if (GUI_Context.PenSize == 1) {
+ *
+ * GL_DrawPoint
+ */
+void GL_DrawPoint(int x, int y)
+{
+ if (GUI_Context.PenSize == 1)
+ {
LCD_HL_DrawPixel(x, y);
- } else {
+ }
+ else
+ {
GL_FillCircle(x, y, (GUI_Context.PenSize - 1) / 2);
}
}
/*********************************************************************
-*
-* GUI_DrawPoint
-*/
-void GUI_DrawPoint(int x, int y) {
+ *
+ * GUI_DrawPoint
+ */
+void GUI_DrawPoint(int x, int y)
+{
GUI_LOCK();
- #if (GUI_WINSUPPORT)
- WM_ADDORG(x, y);
- WM_ITERATE_START(NULL); {
- #endif
- GL_DrawPoint(x, y);
- #if (GUI_WINSUPPORT)
- } WM_ITERATE_END();
- #endif
+#if (GUI_WINSUPPORT)
+ WM_ADDORG(x, y);
+ WM_ITERATE_START(NULL);
+ {
+#endif
+ GL_DrawPoint(x, y);
+#if (GUI_WINSUPPORT)
+ }
+ WM_ITERATE_END();
+#endif
GUI_UNLOCK();
}
diff --git a/User/lib/lcd/lcd_sharp.c b/User/lib/lcd/lcd_sharp.c
index 470d60b..16b789d 100644
--- a/User/lib/lcd/lcd_sharp.c
+++ b/User/lib/lcd/lcd_sharp.c
@@ -121,7 +121,7 @@ static int32_t _init(lcd_t *lcd)
* @return {*}
* @note
*/
-static void _copy_templete(lcd_t *lcd, template_copy_type_e dir)
+static void _copy_template(lcd_t *lcd, template_copy_type_e dir)
{
uint16_t size = (lcd->info.width / 8) * (lcd->info.height);
if (dir == TEMPLATE_COPY_FROM_PRI)
@@ -178,14 +178,14 @@ static void _flush(lcd_t *lcd)
lcd->info.flush_use_time = sys_millis();
uint16_t tmp = 0;
uint32_t length = 0;
+ uint8_t ret = FALSE;
+ int8_t retransmission_count = lcd->info.retransmission_count;
DBG_ASSERT(lcd != NULL __DBG_LINE);
DBG_ASSERT(lcd->info.spi != NULL __DBG_LINE);
uint16_t l = lcd->info.height;
uint16_t r = lcd->info.width / 8;
uint8_t(*lcd_gram)[lcd->info.width / 8] = (uint8_t(*)[lcd->info.width / 8]) lcd->info.pri;
uint8_t *lcd_gram_send = (uint8_t *)lcd->info.pri_send;
- sharp_chip_select(lcd, TRUE);
-
*lcd_gram_send++ = LCD_CMD_UPDATE;
for (uint16_t line = 0; line < l; line++)
{
@@ -203,13 +203,28 @@ static void _flush(lcd_t *lcd)
*lcd_gram_send++ = LCD_CMD_NOP;
*lcd_gram_send++ = LCD_CMD_NOP;
length = (uint32_t)lcd_gram_send - (uint32_t)lcd->info.pri_send;
+
+ lcd->driver.idel = FALSE;
if (length > 4)
{
- lcd->info.spi->interface.spi_dma_send(lcd->info.spi, (uint8_t *)lcd->info.pri_send, (uint32_t)lcd_gram_send - (uint32_t)lcd->info.pri_send);
+ while (--retransmission_count > 0)
+ {
+ sharp_chip_select(lcd, TRUE);
+ ret = lcd->info.spi->interface.spi_dma_send(lcd->info.spi, (uint8_t *)lcd->info.pri_send, (uint32_t)lcd_gram_send - (uint32_t)lcd->info.pri_send);
+ sharp_chip_select(lcd, FALSE);
+ LL_mDelay(10);
+ if (ret == TRUE)
+ {
+ break;
+ }
+ }
+ }
+ if (retransmission_count <= 0)
+ {
+ __NOP();
}
-
- sharp_chip_select(lcd, FALSE);
lcd->info.flush_use_time = sys_millis() - lcd->info.flush_use_time;
+ lcd->driver.idel = TRUE;
}
static void _flush_clear(lcd_t *lcd)
@@ -428,7 +443,7 @@ void lcd_sharp_init(lcd_driver_t *driver)
driver->set_clear_flag = _set_clear_flag; // 已实现
driver->get_clear_flag = _get_clear_flag; // 已实现
driver->full_fill = _full_fill; // 已实现
- driver->copy_templete = _copy_templete; // 已实现
+ driver->copy_template = _copy_template; // 已实现
driver->clear_ram = _clear_ram; // 已实现
// 以下不实现
diff --git a/User/lib/lcd/lcd_st7525.c b/User/lib/lcd/lcd_st7525.c
index 9bd4e34..4e84322 100644
--- a/User/lib/lcd/lcd_st7525.c
+++ b/User/lib/lcd/lcd_st7525.c
@@ -16,7 +16,7 @@
#define ST_DISP_0 0xC4 // 0度正常显示
#define ST_DISP_180 0xC2 // 旋转180度显示
#define ST_SET_EV 0x81 // 对比度控制
-#pragma pack(1)
+
/*
驱动使用的数据结构,不对外
*/
@@ -32,7 +32,6 @@ struct _cog_drv_data
uint16_t disx;
uint16_t disy;
};
-#pragma pack()
/**
* @brief 写命令
diff --git a/User/lib/lcd/lcds.c b/User/lib/lcd/lcds.c
index e562735..17fc908 100644
--- a/User/lib/lcd/lcds.c
+++ b/User/lib/lcd/lcds.c
@@ -26,7 +26,7 @@ lcd_t *lcd_create(lcd_info_t info)
lcd_t *handle = (lcd_t *)osel_mem_alloc(sizeof(lcd_t));
DBG_ASSERT(handle != NULL __DBG_LINE);
osel_memcpy((uint8_t *)&handle->info, (uint8_t *)&info, sizeof(lcd_info_t));
-
+ handle->driver.idel = TRUE;
switch (info.type)
{
case LCD_ST7525:
@@ -41,86 +41,3 @@ lcd_t *lcd_create(lcd_info_t info)
}
return handle;
}
-
-void lcd_set_font_size(font_type_e font)
-{
- GUI_SetBkColor(GUI_WHITE);
- GUI_SetColor(GUI_BLACK);
- switch (font)
- {
- case FONT_SMALL:
- GUI_SetFont(&GUI_FontHZ16x16);
- break;
- case FONT_MEDIUM:
- GUI_SetFont(&GUI_FontHZ24x24);
- break;
- case FONT_LARGE:
- GUI_SetFont(&GUI_FontHZ24x24);
- break;
- default:
- break;
- }
-}
-
-// 对齐显示字符串,其余部分填充背景色
-int32_t lcd_put_alignment_string(lcd_t *lcd, font_type_e font, int32_t row, char *s, uint8_t alignment, BOOL reverse, uint16_t color)
-{
- lcd_set_font_size(font);
- uint16_t len = GUI_GetStringDistX(s);
- switch (alignment)
- {
- case GUI_TA_LEFT:
- case GUI_TA_NORMOL:
- if (reverse == FALSE)
- {
- GUI_SetTextMode(GUI_TEXTMODE_REV); // 反转文本
- GUI_DispStringAt(s, 0, GUI_GetFontSizeY() * row);
- GUI_SetTextAlign(GUI_TA_LEFT);
- GUI_SetColor(GUI_WHITE); // 设置文本颜色
- GUI_SetTextMode(GUI_TEXTMODE_TRANS); // 恢复文本
- GUI_SetColor(GUI_BLACK); // 设置文本颜色
- }
- else
- {
- GUI_DispStringAt(s, 0, GUI_GetFontSizeY() * row);
- GUI_SetTextAlign(GUI_TA_LEFT);
- }
- break;
- case GUI_TA_HCENTER:
- if (reverse == TRUE)
- {
- GUI_SetTextMode(GUI_TEXTMODE_REV); // 反转文本
- GUI_DispStringAt(s, (lcd->info.width - len) / 2, GUI_GetFontSizeY() * row);
- GUI_SetColor(GUI_WHITE); // 设置文本颜色
- GUI_SetTextMode(GUI_TEXTMODE_TRANS); // 恢复文本
- GUI_SetColor(GUI_BLACK); // 设置文本颜色
- }
- else
- {
- GUI_DispStringAt(s, (lcd->info.width - len) / 2, GUI_GetFontSizeY() * row);
- }
-
- break;
- case GUI_TA_RIGHT:
- if (reverse == TRUE)
- {
- GUI_SetTextMode(GUI_TEXTMODE_REV); // 反转文本
- GUI_DispStringAt(s, 0, GUI_GetFontSizeY() * row);
- GUI_SetTextAlign(GUI_TA_RIGHT);
- GUI_SetColor(GUI_WHITE); // 设置文本颜色
- GUI_SetTextMode(GUI_TEXTMODE_TRANS); // 恢复文本
- GUI_SetColor(GUI_BLACK); // 设置文本颜色
- }
- else
- {
- GUI_DispStringAt(s, 0, GUI_GetFontSizeY() * row);
- GUI_SetTextAlign(GUI_TA_RIGHT);
- }
-
- break;
- default:
- break;
- }
-
- return 0;
-}
diff --git a/User/lib/lcd/lcds.h b/User/lib/lcd/lcds.h
index 29380c4..3d10334 100644
--- a/User/lib/lcd/lcds.h
+++ b/User/lib/lcd/lcds.h
@@ -7,12 +7,23 @@
*/
/**
* 16*16字体,宽高16*16,宋体、粗体、11
-欢迎使用智能定位器版本江苏巨石数字技术有限公司选择操作短按长返回进入下一个上取消确认图表页面电流温度℃↑↓←→√×序列号硬件软固设备型安装方向行程类气动正反直角开关单双地址工模式自手测试非待机写保护启闭压力传感状态蓝牙输出块通讯显示语言中文英算法置恒控制变频速域整已未编辑首基准驱存储磁条小路源偏差摩擦弹簧率内累计次时间故障量校大知的项配实执仪服务外拟投相信过高低积分饱和切割点诊断换在报警记录不为空满离线耗尽主要据可指
+欢迎使用智能定位器版本江苏巨石数字技术有限公司选择操作短按长返回进入下一个上取消确认图表页面电流温度℃↑↓←→√○×序列号硬件软固设备型安装方向行程类气动正反直角开关单双地址工模式自手测试非待机写保护启闭压力传感状态蓝牙输出块通讯显示语言中文英算法置恒控制变频速域整已未编辑首基准驱存储磁条小路源偏差摩擦弹簧率内累计次时间故障量校大知的项配实执仪服务外拟投相信过高低积分饱和切割点诊断换在报警记录不为空满离线耗尽主要据可指复零功阀门全更新厂商名称造息范围环境~℉°成平构放带缸薄膜常运停当前移跨减少增加恢参所重比例系微死区益湿
*/
/**
* 24*24字体,宽高24*24,宋体、粗体、18
-,。主菜单设备重启自检保存成功失败加载中置已取消欢迎使用智能定位器版本江苏巨石数字技术有限公司电流温度故障超出规格需要维护正常一键整信息厂阀门诊断行程特性测试输入密码错误编辑当前不满足动条件未知秒后返回首页选择项目查请求参恢复斜坡阶跃计面至默认配包括对校准或的修改但驱控制号发生
+,。主菜单设备重启自检保存成功失败加载中置已取消欢迎使用智能定位器版本江苏巨石数字技术有限公司电流温度故障超出规格需要维护正常一键整信息厂阀门诊断行程特性测试输入密码错误编辑当前不满足动条件未知秒后返回首页选择项目查请求参恢复斜坡阶跃计面至默认配包括对校准或的修改但驱控制号发生实时据变量所℃℉°进
+ */
+
+/**
+ * 32*32字体,宽高32*32,宋体、粗体、26
+进度
+ */
+
+/**
+ * 18x18图片 保持比例 不反色
+ * Public\img\icon\标题栏-HZ18x18
+ * 字符映射:在文件名称中
*/
/**
@@ -111,13 +122,6 @@ typedef enum
LCD_SHARP,
} lcd_type_e;
-typedef enum
-{
- FONT_SMALL, // 16
- FONT_MEDIUM, // 24
- FONT_LARGE, // 32
-} font_type_e;
-
typedef enum
{
TEMPLATE_COPY_FROM_PRI, // 拷贝pri到pri_template
@@ -138,8 +142,9 @@ typedef struct
uint16_t height; // LCDS 高度
// private:
- uint8_t on; // 开关 0关,1开
- uint8_t scandir; // 扫描方向:0, 0度扫描,1, 180度扫描
+ uint8_t on; // 开关 0关,1开
+ uint8_t scandir; // 扫描方向:0, 0度扫描,1, 180度扫描
+ uint8_t retransmission_count; // 重传次数
volatile BOOL need_build;
BOOL clear_flag; // 清屏标志
void *pri; // 私有数据,黑白屏跟OLED屏在初始化的时候会开辟显存
@@ -167,13 +172,15 @@ typedef struct
void (*full_fill)(lcd_t *lcd, uint16_t color);
int32_t (*clear)(lcd_t *lcd); // 清屏
void (*set_clear_flag)(lcd_t *lcd); // 设置清屏标志
- void (*copy_templete)(lcd_t *lcd, template_copy_type_e dir); // 拷贝模板 0,拷贝pri_template到pri;1,拷贝pri到pri_template; 其余清空
+ void (*copy_template)(lcd_t *lcd, template_copy_type_e dir); // 拷贝模板 0,拷贝pri_template到pri;1,拷贝pri到pri_template; 其余清空
void (*clear_ram)(lcd_t *lcd, uint16_t min_row, uint16_t max_row); // 清除显存
// 获取接口
uint8_t (*get_dir)(lcd_t *lcd); // 获取扫描方向
BOOL(*get_clear_flag)
(lcd_t *lcd); // 获取清屏标志
+
+ __IO BOOL idel; // 是否空闲
} lcd_driver_t;
struct LCDS
@@ -184,6 +191,5 @@ struct LCDS
extern lcd_t *lcd_create(lcd_info_t info);
extern void lcd_free(lcd_t *handle);
-extern void lcd_set_font_size(font_type_e font);
-extern int32_t lcd_put_alignment_string(lcd_t *lcd, font_type_e font, int32_t row, char *s, uint8_t alignment, BOOL reverse, uint16_t color); // 对齐显示字符串
-#endif // __LCDS_H__
+
+#endif // __LCDS_H__
diff --git a/User/lib/menu/menu.c b/User/lib/menu/menu.c
index 64ccdec..ec59239 100644
--- a/User/lib/menu/menu.c
+++ b/User/lib/menu/menu.c
@@ -1,6 +1,9 @@
#include "menu.h"
+#include "menus_main.h"
+#include "entity.h"
#include
#include
+#include "convert.h"
#ifdef _COT_MENU_USE_MALLOC_
#include
#endif
@@ -206,6 +209,7 @@ BOOL menu_bind(uint16_t parent_window_no, const menu_list_t *p_menu_list, menusi
sg_t_menu_manage.p_menu_ctrl->p_menu_list = (menu_list_t *)p_menu_list;
sg_t_menu_manage.p_menu_ctrl->items_num = menu_num;
sg_t_menu_manage.p_menu_ctrl->parent_window_no = parent_window_no;
+ sg_t_menu_manage.p_menu_ctrl->select_item = 0;
if (pfn_show_menu_fun != NULL)
{
diff --git a/User/lib/menu/menu.h b/User/lib/menu/menu.h
index 68df10a..e0b8e5f 100644
--- a/User/lib/menu/menu.h
+++ b/User/lib/menu/menu.h
@@ -24,11 +24,7 @@
/* exported types ----------------------------------------------------------------------------------------------------*/
-#if MENU_MAX_NUM < 255
-typedef uint8_t menusize_t;
-#else
typedef uint16_t menusize_t;
-#endif
typedef void (*menu_call_fun_f)(void);
@@ -76,7 +72,7 @@ typedef struct
menu_call_fun_f pfn_run_call_fun; /*!< 当前菜单选项的周期调度函数 */
- void *p_extend_data; /*!< 当前选项的菜单显示效果函数扩展数据入参, 可自行设置该内容 */
+ void *p_extend_data; /*!< 当前选项的菜单显示效果函数扩展数据入参, 可自行设置该内容 赋值给p_items_ex_data*/
} menu_list_t, menu_item_t;
/**
diff --git a/User/static.lib b/User/static.lib
new file mode 100644
index 0000000..a8c53cd
Binary files /dev/null and b/User/static.lib differ
diff --git a/User/system/bsp/adcs.c b/User/system/bsp/adcs.c
deleted file mode 100644
index eb34b9b..0000000
--- a/User/system/bsp/adcs.c
+++ /dev/null
@@ -1,407 +0,0 @@
-/**
- * @file adcs.c
- * @author xxx
- * @date 2023-09-04 15:59:16
- * @brief LL库ADC驱动
- * @copyright Copyright (c) 2023 by xxx, All Rights Reserved.
- */
-
-#include "adcs.h"
-#include "sys.h"
-
-adcs_t adcs[ADCS_MAX];
-
-static uint8_t adc_get_channels_count(uint32_t channnels); // 通过用户配置的通道号获取通道数量
-
-/**
- * @brief ADC初始化
- * @param {adcs_e} num ADC编号
- * @param {ADC_TypeDef} *adc ADC外设
- * @param {DMA_TypeDef} *dma DMA外设
- * @param {uint32_t} dma_channel DMA通道
- * @param {uint8_t} adc_cct ADC采样次数
- * @param {uint32_t} channels 存储数据所在的序列号
- * @return {*}
- * @note TCONV(转换时间) = (采样时间 + 12.5 个周期)/(主频/ADC分频系数)
- */
-void adc_init(adcs_e num, ADC_TypeDef *adc, DMA_TypeDef *dma, uint32_t dma_channel, uint8_t adc_cct, uint32_t channels)
-{
- DBG_ASSERT(num < ADCS_MAX __DBG_LINE);
- DBG_ASSERT(adc != NULL __DBG_LINE);
- DBG_ASSERT(dma != NULL __DBG_LINE);
- DBG_ASSERT(adc_cct > 0 __DBG_LINE);
-
- adcs_t *p = &adcs[num];
- osel_memset((uint8_t *)p, 0, sizeof(adcs_t));
- p->adc = adc;
- p->dma = dma;
- p->dma_channel = dma_channel;
- p->channels.data = channels;
- p->adc_cct = adc_cct;
- p->adc_chans_count = adc_get_channels_count(channels);
- p->adc_sum = adc_cct * p->adc_chans_count;
-
-#if defined(SRAM2_BASE) // SRAM2速度更快
- p->adc_value = (uint16_t *)osel_mem_alloc2(sizeof(uint16_t) * p->adc_sum);
-#else
- p->adc_value = (uint16_t *)osel_mem_alloc(sizeof(uint16_t) * p->adc_sum);
-#endif
-
- DBG_ASSERT(p->adc_value != NULL __DBG_LINE);
- osel_memset((uint8_t *)p->adc_value, 0, sizeof(uint16_t) * p->adc_sum);
-
- uint32_t backup_setting_adc_dma_transfer = 0U;
- backup_setting_adc_dma_transfer = LL_ADC_REG_GetDMATransfer(p->adc);
- LL_ADC_REG_SetDMATransfer(p->adc, LL_ADC_REG_DMA_TRANSFER_NONE);
-
- // ADC开始校准
- LL_ADC_StartCalibration(p->adc, LL_ADC_SINGLE_ENDED);
- // 等待校准完成
- while (LL_ADC_IsCalibrationOnGoing(p->adc))
- ;
- LL_ADC_REG_SetDMATransfer(p->adc, backup_setting_adc_dma_transfer);
- LL_mDelay(10);
- LL_ADC_EnableIT_OVR(p->adc);
- LL_ADC_Enable(p->adc);
- LL_mDelay(10);
-
- if (BIT_IS_SET(channels, INVREF))
- {
- // 使能VREFINT
- LL_ADC_SetCommonPathInternalCh(__LL_ADC_COMMON_INSTANCE(p->adc), LL_ADC_PATH_INTERNAL_VREFINT);
- }
-
- LL_DMA_SetDataLength(p->dma, p->dma_channel, p->adc_sum);
- LL_DMA_SetPeriphAddress(p->dma, p->dma_channel, LL_ADC_DMA_GetRegAddr(p->adc, LL_ADC_DMA_REG_REGULAR_DATA));
- LL_DMA_SetMemoryAddress(p->dma, p->dma_channel, (uint32_t)p->adc_value);
- LL_DMA_EnableChannel(p->dma, p->dma_channel);
-
- if (backup_setting_adc_dma_transfer == LL_ADC_REG_DMA_TRANSFER_UNLIMITED)
- {
- LL_ADC_REG_StartConversion(p->adc); // 开始转换
- }
-}
-
-/**
- * @brief ADC重新开始转换
- * @param {adcs_e} num ADC编号
- * @return {*}
- * @note
- */
-void adc_restart(adcs_e num)
-{
- DBG_ASSERT(num < ADCS_MAX __DBG_LINE);
- adcs_t *p = &adcs[num];
- LL_ADC_REG_StopConversion(p->adc);
- LL_DMA_DisableChannel(p->dma, p->dma_channel);
-
- LL_DMA_SetDataLength(p->dma, p->dma_channel, p->adc_sum);
- LL_DMA_SetPeriphAddress(p->dma, p->dma_channel, LL_ADC_DMA_GetRegAddr(p->adc, LL_ADC_DMA_REG_REGULAR_DATA));
- LL_DMA_SetMemoryAddress(p->dma, p->dma_channel, (uint32_t)p->adc_value);
- LL_DMA_EnableChannel(p->dma, p->dma_channel);
-
- LL_ADC_ClearFlag_OVR(p->adc);
- LL_ADC_ClearFlag_EOC(p->adc);
- LL_ADC_REG_StartConversion(p->adc); // 开始转换
-}
-
-/**
- * @brief ADC反初始化
- * @param {adcs_e} num ADC编号
- * @return {*}
- * @note
- */
-void adc_dinit(adcs_e num)
-{
- DBG_ASSERT(num < ADCS_MAX __DBG_LINE);
- adcs_t *p = &adcs[num];
- LL_ADC_REG_StopConversion(p->adc);
- LL_DMA_DisableChannel(p->dma, p->dma_channel);
- LL_ADC_Disable(p->adc);
- if (p->adc_value != NULL)
- {
-#if defined(SRAM2_BASE)
- osel_mem_free2((uint16_t *)p->adc_value);
-#else
- osel_mem_free((uint16_t *)p->adc_value);
-#endif
- }
-}
-/**
- * @brief 获取ADC转换结果,只需要第一个值
- * @param {adcs_e} num
- * @param {uint8_t} chan
- * @return {*}
- * @note
- */
-uint16_t adc_result_only_one(adcs_e num, uint8_t chan)
-{
- DBG_ASSERT(num < ADCS_MAX __DBG_LINE);
- adcs_t *p = &adcs[num];
- DBG_ASSERT(p != NULL __DBG_LINE);
- uint16_t(*gram)[p->adc_chans_count] = (uint16_t(*)[p->adc_chans_count])p->adc_value;
- return gram[0][chan];
-}
-
-/**
- * @brief 中位值平均滤波,获取ADC转换结果
- * @param {adcs_e} num ADC编号
- * @param {uint8_t} chan 存储数据所在的序列号
- * @return {*}
- * @note
- */
-uint16_t adc_result_median_average(adcs_e num, uint8_t chan)
-{
- DBG_ASSERT(num < ADCS_MAX __DBG_LINE);
- adcs_t *p = &adcs[num];
- DBG_ASSERT(p != NULL __DBG_LINE);
-
- if (p->adc_cct <= 2)
- return 0; // 如果adc_cct小于等于2,直接返回0
-
- uint16_t adc_temp[p->adc_cct];
- uint32_t adc_sum = 0;
- uint8_t count = p->adc_cct >> 2; // 使用位移操作计算n的值
-
- // 减少重复计算,计算基础偏移量
- uint16_t *adc_values = (uint16_t *)p->adc_value + chan;
- for (uint8_t i = 0; i < p->adc_cct; ++i, adc_values += p->adc_chans_count)
- {
- adc_temp[i] = *adc_values;
- }
-
- insertion_sort(adc_temp, p->adc_cct);
-
- // 计算中间部分的和
- for (uint8_t i = count; i < p->adc_cct - count; ++i)
- {
- adc_sum += adc_temp[i];
- }
-
- // 计算平均值,确保不会除以0
- uint16_t res = adc_sum / (p->adc_cct - (count << 1));
- return res;
-}
-
-/**
- * @brief 中位值滤波,获取ADC转换结果
- * @param {adcs_e} num ADC编号
- * @param {uint8_t} chan 存储数据所在的序列号
- * @return {*}
- * @note
- */
-uint16_t adc_result_median(adcs_e num, uint8_t chan)
-{
- DBG_ASSERT(num < ADCS_MAX __DBG_LINE);
- uint16_t res = 0;
- adcs_t *p = &adcs[num];
- DBG_ASSERT(p != NULL __DBG_LINE);
- uint16_t adc_temp[p->adc_cct];
- // 减少重复计算,计算基础偏移量
- uint16_t *adc_values = (uint16_t *)p->adc_value + chan;
- for (uint8_t i = 0; i < p->adc_cct; ++i, adc_values += p->adc_chans_count)
- {
- adc_temp[i] = *adc_values;
- }
- insertion_sort(adc_temp, p->adc_cct);
- res = adc_temp[p->adc_cct >> 1];
- return res;
-}
-
-/**
- * @brief 平均值,获取ADC转换结果
- * @param {adcs_e} num ADC编号
- * @param {uint8_t} chan 存储数据所在的序列号
- * @return {*}
- * @note
- */
-uint16_t adc_result_average(adcs_e num, uint8_t chan)
-{
- DBG_ASSERT(num < ADCS_MAX __DBG_LINE);
- uint32_t adc_sum = 0;
- adcs_t *p = &adcs[num];
- DBG_ASSERT(p != NULL __DBG_LINE);
- // 减少重复计算,计算基础偏移量
- uint16_t *adc_values = (uint16_t *)p->adc_value + chan;
- for (uint8_t i = 0; i < p->adc_cct; ++i, adc_values += p->adc_chans_count)
- {
- adc_sum += *adc_values;
- }
-
- return adc_sum / p->adc_cct;
-}
-
-/**
- * @brief 计算内部温度
- * @param {uint16_t} adc_value ADC转换结果
- * @return {*}
- * @note 计算公式为:(measure * VDD_APPLI / VDD_CALIB) - (int32_t)*TEMP30_CAL_ADDR) * (int32_t)(130 - 30) / (int32_t)(*TEMP130_CAL_ADDR - *TEMP30_CAL_ADDR)) + 30
- */
-float32 adc_result_temperature(uint16_t adc_value)
-{
-#define TEMP130_CAL_ADDR ((uint16_t *)((uint32_t)0x1FFF75A8))
-#define TEMP30_CAL_ADDR ((uint16_t *)((uint32_t)0x1FFF75CA))
-#define VDD_CALIB ((uint16_t)(300))
-#define VDD_APPLI ((uint16_t)(330))
- float32 res;
- res = ((adc_value * VDD_APPLI / VDD_CALIB) -
- (int32_t)*TEMP30_CAL_ADDR);
- res = res * (int32_t)(130 - 30);
- res = res / (int32_t)(*TEMP130_CAL_ADDR -
- *TEMP30_CAL_ADDR);
- res = res + 30;
- return res * 0.1f;
-}
-
-/**
- * @brief 计算内部电压
- * @param {uint16_t} adc_value ADC转换结果
- * @return {*} 电压值V
- * @note
- */
-float32 adc_result_value_local(uint16_t adc_value)
-{
- float32 vdd = (VREFINT_CAL_VREF * (*VREFINT_CAL_ADDR)) / 4095;
- return ((vdd / adc_value) * 4095) / 1000;
-}
-
-/**
- * @brief ADC DMA转换回调函数
-{
- * @param {adcs_e} num ADC编号
- * @return {*}
- * @note
- */
-void adc_dma_callback(adcs_e num)
-{
- adcs_t *p = &adcs[num];
- DBG_ASSERT(p != NULL __DBG_LINE);
- if (LL_DMA_IsActiveFlag_TC1(p->dma) != 0)
- {
- LL_DMA_ClearFlag_TC1(p->dma);
- // 停止ADC转换
- LL_ADC_REG_StopConversion(p->adc);
- // 关闭ADC,可以不关闭但是校准无法清除
- // LL_ADC_Disable(p->adc);
- }
- // 检查DMA1的传输错误标志是否为1,如果是,则清除该标志
- if (LL_DMA_IsActiveFlag_TE1(p->dma) != 0)
- {
- LL_DMA_ClearFlag_TE1(p->dma);
- }
-}
-
-/**
- * @brief ADC回调函数
- * @param {adcs_e} num ADC编号
- * @return {*}
- * @note
- */
-void adc_env_callback(adcs_e num)
-{
- adcs_t *p = &adcs[num];
- DBG_ASSERT(p != NULL __DBG_LINE);
- if (LL_ADC_IsActiveFlag_OVR(p->adc) != 0)
- {
- p->ovr_count++;
- LL_ADC_REG_StopConversion(p->adc);
- LL_DMA_DisableChannel(p->dma, p->dma_channel);
-
- LL_DMA_SetDataLength(p->dma, p->dma_channel, p->adc_sum);
- LL_DMA_SetPeriphAddress(p->dma, p->dma_channel, LL_ADC_DMA_GetRegAddr(p->adc, LL_ADC_DMA_REG_REGULAR_DATA));
- LL_DMA_SetMemoryAddress(p->dma, p->dma_channel, (uint32_t)p->adc_value);
- LL_DMA_EnableChannel(p->dma, p->dma_channel);
-
- LL_ADC_ClearFlag_OVR(p->adc);
- LL_ADC_ClearFlag_EOC(p->adc);
- LL_ADC_REG_StartConversion(p->adc); // 开始转换
- }
-}
-
-/**
- * @brief 通过用户配置的通道号获取通道数量
- * @param {uint32_t} channnels 存储数据所在的序列号
- * @return {*}
- * @note
- */
-static uint8_t adc_get_channels_count(uint32_t channnels)
-{
- uint8_t ch_num = 0;
- if (BIT_IS_SET(channnels, IN0))
- {
- ch_num++;
- }
- if (BIT_IS_SET(channnels, IN1))
- {
- ch_num++;
- }
- if (BIT_IS_SET(channnels, IN2))
- {
- ch_num++;
- }
- if (BIT_IS_SET(channnels, IN3))
- {
- ch_num++;
- }
- if (BIT_IS_SET(channnels, IN4))
- {
- ch_num++;
- }
- if (BIT_IS_SET(channnels, IN5))
- {
- ch_num++;
- }
- if (BIT_IS_SET(channnels, IN6))
- {
- ch_num++;
- }
- if (BIT_IS_SET(channnels, IN7))
- {
- ch_num++;
- }
- if (BIT_IS_SET(channnels, IN8))
- {
- ch_num++;
- }
- if (BIT_IS_SET(channnels, IN9))
- {
- ch_num++;
- }
- if (BIT_IS_SET(channnels, IN10))
- {
- ch_num++;
- }
- if (BIT_IS_SET(channnels, IN11))
- {
- ch_num++;
- }
- if (BIT_IS_SET(channnels, IN12))
- {
- ch_num++;
- }
- if (BIT_IS_SET(channnels, IN13))
- {
- ch_num++;
- }
- if (BIT_IS_SET(channnels, IN14))
- {
- ch_num++;
- }
- if (BIT_IS_SET(channnels, IN15))
- {
- ch_num++;
- }
- if (BIT_IS_SET(channnels, INVREF))
- {
- ch_num++;
- }
- if (BIT_IS_SET(channnels, INVBAT))
- {
- ch_num++;
- }
- if (BIT_IS_SET(channnels, INTEMP))
- {
- ch_num++;
- }
- return ch_num;
-}
diff --git a/User/system/bsp/adcs.h b/User/system/bsp/adcs.h
index 9ae5801..a873a66 100644
--- a/User/system/bsp/adcs.h
+++ b/User/system/bsp/adcs.h
@@ -20,7 +20,9 @@
#include "lib.h"
#include "main.h"
-#define ADC_CHANNEL_MAX 18 // Maximum number of ADC channels
+#include "sys.h"
+
+#define ADC_CHANNEL_MAX 18 ///< Maximum number of ADC channels
typedef enum
{
IN0 = BIT0,
@@ -39,10 +41,11 @@ typedef enum
IN13 = BIT13,
IN14 = BIT14,
IN15 = BIT15,
- INTEMP = BIT16,
- INVREF = BIT18,
- INVBAT = BIT17,
-} adc_num_e; // ADC channel number
+ IN16 = BIT16,
+ INTEMP = BIT17,
+ INVBAT = BIT18,
+ INVREF = BIT19,
+} adc_num_e; ///< ADC channel number
typedef enum
{
@@ -50,7 +53,7 @@ typedef enum
ADCS_2,
ADCS_3,
ADCS_MAX,
-} adcs_e; // ADC number
+} adcs_e; ///< ADC number
typedef union
{
@@ -76,20 +79,24 @@ typedef union
uint32_t invref : 1;
uint32_t intemp : 1;
};
-} adcs_channels_u; // ADC channels
+} adcs_channels_u; ///< ADC channels
typedef struct
{
- ADC_TypeDef *adc; // ADC peripheral
- DMA_TypeDef *dma; // DMA peripheral
- uint32_t dma_channel; // DMA channel
- adcs_channels_u channels; // ADC channels
- uint32_t ovr_count; // ADC overflow count
+ ADC_TypeDef *adc; ///< ADC peripheral
+ DMA_TypeDef *dma; ///< DMA peripheral
+ uint32_t dma_channel; ///< DMA channel
+ adcs_channels_u channels; ///< ADC channels
+ uint32_t ovr_count; ///< ADC overflow count
- uint8_t adc_cct; // Channel single acquisition count
- uint8_t adc_chans_count; // Number of channels
- uint16_t adc_sum; // Channel acquisition count
- __IO uint16_t *adc_value; // Address to store ADC conversion results
+ uint16_t adc_cct; ///< Channel single acquisition count
+ uint8_t adc_chans_count; ///< Number of channels
+ uint16_t adc_sum; ///< Channel acquisition count
+ __IO uint16_t *adc_value; ///< Address to store ADC conversion results
+
+ utime_ticks_t median_average_ticks; ///< Median average filtering ticks
+ utime_ticks_t median_ticks; ///< Median filtering ticks
+ utime_ticks_t average_ticks; ///< Average filtering ticks
} adcs_t;
/**
@@ -104,7 +111,7 @@ typedef struct
* @param adc_cct The ADC continuous conversion mode.
* @param channels The number of ADC channels to be converted.
*/
-extern void adc_init(adcs_e num, ADC_TypeDef *adc, DMA_TypeDef *dma, uint32_t dma_channel, uint8_t adc_cct, uint32_t channels);
+extern void adc_init(adcs_e num, ADC_TypeDef *adc, DMA_TypeDef *dma, uint32_t dma_channel, uint16_t adc_cct, uint32_t channels);
/**
* @brief Starts the ADC conversion.
@@ -223,4 +230,4 @@ extern void adc_env_callback(adcs_e num);
* @param num The ADC number.
*/
extern void adc_dma_callback(adcs_e num);
-#endif // __ADCS_H__
+#endif ///< __ADCS_H__
diff --git a/User/system/bsp/bsp.h b/User/system/bsp/bsp.h
index 886c3c0..4ad1644 100644
--- a/User/system/bsp/bsp.h
+++ b/User/system/bsp/bsp.h
@@ -11,6 +11,7 @@
*/
#ifndef __BSP_H__
#define __BSP_H__
+#include "dma.h"
#include "gpios.h"
#include "adcs.h"
@@ -22,30 +23,10 @@
#include "spis.h"
#include "i2cs.h"
-/**
- * @brief Clears the flags of a DMA channel
- * @param DMAX DMAx register base
- * @param CHx DMA channel number
- * @param Flag a boolean variable that indicates if the transfer is complete
- * @note This function should be called within the interrupt service routine of the DMA channel
- */
-#define DMA_ClEAR_FLAG(DMAX, CHx, Flag) \
- do \
- { \
- if (LL_DMA_IsActiveFlag_TC##CHx(DMAX)) \
- { \
- LL_DMA_ClearFlag_TC##CHx(DMAX); \
- LL_DMA_ClearFlag_GI##CHx(DMAX); \
- Flag = TRUE; \
- } \
- if (LL_DMA_IsActiveFlag_TE##CHx(DMAX)) \
- { \
- LL_DMA_ClearFlag_TE##CHx(DMAX); \
- } \
- if (LL_DMA_IsActiveFlag_GI##CHx(DMAX)) \
- { \
- LL_DMA_ClearFlag_GI##CHx(DMAX); \
- } \
- } while (__LINE__ == -1)
+///< 定义回调函数类型
+typedef void (*pvd_irq_handle_cb)(void);
-#endif // __BSP_H__
+extern void pvd_configuration(uint32_t pwr_level, pvd_irq_handle_cb call); ///< Configures the Programmable Voltage Detector (PVD) module
+extern void pvd_irq_handle(void); ///< Handles the PVD interrupt
+extern void disable_debug_interface(void); ///< Disables the debug interface
+#endif ///< __BSP_H__
diff --git a/User/system/bsp/dacs.c b/User/system/bsp/dacs.c
deleted file mode 100644
index 04c96dc..0000000
--- a/User/system/bsp/dacs.c
+++ /dev/null
@@ -1,49 +0,0 @@
-/**
- * @file dacs.c
- * @brief This file contains the implementation of the DAC module.
- * It provides functions to initialize and de-initialize a DAC instance,
- * as well as write a 16-bit value to the specified DAC channel.
- * @author xxx
- * @date 2023-12-27 14:44:03
- * @copyright Copyright (c) 2024 by xxx, All Rights Reserved.
- */
-#include "dacs.h"
-
-/**
- * @brief Writes a 16-bit value to the specified DAC channel
- *
- * @param dac pointer to the DAC instance
- * @param value 16-bit value to write to the DAC
- */
-static void _out(dac_t *dac, uint16_t value)
-{
- DAC_OUT(dac->dac, dac->dac_channel, value);
-}
-
-/**
- * @brief Initializes a DAC instance
- *
- * @param dac pointer to the DAC instance
- * @param dac_channel DAC channel to use
- * @return pointer to the initialized DAC instance
- */
-dac_t *dac_create(DAC_TypeDef *dac, uint16_t dac_channel)
-{
- dac_t *handle = (dac_t *)osel_mem_alloc(sizeof(dac_t));
- DBG_ASSERT(handle != NULL __DBG_LINE);
- handle->dac = dac;
- handle->dac_channel = dac_channel;
-
- handle->out = _out;
- return handle;
-}
-
-/**
- * @brief De-initializes a DAC instance
- *
- * @param dac pointer to the DAC instance
- */
-void dac_free(dac_t *dac)
-{
- osel_mem_free(dac);
-}
diff --git a/User/system/bsp/dma.h b/User/system/bsp/dma.h
new file mode 100644
index 0000000..2ce0399
--- /dev/null
+++ b/User/system/bsp/dma.h
@@ -0,0 +1,135 @@
+#ifndef __DMA_H__
+#define __DMA_H__
+
+/**
+ * @brief 清除DMA传输完成标志
+ * @param {DMA_HandleTypeDef} *DMAX DMA总线句柄
+ * @param {uint32_t} CHx DMA通道号
+ * @return {*} 操作结果
+ * @note: 该宏用于清除DMA总线的传输完成标志。它首先检查DMA总线的传输完成标志是否已置位,如果已置位,则清除该标志。
+ */
+#define DMA_ClEAR_FLAG_TC(DMAX, CHx) \
+ do \
+ { \
+ if (LL_DMA_IsActiveFlag_TC##CHx(DMAX)) \
+ { \
+ LL_DMA_ClearFlag_TC##CHx(DMAX); \
+ } \
+ } while (__LINE__ == -1)
+
+/**
+ * @brief 清除DMA传输错误标志
+ * @param {DMA_HandleTypeDef} *DMAX DMA总线句柄
+ * @param {uint32_t} CHx DMA通道号
+ * @return {*} 操作结果
+ * @note: 该宏用于清除DMA总线的传输错误标志。它首先检查DMA总线的传输错误标志是否已置位,如果已置位,则清除该标志。
+ */
+#define DMA_ClEAR_FLAG_TE(DMAX, CHx) \
+ do \
+ { \
+ if (LL_DMA_IsActiveFlag_TE##CHx(DMAX)) \
+ { \
+ LL_DMA_ClearFlag_TE##CHx(DMAX); \
+ } \
+ } while (__LINE__ == -1)
+
+/**
+ * @file uarts.c
+ * @brief This file contains the implementation of DMA_CLEAR_FLAG_TC_CHANNEL macro.
+ */
+
+/**
+ * @brief Clear the Transfer Complete (TC) flag of a specific DMA channel.
+ *
+ * @param dma The DMA peripheral.
+ * @param channel The DMA channel number.
+ */
+#define DMA_CLEAR_FLAG_TC_CHANNEL(dma, channel) \
+ switch (channel) \
+ { \
+ case LL_DMA_CHANNEL_1: \
+ DMA_ClEAR_FLAG_TC(dma, 1); \
+ break; \
+ case LL_DMA_CHANNEL_2: \
+ DMA_ClEAR_FLAG_TC(dma, 2); \
+ break; \
+ case LL_DMA_CHANNEL_3: \
+ DMA_ClEAR_FLAG_TC(dma, 3); \
+ break; \
+ case LL_DMA_CHANNEL_4: \
+ DMA_ClEAR_FLAG_TC(dma, 4); \
+ break; \
+ case LL_DMA_CHANNEL_5: \
+ DMA_ClEAR_FLAG_TC(dma, 5); \
+ break; \
+ case LL_DMA_CHANNEL_6: \
+ DMA_ClEAR_FLAG_TC(dma, 6); \
+ break; \
+ case LL_DMA_CHANNEL_7: \
+ DMA_ClEAR_FLAG_TC(dma, 7); \
+ break; \
+ default: \
+ break; \
+ }
+
+/**
+ * @brief Clear the Transfer Error (TE) flag for the specified DMA channel.
+ *
+ * @param dma The DMA peripheral.
+ * @param channel The DMA channel number.
+ */
+#define DMA_CLEAR_FLAG_TE_CHANNEL(dma, channel) \
+ switch (channel) \
+ { \
+ case 1: \
+ DMA_ClEAR_FLAG_TE(dma, 1); \
+ break; \
+ case 2: \
+ DMA_ClEAR_FLAG_TE(dma, 2); \
+ break; \
+ case 3: \
+ DMA_ClEAR_FLAG_TE(dma, 3); \
+ break; \
+ case 4: \
+ DMA_ClEAR_FLAG_TE(dma, 4); \
+ break; \
+ case 5: \
+ DMA_ClEAR_FLAG_TE(dma, 5); \
+ break; \
+ case 6: \
+ DMA_ClEAR_FLAG_TE(dma, 6); \
+ break; \
+ case 7: \
+ DMA_ClEAR_FLAG_TE(dma, 7); \
+ break; \
+ default: \
+ break; \
+ }
+
+/**
+ * @brief Clears the flags of a DMA channel
+ * @param DMAX DMAx register base
+ * @param CHx DMA channel number
+ * @param Flag a boolean variable that indicates if the transfer is complete
+ * @note This function should be called within the interrupt service routine of the DMA channel
+ */
+#define DMA_ClEAR_FLAG(DMAX, CHx, Flag) \
+ do \
+ { \
+ if (LL_DMA_IsActiveFlag_TC##CHx(DMAX)) \
+ { \
+ LL_DMA_ClearFlag_TC##CHx(DMAX); \
+ LL_DMA_ClearFlag_GI##CHx(DMAX); \
+ Flag = TRUE; \
+ } \
+ if (LL_DMA_IsActiveFlag_TE##CHx(DMAX)) \
+ { \
+ LL_DMA_ClearFlag_TE##CHx(DMAX); \
+ } \
+ if (LL_DMA_IsActiveFlag_GI##CHx(DMAX)) \
+ { \
+ LL_DMA_ClearFlag_GI##CHx(DMAX); \
+ } \
+ } while (__LINE__ == -1)
+
+#endif // __DMA_H__
diff --git a/User/system/bsp/eeprom.c b/User/system/bsp/eeprom.c
deleted file mode 100644
index 6be9a42..0000000
--- a/User/system/bsp/eeprom.c
+++ /dev/null
@@ -1,91 +0,0 @@
-/**
- * @file eeprom.c
- * @author xxx
- * @date 2023-11-16 10:28:47
- * @brief STM32L072xx EEPROM 驱动
- * @copyright Copyright (c) 2023 by xxx, All Rights Reserved.
- */
-#include "eeprom.h"
-#include "main.h"
-
-#ifdef STM32L072xx
-#define PEKEY1 0x89ABCDEF // FLASH_PEKEYR
-#define PEKEY2 0x02030405 // FLASH_PEKEYR
-
-#define LOCK __enable_irq(); // 系统开全局中断
-#define UNLOCK __disable_irq(); // 系统关全局中断
-
-/**
- * @brief 用于配置读取和写入EEPROM的函数
- * @param {uint32_t} read_addr - 读取地址
- * @param {uint8_t} *data - 存储数据的指针
- * @param {uint16_t} length - 读取或写入的数据长度
- * @return {*}
- * @note: 这些函数用于在特定的地址读取或写入数据到EEPROM中。地址和数据以字节为单位,长度以字节为单位。
- */
-void chip_eeprom_config_read(uint32_t read_addr, uint8_t *data, uint16_t length)
-{
- uint8_t *wAddr;
- wAddr = (uint8_t *)(read_addr);
- while (length--)
- {
- *data++ = *wAddr++;
- }
-}
-
-/**
- * @brief 用于配置写入EEPROM的函数
- * @param {uint32_t} write_addr - 写入地址
- * @param {uint8_t} *data - 存储数据的指针
- * @param {uint16_t} length - 写入的数据长度
- * @return {*}
- * @note: 这些函数用于在特定的地址写入数据到EEPROM中。地址和数据以字节为单位,长度以字节为单位。在写入数据之前,需要先解锁EEPROM,写入数据,然后锁定EEPROM。
- */
-void chip_eeprom_config_write(uint32_t write_addr, uint8_t *data, uint16_t length)
-{
- uint8_t *addr;
- addr = (uint8_t *)(write_addr);
- UNLOCK
- FLASH->PDKEYR = PEKEY1;
- FLASH->PDKEYR = PEKEY2;
- while (FLASH->PECR & FLASH_PECR_PELOCK)
- ;
-
- while (length--)
- {
- *addr++ = *data++;
- while (FLASH->SR & FLASH_SR_BSY)
- ;
- }
- FLASH->PECR |= FLASH_PECR_PELOCK;
- LOCK
-}
-
-#endif // STM32L072xx
-
-#ifdef STM32L476xx
-
-/**
- * @brief 用于配置读取和写入SRAM2的函数
- * @param {uint32_t} read_addr - 读取地址
- * @param {uint8_t} *data - 存储数据的指针
- * @param {uint16_t} length - 读取或写入的数据长度
- * @return {*}
- * @note: 这些函数用于在特定的地址读取或写入数据到SRAM2中。地址和数据以字节为单位,长度以字节为单位。
- */
-void chip_eeprom_config_read(uint32_t read_addr, uint8_t *data, uint16_t length)
-{
-}
-
-/**
- * @brief 用于配置写入SRAM2的函数
- * @param {uint32_t} write_addr - 写入地址 从0开始
- * @param {uint8_t} *data - 存储数据的指针
- * @param {uint16_t} length - 写入的数据长度
- * @return {*}
- * @note: 这些函数用于在特定的地址写入数据到SRAM2中。地址和数据以字节为单位,长度以字节为单位。
- */
-void chip_eeprom_config_write(uint32_t write_addr, uint8_t *data, uint16_t length)
-{
-}
-#endif // STM32L476xx
diff --git a/User/system/bsp/eeprom.h b/User/system/bsp/eeprom.h
index 41bb951..42ea792 100644
--- a/User/system/bsp/eeprom.h
+++ b/User/system/bsp/eeprom.h
@@ -2,6 +2,6 @@
#define __EEPROM_H__
#include "lib.h"
-extern void chip_eeprom_config_read(uint32_t read_addr, uint8_t *data, uint16_t length); // 读取数据
-extern void chip_eeprom_config_write(uint32_t write_addr, uint8_t *data, uint16_t length); // 写入数据
-#endif // __EEPROM_H__
+extern void chip_eeprom_config_read(uint32_t read_addr, uint8_t *data, uint16_t length); ///< 读取数据
+extern void chip_eeprom_config_write(uint32_t write_addr, uint8_t *data, uint16_t length); ///< 写入数据
+#endif ///< __EEPROM_H__
diff --git a/User/system/bsp/flash.c b/User/system/bsp/flash.c
deleted file mode 100644
index 8855cb7..0000000
--- a/User/system/bsp/flash.c
+++ /dev/null
@@ -1,530 +0,0 @@
-/**
- * @file flash.c
- * @author xxx
- * @date 2024-02-07 11:49:34
- * @brief
- * @copyright Copyright (c) 2024 by xxx, All Rights Reserved.
- * @attention
- *
- * ST 的官方驱动 LL 库并没有 flash 驱动。这里自己实现。
- *
- * 1. 由于在 stm32l4xx_ll_system.h 中存在部分 FLASH 操作函数(ACR寄存器的处理)且不全面
- * 因此这里需要额外处理(重命名)
- *
- * 2. Main memory
- * (1) FLASH_ACR 完成
- * (2) FLASH_PDKEYR 完成
- * (3) FLASH_KEYR 完成
- * (4) FLASH_OPTKEYR 完成
- * (5) FLASH_SR 完成
- * (6) FLASH_CR 完成
- * (7) FLASH_ECCR 完成
- * (8) FLASH_OPTR 未完成
- * (9) FLASH_PCROP1SR 未完成
- * 后续寄存器 均未完成
- * 3. Information block
- * - System memory
- * - OTP area
- * - Option bytes
- * 4. 根据 HAL 库的实现,相比于与手册的推荐流程,擦写的执行序列还有其他操作。
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- ******************************************************************************
- */
-/* Includes ------------------------------------------------------------------*/
-#include "flash.h"
-#include "stm32l4xx_ll_rcc.h"
-#include "stm32l4xx_ll_system.h"
-#include "stm32l4xx_ll_pwr.h"
-#ifdef USE_FULL_ASSERT
-#include "stm32_assert.h"
-#else
-#define assert_param(expr) ((void)0U)
-#endif /* USE_FULL_ASSERT */
-
-#define WHILE_MAX 10000U
-/** @addtogroup STM32L4xx_LL_Driver
- * @{
- */
-
-/** @addtogroup FLASH_LL
- * @{
- */
-
-/* Private types -------------------------------------------------------------*/
-/* Private variables ---------------------------------------------------------*/
-/* Private constants ---------------------------------------------------------*/
-/** @addtogroup FLASH_LL_Private_Constants
- * @{
- */
-
-/**
- * @}
- */
-
-/* Private macros ------------------------------------------------------------*/
-/** @addtogroup FLASH_LL_Private_Macros
- * @{
- */
-
-#define IS_LL_FLASH_WRITE_ADDR(__ADDR__) ((__ADDR__) % LL_FLASH_ALIGNMENT_MIN_SIZE == 0)
-
-/**
- * @}
- */
-/* Private function prototypes -----------------------------------------------*/
-/** @defgroup FLASH_LL_Private_Functions FLASH Private functions
- * @{
- */
-
-/**
- * @}
- */
-
-/* Exported functions --------------------------------------------------------*/
-/** @addtogroup FLASH_LL_Exported_Functions
- * @{
- */
-/**
- * @brief Clear All Error in SR
- * @param FLASHx FLASH Instance
- * @retval None
- */
-void LL_FLASH_ClearAllErrorFlag(void)
-{
- LL_FLASH_ClearFlag_OPTVERR(FLASH);
- LL_FLASH_ClearFlag_RDERR(FLASH);
- LL_FLASH_ClearFlag_FASTERR(FLASH);
- LL_FLASH_ClearFlag_MISERR(FLASH);
- LL_FLASH_ClearFlag_PGSERR(FLASH);
- LL_FLASH_ClearFlag_SIZERR(FLASH);
- LL_FLASH_ClearFlag_PGAERR(FLASH);
- LL_FLASH_ClearFlag_WRPERR(FLASH);
- LL_FLASH_ClearFlag_PROGERR(FLASH);
- LL_FLASH_ClearFlag_OPERR(FLASH);
-}
-
-/**
- * @brief Flush the instruction and data caches.
- * @retval None
- */
-void LL_FLASH_FlushCaches(void)
-{
- /* Flush instruction cache */
- if (LL_FLASH_IsEnabledInstructionCache(FLASH))
- {
- LL_FLASH_DisableInstructionCache(FLASH);
- /* Reset instruction cache */
- LL_FLASH_InstructionCacheReset(FLASH);
- /* Enable instruction cache */
- LL_FLASH_EnableInstructionCache(FLASH);
- }
-
- /* Flush data cache */
- if (LL_FLASH_IsEnabledDataCache(FLASH))
- {
- LL_FLASH_ZCS_DisableDataCache(FLASH);
- /* Reset data cache */
- LL_FLASH_DataCacheReset(FLASH);
- /* Enable data cache */
- LL_FLASH_ZCS_EnableDataCache(FLASH);
- }
-}
-
-/**
- * @brief Erase Page
- * @param pageno Page number
- * @retval None
- */
-ErrorStatus LL_FLASH_ErasePage(uint32_t pageno)
-{
- uint16_t count = 0;
- /* Check that no Flash memory operation is ongoing by checking the BSY bit */
- while (LL_FLASH_IsActiveFlag_BSY(FLASH))
- {
- if (count++ > WHILE_MAX)
- {
- return ERROR;
- }
- }
- count = 0;
-
- /* Check and clear all error programming flags due to a previous programming. If not, PGSERR is set. */
- LL_FLASH_ClearAllErrorFlag();
-
- /* Set the PER bit and select the page you wish to erase (PNB) with the associated bank (BKER) in the Flash control register (FLASH_CR). */
- LL_FLASH_EnablePageErase(FLASH);
-
- if (pageno >= LL_FLASH_BANK1_PAGE_NUM)
- {
- pageno -= LL_FLASH_BANK1_PAGE_NUM;
- LL_FLASH_SetErasePageBank(FLASH, LL_FLASH_BANK2);
- }
- else
- {
- LL_FLASH_SetErasePageBank(FLASH, LL_FLASH_BANK1);
- }
-
- LL_FLASH_SetErasePageNo(FLASH, pageno);
-
- /* Set the STRT bit in the FLASH_CR register. */
- LL_FLASH_EraseStart(FLASH);
-
- /* Wait for the BSY bit to be cleared in the FLASH_SR register. */
- while (LL_FLASH_IsActiveFlag_BSY(FLASH))
- {
- if (count++ > WHILE_MAX)
- {
- return ERROR;
- }
- }
- count = 0;
-
- /* 完成只有需要清除擦除标志. */
- LL_FLASH_DisablePageErase(FLASH);
-
- /* Flush the caches to be sure of the data consistency */
- LL_FLASH_FlushCaches();
-
- return SUCCESS;
-}
-
-/**
- * @brief Erase bank
- * @param bank This parameter can be one of the following values:
- * @arg @ref LL_FLASH_BANK1
- * @arg @ref LL_FLASH_BANK2
- * @retval None
- */
-ErrorStatus LL_FLASH_EraseBank(uint32_t bank)
-{
- uint16_t count = 0;
- /* Check that no Flash memory operation is ongoing by checking the BSY bit */
- while (LL_FLASH_IsActiveFlag_BSY(FLASH))
- {
- if (count++ > WHILE_MAX)
- {
- return ERROR;
- }
- }
- count = 0;
-
- /* Check and clear all error programming flags due to a previous programming. If not, PGSERR is set. */
- LL_FLASH_ClearAllErrorFlag();
-
- /* Set the MER1 bit or/and MER2 (depending on the bank) in the Flash control register (FLASH_CR).
- Both banks can be selected in the same operation. */
- if (bank == LL_FLASH_BANK1)
- {
- LL_FLASH_EnableBank1Erase(FLASH);
- }
- else
- {
- LL_FLASH_EnableBank2Erase(FLASH);
- }
-
- /* Set the STRT bit in the FLASH_CR register. */
- LL_FLASH_EraseStart(FLASH);
-
- /* Wait for the BSY bit to be cleared in the FLASH_SR register. */
- while (LL_FLASH_IsActiveFlag_BSY(FLASH))
- {
- if (count++ > WHILE_MAX)
- {
- return ERROR;
- }
- }
- count = 0;
-
- /* 完成只有需要清除擦除标志. */
- LL_FLASH_DisableBank1Erase(FLASH);
- LL_FLASH_DisableBank2Erase(FLASH);
-
- /* Flush the caches to be sure of the data consistency */
- LL_FLASH_FlushCaches();
- return SUCCESS;
-}
-
-/**
- * @brief Erase Chip
- * @param None
- * @retval None
- */
-ErrorStatus LL_FLASH_EraseChip(void)
-{
- uint16_t count = 0;
- /* Check that no Flash memory operation is ongoing by checking the BSY bit */
- while (LL_FLASH_IsActiveFlag_BSY(FLASH))
- {
- if (count++ > WHILE_MAX)
- {
- return ERROR;
- }
- }
- count = 0;
-
- /* Check and clear all error programming flags due to a previous programming. If not, PGSERR is set. */
- LL_FLASH_ClearAllErrorFlag();
-
- /* Set the MER1 bit or/and MER2 (depending on the bank) in the Flash control register (FLASH_CR).
- Both banks can be selected in the same operation. */
- LL_FLASH_EnableBank1Erase(FLASH);
- LL_FLASH_EnableBank2Erase(FLASH);
-
- /* Set the STRT bit in the FLASH_CR register. */
- LL_FLASH_EraseStart(FLASH);
-
- /* Wait for the BSY bit to be cleared in the FLASH_SR register. */
- while (LL_FLASH_IsActiveFlag_BSY(FLASH))
- {
- if (count++ > WHILE_MAX)
- {
- return ERROR;
- }
- }
- count = 0;
-
- /* 完成只有需要清除擦除标志. */
- LL_FLASH_DisableBank1Erase(FLASH);
- LL_FLASH_DisableBank2Erase(FLASH);
-
- /* Flush the caches to be sure of the data consistency */
- LL_FLASH_FlushCaches();
- return SUCCESS;
-}
-
-/**
- * @brief Program Double Word
- * @param address specifies the address to be programmed.
- * @param data specifies the data to be programmed.
- * @retval An ErrorStatus enumeration value:
- * - SUCCESS: Write successfully
- * - ERROR: error
- */
-ErrorStatus LL_FLASH_ProgramDoubleWord(uint32_t address, uint64_t data)
-{
- assert_param(!IS_LL_FLASH_WRITE_ADDR(address));
- uint16_t count = 0;
- /* Check that no Flash memory operation is ongoing by checking the BSY bit */
- while (LL_FLASH_IsActiveFlag_BSY(FLASH))
- {
- if (count++ > WHILE_MAX)
- {
- return ERROR;
- }
- }
- count = 0;
- /* Check and clear all error programming flags due to a previous programming. If not, PGSERR is set. */
- LL_FLASH_ClearAllErrorFlag();
-
- /* Set the PG bit in the Flash control register (FLASH_CR). */
- LL_FLASH_EnableProgram(FLASH);
-
- /* Perform the data write operation at the desired memory address, inside main memory
- block or OTP area. Only double word can be programmed. */
- /* Program the double word */
- *(__IO uint32_t *)address = (uint32_t)data;
- *(__IO uint32_t *)(address + 4U) = (uint32_t)(data >> 32);
-
- /* Check that no Flash memory operation is ongoing by checking the BSY bit */
- while (LL_FLASH_IsActiveFlag_BSY(FLASH))
- {
- if (count++ > WHILE_MAX)
- {
- return ERROR;
- }
- }
- count = 0;
- /* Check that EOP flag is set in the FLASH_SR register (meaning that the programming
- operation has succeed), and clear it by software. */
- if (LL_FLASH_IsActiveFlag_EOP(FLASH))
- {
- LL_FLASH_ClearFlag_EOP(FLASH);
- }
-
- /* Clear the PG bit in the FLASH_CR register if there no more programming request anymore. */
- LL_FLASH_DisableProgram(FLASH);
-
- /* Flush the caches to be sure of the data consistency */
- LL_FLASH_FlushCaches();
-
- return SUCCESS;
-}
-
-/**
- * @brief Program
- * @param address specifies the address to be programmed.
- * @param data specifies the data to be programmed.
- * @param num specifies the data number
- * @retval An ErrorStatus enumeration value:
- * - SUCCESS: Write successfully
- * - ERROR: error
- */
-ErrorStatus LL_FLASH_Program(uint32_t address, uint8_t data[], uint32_t num)
-{
- static uint64_t DataT = 0;
- uint32_t T = 0, S = 0;
- uint16_t count = 0;
- assert_param(!IS_LL_FLASH_WRITE_ADDR(address));
-
- if (num == 0)
- {
- return SUCCESS;
- }
-
- /* Check that no Flash memory operation is ongoing by checking the BSY bit */
- while (LL_FLASH_IsActiveFlag_BSY(FLASH))
- {
- if (count++ > WHILE_MAX)
- {
- return ERROR;
- }
- }
- count = 0;
- /* Check and clear all error programming flags due to a previous programming. If not, PGSERR is set. */
- LL_FLASH_ClearAllErrorFlag();
-
- /* Set the PG bit in the Flash control register (FLASH_CR). */
- LL_FLASH_EnableProgram(FLASH);
-
- /* Perform the data write operation at the desired memory address, inside main memory
- block or OTP area. Only double word can be programmed. */
- T = num;
- while (num > 0)
- {
- DataT = 0;
- if (num >= 8)
- {
- for (int i = 0; i < LL_FLASH_ALIGNMENT_MIN_SIZE; i++)
- {
- DataT = DataT << 8;
- DataT |= data[S + 7 - i];
- }
- S += LL_FLASH_ALIGNMENT_MIN_SIZE;
- num -= LL_FLASH_ALIGNMENT_MIN_SIZE;
- }
- else
- {
- for (int i = 0; i < num; i++)
- {
- DataT = DataT << 8;
- DataT |= data[T - 1 - i];
- }
- num = 0;
- }
-
- /* Program the double word */
- *(__IO uint32_t *)address = (uint32_t)DataT;
- *(__IO uint32_t *)(address + 4U) = (uint32_t)(DataT >> 32);
-
- /* Check that no Flash memory operation is ongoing by checking the BSY bit */
- while (LL_FLASH_IsActiveFlag_BSY(FLASH))
- {
- if (count++ > WHILE_MAX)
- {
- return ERROR;
- }
- }
- count = 0;
-
- /* Check that EOP flag is set in the FLASH_SR register (meaning that the programming
- operation has succeed), and clear it by software. */
- if (LL_FLASH_IsActiveFlag_EOP(FLASH))
- {
- LL_FLASH_ClearFlag_EOP(FLASH);
- }
-
- address += LL_FLASH_ALIGNMENT_MIN_SIZE;
- }
-
- /* Clear the PG bit in the FLASH_CR register if there no more programming request anymore. */
- LL_FLASH_DisableProgram(FLASH);
-
- /* Flush the caches to be sure of the data consistency */
- LL_FLASH_FlushCaches();
-
- return SUCCESS;
-}
-
-/**
- * @}
- */
-
-/** @addtogroup FLASH_LL_Private_Functions
- * @{
- */
-/**
- * @brief Fast program a row double-word (64-bit) at a specified address.
- * @param address: specifies the address to be programmed.
- * @param DataAddress: specifies the address where the data are stored.
- * @retval None
- */
-void LL_FLASH_ProgramFast(uint32_t address, uint32_t DataAddress)
-{
- uint8_t row_index = (2 * LL_FLASH_ROW_SIZE);
- __IO uint32_t *dest_addr = (__IO uint32_t *)address;
- __IO uint32_t *src_addr = (__IO uint32_t *)DataAddress;
-
- /* Check the parameters */
- assert_param(IS_FLASH_MAIN_MEM_ADDRESS(address));
-
- /* Set FSTPG bit */
- LL_FLASH_EnableFastProgram(FLASH);
-
- /* Disable interrupts to avoid any interruption during the loop */
- __disable_irq();
-
- /* Program the double word of the row */
- do
- {
- *dest_addr = *src_addr;
- dest_addr++;
- src_addr++;
- row_index--;
- } while (row_index != 0U);
-
- /* Re-enable the interrupts */
- __enable_irq();
-
- LL_FLASH_DisableFastProgram(FLASH);
-}
-
-/**
- * @brief Fast program a row double-word (64-bit) at a specified address.
- * @param address: specifies the address to be programmed.
- * @param data: specifies the data to be programmed.
- * @retval None
- */
-ErrorStatus LL_FLASH_Read(uint32_t address, uint8_t data[], uint32_t num)
-{
- if (num == 0)
- {
- return SUCCESS;
- }
- for (uint32_t i = 0; i < num; i++)
- {
- data[i] = *(__IO uint8_t *)(address + i);
- }
-
- return SUCCESS;
-}
-
-/**
- * @}
- */
-
-/**
- * @}
- */
-
-/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/User/system/bsp/flash.h b/User/system/bsp/flash.h
index 8051762..b4b693a 100644
--- a/User/system/bsp/flash.h
+++ b/User/system/bsp/flash.h
@@ -52,7 +52,7 @@ extern "C"
#endif
/* Includes ------------------------------------------------------------------*/
-#include "stm32l4xx.h"
+#include "osel_arch.h"
/** @addtogroup STM32L4xx_LL_Driver
* @{
@@ -1699,7 +1699,7 @@ FLASH_ACR */
ErrorStatus LL_FLASH_Program(uint32_t address, uint8_t data[], uint32_t num);
ErrorStatus LL_FLASH_Read(uint32_t address, uint8_t data[], uint32_t num);
void LL_FLASH_ProgramFast(uint32_t address, uint32_t DataAddress);
-
+ void LL_FLASH_EraseAddress(uint32_t address, uint16_t size);
/**
* @}
*/
diff --git a/User/system/bsp/gpios.c b/User/system/bsp/gpios.c
deleted file mode 100644
index cb59b80..0000000
--- a/User/system/bsp/gpios.c
+++ /dev/null
@@ -1,76 +0,0 @@
-#include "gpios.h"
-#include "gpio.h"
-/**
- * @brief 设置GPIO引脚为高电平
- * @param {gpio_t} gpio - GPIO对象
- * @note: 用于设置指定GPIO引脚为高电平。
- */
-static void _set(gpio_t gpio)
-{
- GPIO_SET(gpio.port, gpio.pin);
-}
-
-/**
- * @brief 设置GPIO引脚为低电平
- * @param {gpio_t} gpio - GPIO对象
- * @note: 用于设置指定GPIO引脚为低电平。
- */
-static void _reset(gpio_t gpio)
-{
- GPIO_RESET(gpio.port, gpio.pin);
-}
-
-/**
- * @brief 切换GPIO引脚状态
- * @param {gpio_t} gpio - GPIO对象
- * @note: 用于切换指定GPIO引脚的状态,即高电平变为低电平,低电平变为高电平。
- */
-static void _toggle(gpio_t gpio)
-{
- GPIO_TOGGLE(gpio.port, gpio.pin);
-}
-
-/**
- * @brief 读取GPIO引脚状态
- * @param {gpio_t} gpio - GPIO对象
- * @return {*} - GPIO引脚当前状态,即0表示低电平,1表示高电平
- * @note: 用于读取指定GPIO引脚的状态,即返回0或1。
- */
-static uint8_t _read(gpio_t gpio)
-{
- return (uint8_t)GPIO_READ(gpio.port, gpio.pin);
-}
-
-/**
- * @brief 创建GPIO对象
- * @param {GPIO_TypeDef} *port - GPIO寄存器指针
- * @param {uint16_t} pin - 引脚号
- * @return {gpio_t *} - 创建的GPIO对象指针
- * @note: 用于创建一个GPIO对象,用于操作特定端口和引脚的GPIO功能。
- */
-gpio_t *gpio_create(GPIO_TypeDef *port, uint16_t pin)
-{
- gpio_t *gpio = (gpio_t *)osel_mem_alloc(sizeof(gpio_t));
- DBG_ASSERT(gpio != NULL __DBG_LINE);
- gpio->port = port;
- gpio->pin = pin;
- gpio->set = _set;
- gpio->reset = _reset;
- gpio->toggle = _toggle;
- gpio->read = _read;
- return gpio;
-}
-
-/**
- * @brief 释放GPIO对象
- * @param {gpio_t} *gpio - GPIO对象指针
- * @return {*}
- * @note: 用于释放一个GPIO对象,释放后不能再使用该对象。
- */
-void gpio_free(gpio_t *gpio)
-{
- if (gpio != NULL)
- {
- osel_mem_free(gpio);
- }
-}
diff --git a/User/system/bsp/gpios.h b/User/system/bsp/gpios.h
index 9f71165..35b86fc 100644
--- a/User/system/bsp/gpios.h
+++ b/User/system/bsp/gpios.h
@@ -92,8 +92,8 @@
*/
typedef struct GPIO
{
- GPIO_TypeDef *port; // The GPIO port.
- uint16_t pin; // The GPIO pin.
+ GPIO_TypeDef *port; ///< The GPIO port.
+ uint16_t pin; ///< The GPIO pin.
/**
* @brief Set the GPIO pin to high.
@@ -141,4 +141,4 @@ extern gpio_t *gpio_create(GPIO_TypeDef *port, uint16_t pin);
*/
extern void gpio_free(gpio_t *gpio);
-#endif // __GPIOS_H__
+#endif ///< __GPIOS_H__
diff --git a/User/system/bsp/i2cs.c b/User/system/bsp/i2cs.c
deleted file mode 100644
index ee2be33..0000000
--- a/User/system/bsp/i2cs.c
+++ /dev/null
@@ -1,663 +0,0 @@
-#include "i2cs.h"
-#include "main.h"
-
-static inline void delay(i2c_t *handle); // 延时函数
-static inline void _ack(i2c_t *handle); // 应答
-static inline void _nack(i2c_t *handle); // 非应答
-
-/**
- * @brief 启动I2C总线
- * @param {i2c_t} *handle - I2C总线句柄
- * @note: 用于启动I2C总线的操作。在发送或接收数据之前,需要先启动总线。
- */
-static void _start(i2c_t *handle)
-{
- DBG_ASSERT(handle != NULL __DBG_LINE);
- // 获取gpios指针
- i2c_gpio_group_t *gpios = &handle->gpios;
- // 获取scl指针
- gpio_t *scl = gpios->scl;
- // 获取sda指针
- gpio_t *sda = gpios->sda;
- // 设置sda
- gpios->sda->set(*sda);
- // 设置scl
- gpios->scl->set(*scl);
- // 延时
- delay(handle);
- // 重置sda
- gpios->sda->reset(*sda);
- // 延时
- delay(handle);
- // 重置scl
- gpios->scl->reset(*scl);
- // 延时
- delay(handle);
-}
-
-/**
- * @brief 停止I2C总线
- * @param {i2c_t} *handle - I2C总线句柄
- * @note: 用于停止I2C总线的操作。在发送或接收数据之后,需要先停止总线。
- */
-static void _stop(i2c_t *handle)
-{
- DBG_ASSERT(handle != NULL __DBG_LINE);
- i2c_gpio_group_t *gpios = &handle->gpios;
- gpio_t *scl = gpios->scl;
- gpio_t *sda = gpios->sda;
- gpios->scl->reset(*scl);
- gpios->sda->reset(*sda);
- delay(handle);
- gpios->scl->set(*scl);
- gpios->sda->set(*sda);
- delay(handle);
-}
-/**
- * @brief 等待应答信号
- * @param {i2c_t} *handle - I2C总线句柄
- * @return {BOOL} - 等待成功返回TRUE,否则返回FALSE
- * @note: 用于等待I2C总线上发送的应答信号。
- */
-static BOOL _wait_ack(i2c_t *handle)
-{
- DBG_ASSERT(handle != NULL __DBG_LINE);
- uint8_t count = 0;
- i2c_gpio_group_t *gpios = &handle->gpios;
- gpio_t *scl = gpios->scl;
- gpio_t *sda = gpios->sda;
- gpios->sda->set(*sda);
- gpios->scl->set(*scl);
- delay(handle);
- while (gpios->sda->read(*sda))
- {
- count++;
- if (count > 250)
- {
- _stop(handle);
- return FALSE;
- }
- }
- gpios->scl->reset(*scl);
- delay(handle);
- return TRUE;
-}
-
-/**
- * @brief 读取一个字节
- * @param {i2c_t} *handle - I2C总线句柄
- * @param {BOOL} ack - 应答信号标志
- * @return {uint8_t} - 读取到的字节
- * @note: 用于从I2C总线上读取一个字节。在读取一个字节后,需要发送应答信号。
- */
-static uint8_t _read_byte(i2c_t *handle, BOOL ack)
-{
- DBG_ASSERT(handle != NULL __DBG_LINE);
- uint8_t i = 0, receive = 0;
- i2c_gpio_group_t *gpios = &handle->gpios;
- gpio_t *scl = gpios->scl;
- gpio_t *sda = gpios->sda;
- for (i = 0; i < 8; i++)
- {
- gpios->sda->set(*sda);
- gpios->scl->set(*scl);
- receive <<= 1;
- delay(handle);
-
- if (gpios->sda->read(*sda))
- receive++;
-
- gpios->scl->reset(*scl);
- delay(handle);
- }
-
- if (TRUE == ack)
- {
- _ack(handle);
- }
- else
- {
- _nack(handle);
- }
- return receive;
-}
-/**
- * @brief 发送一个字节的数据到I2C总线上
- * @param {i2c_t} *handle I2C总线的句柄
- * @param {uint8_t} data 要发送的字节数据
- * @return {*} 无
- * @note: 该函数用于在I2C总线上发送一个字节的数据。它首先定义了一个循环,用于遍历要发送的字节中的每一位。在循环中,首先检查当前位是否为1,如果是,则设置SDA为1,否则设置SDA为0。然后设置SCL为1,延时1ms。接着将数据右移一位,然后设置SCL为0,延时1ms。当位遍历完后,最后设置SDA为1,以确保正确的结束传输。
- */
-static void _write_byte(i2c_t *handle, uint8_t data)
-{
- // 定义变量i
- uint8_t i = 0;
- // 断言参数handle不为空
- DBG_ASSERT(handle != NULL __DBG_LINE);
- // 定义变量gpios
- i2c_gpio_group_t *gpios = &handle->gpios;
- // 定义变量scl
- gpio_t *scl = gpios->scl;
- // 定义变量sda
- gpio_t *sda = gpios->sda;
- // 遍历每一位
- for (i = 0; i < 8; i++)
- {
- // 如果data的最低位为1
- if (data & 0x80)
- {
- // 设置sda的状态为1
- gpios->sda->set(*sda);
- }
- // 否则,设置sda的状态为0
- else
- {
- // 设置sda的状态为0
- gpios->sda->reset(*sda);
- }
-
- // 设置scl的状态为1
- gpios->scl->set(*scl);
- // 延时1ms
- delay(handle);
- // 将data右移1位
- data <<= 1;
- // 设置scl的状态为0
- gpios->scl->reset(*scl);
- // 延时1ms
- delay(handle);
-
- // 如果i等于7
- if (i == 7)
- {
- // 设置sda的状态为1
- gpios->sda->set(*sda);
- }
- }
-}
-
-/**
- * @brief 发送一个字节的数据到I2C总线上
- * @param {i2c_t} *handle I2C总线的句柄
- * @param {uint16_t} data 要发送的字节数据
- * @return {*} 无
- * @note: 该函数用于在I2C总线上发送一个字节的数据。它首先定义了一个循环,用于遍历要发送的字节中的每一位。在循环中,首先检查当前位是否为1,如果是,则设置SDA为1,否则设置SDA为0。然后设置SCL为1,延时1ms。接着将数据右移一位,然后设置SCL为0,延时1ms。当位遍历完后,最后设置SDA为1,以确保正确的结束传输。
- */
-static void _write_word(i2c_t *handle, uint16_t data)
-{
- // 循环写入2个字节
- for (uint8_t i = 0; i < 2; i++)
- {
- // 将data的第i个字节写入i2c接口
- _write_byte(handle, (uint8_t)(data >> (8 * i)));
- // 等待ACK
- _wait_ack(handle);
- }
-}
-
-/**
- * @brief I2C重置
- * @param {I2C_TypeDef} *I2Cx
- * @return {*}
- * @note 解决I2C总线死锁问题
- */
-static void i2c_reset(i2c_t *handle)
-{
- LL_I2C_Disable(handle->i2c);
- LL_I2C_Enable(handle->i2c);
- handle->dead_count++;
-}
-
-/**
- * @brief 非阻塞模式下使用DMA将数据写入特定内存地址
- * @param {i2c_t} *handle 指向一个i2c_t结构体,其中包含指定I2C的配置信息
- * @param {uint16_t} dev_address 目标设备地址:在数据手册中,设备7位地址值需要向左移动以调用接口
- * @param {uint16_t} mem_address 内部内存地址
- * @param {uint16_t} mem_addsize 内部内存地址大小
- * @param {uint8_t} *data 数据缓冲区的指针
- * @param {uint16_t} size 要发送的数据量
- * @return {*}
- * @note
- */
-static BOOL _write_mem_dma(i2c_t *handle, uint16_t mem_address, uint16_t mem_addsize, uint8_t *data, uint16_t size)
-{
- DBG_ASSERT(handle != NULL __DBG_LINE);
- DBG_ASSERT(data != NULL __DBG_LINE);
- uint16_t count = 2000;
- if (LL_I2C_IsActiveFlag_BUSY(handle->i2c) == 1)
- {
- i2c_reset(handle); // xsh:重置I2C,修复一段时间后无法读写的问题
- return FALSE;
- }
-
- handle->txsize = 0;
- handle->tx_dma_ok = FALSE;
- for (uint8_t i = mem_addsize; i > 0; i--)
- {
- handle->txbuf[handle->txsize++] = (uint8_t)(mem_address >> (8 * (i - 1)));
- }
- osel_memcpy(&handle->txbuf[handle->txsize], data, size);
- handle->txsize += size;
- LL_DMA_SetDataLength(handle->dma, handle->dma_tx_channel, handle->txsize);
- LL_DMA_EnableChannel(handle->dma, handle->dma_tx_channel);
-
- LL_I2C_HandleTransfer(handle->i2c, handle->w_address, LL_I2C_ADDRSLAVE_7BIT, handle->txsize, LL_I2C_MODE_AUTOEND, LL_I2C_GENERATE_START_WRITE);
-
- count = 2000;
- while (!handle->tx_dma_ok)
- {
- if (count-- == 0)
- {
- handle->tx_dma_ok = TRUE;
- return FALSE;
- }
- }
- count = 2000;
- while (!LL_I2C_IsActiveFlag_STOP(handle->i2c))
- {
- if (count-- == 0)
- {
- handle->tx_dma_ok = TRUE;
- return FALSE;
- }
- }
-
- LL_DMA_DisableChannel(handle->dma, handle->dma_tx_channel);
- LL_I2C_ClearFlag_STOP(handle->i2c);
-
- return TRUE;
-}
-
-/**
- * @brief 非阻塞模式下使用DMA从特定内存地址读取数据
- * @param {i2c_t} *handle 指向一个i2c_t结构体,其中包含指定I2C的配置信息
- * @param {uint16_t} dev_address 目标设备地址:在数据手册中,设备7位地址值需要向左移动以调用接口
- * @param {uint16_t} mem_address 内部内存地址
- * @param {uint16_t} mem_addsize 内部内存地址大小
- * @param {uint8_t} *data 数据缓冲区的指针
- * @param {uint16_t} size 要发送的数据量
- * @return {*}
- * @note
- */
-static BOOL _read_mem_dma(i2c_t *handle, uint16_t mem_address, uint16_t mem_addsize, uint8_t *data, uint16_t size)
-{
- DBG_ASSERT(handle != NULL __DBG_LINE);
- DBG_ASSERT(data != NULL __DBG_LINE);
- if (LL_I2C_IsActiveFlag_BUSY(handle->i2c) == 1)
- {
- i2c_reset(handle); // xsh:重置I2C,修复一段时间后无法读写的问题
- return FALSE;
- }
- uint16_t count = 2000;
- handle->txsize = 0;
- handle->tx_dma_ok = FALSE;
- handle->rx_dma_ok = FALSE;
-
- for (uint8_t i = mem_addsize; i > 0; i--)
- {
- handle->txbuf[handle->txsize++] = (uint8_t)(mem_address >> (8 * (i - 1)));
- }
-
- LL_DMA_SetDataLength(handle->dma, handle->dma_tx_channel, handle->txsize);
- LL_DMA_EnableChannel(handle->dma, handle->dma_tx_channel);
-
- LL_I2C_HandleTransfer(handle->i2c, handle->w_address, LL_I2C_ADDRSLAVE_7BIT, handle->txsize, LL_I2C_MODE_SOFTEND, LL_I2C_GENERATE_START_WRITE);
- count = 2000;
- while (!handle->tx_dma_ok)
- {
- if (count-- == 0)
- {
- handle->tx_dma_ok = TRUE;
- return FALSE;
- }
- }
-
- count = 2000;
- while (LL_I2C_IsActiveFlag_TC(handle->i2c) != 1)
- {
- if (count-- == 0)
- {
- handle->tx_dma_ok = TRUE;
- return FALSE;
- }
- }
-
- handle->tx_dma_ok = FALSE;
- handle->rx_dma_ok = FALSE;
- handle->rxsize = size;
- osel_memset(handle->rxbuf, 0, handle->rxsize);
- LL_DMA_DisableChannel(handle->dma, handle->dma_tx_channel);
- LL_DMA_SetDataLength(handle->dma, handle->dma_rx_channel, handle->rxsize);
- LL_DMA_EnableChannel(handle->dma, handle->dma_rx_channel);
- LL_I2C_HandleTransfer(handle->i2c, handle->r_address, LL_I2C_ADDRSLAVE_7BIT, handle->rxsize, LL_I2C_MODE_AUTOEND, LL_I2C_GENERATE_RESTART_7BIT_READ);
-
- count = 2000;
- while (!LL_I2C_IsActiveFlag_STOP(handle->i2c))
- {
- if (count-- == 0)
- {
- handle->tx_dma_ok = TRUE;
- return FALSE;
- }
- }
-
- LL_DMA_DisableChannel(handle->dma, handle->dma_rx_channel);
- LL_I2C_ClearFlag_STOP(handle->i2c);
- osel_memcpy(data, handle->rxbuf, handle->rxsize);
- return TRUE;
-}
-/**
- * @brief 创建一个I2C总线设备
- * @param {i2c_gpio_group_t} gpios I2C总线的GPIO配置
- * @param {uint16_t} delay_ticks I2C总线的延时参数
- * @return {i2c_t *} 创建的I2C总线设备句柄
- * @note: 该函数用于创建一个I2C总线设备。它首先创建一个i2c_t结构体,并将gpios和delay_ticks的内存地址复制到handle结构体中。然后,它为handle结构体定义了start、stop、wait_ack、read_byte、write_byte和write_word函数。最后,它返回handle结构体。
- */
-i2c_t *i2c_create(i2c_gpio_group_t gpios, uint16_t delay_ticks)
-{
- // 创建一个i2c_t结构体
- i2c_t *handle = (i2c_t *)osel_mem_alloc(sizeof(i2c_t));
- // 将gpios的内存地址复制到handle结构体中
- osel_memcpy((uint8_t *)&handle->gpios, (uint8_t *)&gpios, sizeof(i2c_gpio_group_t));
- // 将delay_ticks的内存地址复制到handle结构体中
- handle->delay_ticks = delay_ticks;
-
- // 创建一个start函数
- handle->interface.start = _start;
- // 创建一个stop函数
- handle->interface.stop = _stop;
- // 创建一个wait_ack函数
- handle->interface.wait_ack = _wait_ack;
- // 创建一个read_byte函数
- handle->interface.read_byte = _read_byte;
- // 创建一个write_byte函数
- handle->interface.write_byte = _write_byte;
- // 创建一个write_word函数
- handle->interface.write_word = _write_word;
-
- handle->dead_count = 0;
- // 返回handle结构体
- return handle;
-}
-
-/**
- * @brief 创建一个I2C总线设备 DMA
- * @param {I2C_TypeDef} *i2c
- * @param {DMA_TypeDef} *dma
- * @param {uint16_t} rxsize
- * @param {uint32_t} dma_rx_channel
- * @param {uint16_t} txsize
- * @param {uint32_t} dma_tx_channel
- * @return {*}
- * @note
- */
-i2c_t *i2c_create_dma(I2C_TypeDef *i2c, DMA_TypeDef *dma, uint16_t rxsize, uint32_t dma_rx_channel,
- i2cs_dma_callback *dma_rx_cb, uint16_t txsize, uint32_t dma_tx_channel, i2cs_dma_callback *dma_tx_cb)
-{
- i2c_t *handle = (i2c_t *)osel_mem_alloc(sizeof(i2c_t));
- handle->i2c = i2c;
- handle->dma = dma;
- handle->dma_rx_channel = dma_rx_channel;
- handle->dma_tx_channel = dma_tx_channel;
- handle->rxbuf = (uint8_t *)osel_mem_alloc(rxsize);
- handle->txbuf = (uint8_t *)osel_mem_alloc(txsize);
- handle->rxsize = rxsize;
- handle->txsize = txsize;
- handle->tx_dma_ok = TRUE;
- handle->interface.write_mem_dma = _write_mem_dma;
- handle->interface.read_mem_dma = _read_mem_dma;
- if (dma_rx_cb != NULL)
- {
- handle->dma_rx_cb = dma_rx_cb;
- }
-
- if (dma_tx_cb != NULL)
- {
- handle->dma_tx_cb = dma_tx_cb;
- }
-
- LL_DMA_DisableChannel(dma, dma_tx_channel);
- LL_DMA_DisableChannel(dma, dma_rx_channel);
-
- // TX
- uint8_t *pTransmitBuffer = handle->txbuf;
- LL_DMA_ConfigTransfer(dma, dma_tx_channel, LL_DMA_DIRECTION_MEMORY_TO_PERIPH | LL_DMA_PRIORITY_HIGH | LL_DMA_MODE_NORMAL | LL_DMA_PERIPH_NOINCREMENT | LL_DMA_MEMORY_INCREMENT | LL_DMA_PDATAALIGN_BYTE | LL_DMA_MDATAALIGN_BYTE);
- LL_DMA_ConfigAddresses(dma, dma_tx_channel, (uint32_t)pTransmitBuffer, (uint32_t)LL_I2C_DMA_GetRegAddr(i2c, LL_I2C_DMA_REG_DATA_TRANSMIT), LL_DMA_GetDataTransferDirection(dma, dma_tx_channel));
- LL_DMA_SetPeriphRequest(dma, dma_tx_channel, LL_DMA_REQUEST_3);
-
- // RX
- uint8_t *pReceiveBuffer = handle->rxbuf;
- LL_DMA_ConfigTransfer(dma, dma_rx_channel, LL_DMA_DIRECTION_PERIPH_TO_MEMORY | LL_DMA_PRIORITY_HIGH | LL_DMA_MODE_NORMAL | LL_DMA_PERIPH_NOINCREMENT | LL_DMA_MEMORY_INCREMENT | LL_DMA_PDATAALIGN_BYTE | LL_DMA_MDATAALIGN_BYTE);
- LL_DMA_ConfigAddresses(dma, dma_rx_channel, (uint32_t)LL_I2C_DMA_GetRegAddr(i2c, LL_I2C_DMA_REG_DATA_RECEIVE), (uint32_t)pReceiveBuffer, LL_DMA_GetDataTransferDirection(dma, dma_rx_channel));
- LL_DMA_SetPeriphRequest(dma, dma_rx_channel, LL_DMA_REQUEST_3);
-
- LL_DMA_EnableIT_TC(dma, dma_tx_channel);
- LL_DMA_EnableIT_TE(dma, dma_tx_channel);
- LL_DMA_EnableIT_TC(dma, dma_rx_channel);
- LL_DMA_EnableIT_TE(dma, dma_rx_channel);
-
- LL_I2C_EnableDMAReq_TX(i2c);
- LL_I2C_EnableDMAReq_RX(i2c);
- LL_I2C_Enable(i2c);
-
- return handle;
-}
-
-/**
- * @brief 设置I2C器件地址
- * @param {i2c_t} *handle
- * @param {uint8_t} w_address 写地址
- * @param {uint8_t} r_address 读地址
- * @return {*}
- * @note
- */
-void i2c_dma_set_address(i2c_t *handle, uint8_t w_address, uint8_t r_address)
-{
- DBG_ASSERT(handle != NULL __DBG_LINE);
- handle->w_address = w_address;
- handle->r_address = r_address;
-}
-
-/**
- * @brief 释放I2C总线设备
- * @param {i2c_t} *handle 需要释放的I2C总线设备句柄
- * @return {*} 无
- * @note: 该函数用于释放一个I2C总线设备。它首先检查handle是否为空,如果不为空,则释放所有的GPIO。最后,释放handle的内存。
- */
-void i2c_free(i2c_t *handle)
-{
- // 如果handle不为空,则释放所有的gpio
- if (NULL != handle)
- {
- gpio_free(handle->gpios.scl);
- gpio_free(handle->gpios.sda);
- osel_mem_free(handle);
- }
-}
-
-/**
- * @brief I2C DMA TX回调函数
- * @param {i2c_t} handle
- * @return {*}
- * @note
- */
-void i2c_dma_callback(i2c_t *handle)
-{
- // 检查输入参数是否为空
- DBG_ASSERT(handle != NULL __DBG_LINE);
- // 清除传输完成标志位
- if (handle->dma_tx_cb != NULL)
- {
- handle->dma_tx_cb(handle);
- }
- if (handle->dma_rx_cb != NULL)
- {
- handle->dma_rx_cb(handle);
- }
-}
-
-/**
- * @brief I2C 中断回调函数
- * @param {i2c_t} *handle
- * @return {*}
- * @note
- */
-void i2c_ev_callback(i2c_t *handle)
-{
- DBG_ASSERT(handle != NULL __DBG_LINE);
- if (LL_I2C_IsActiveFlag_ADDR(handle->i2c))
- {
- /* Verify the Address Match with the OWN Slave address */
- if (LL_I2C_GetAddressMatchCode(handle->i2c) == handle->w_address || LL_I2C_GetAddressMatchCode(handle->i2c) == handle->r_address)
- {
- /* Verify the transfer direction, a write direction, Slave enters receiver mode */
- if (LL_I2C_GetTransferDirection(handle->i2c) == LL_I2C_DIRECTION_WRITE)
- {
- /* Clear ADDR flag value in ISR register */
- LL_I2C_ClearFlag_ADDR(handle->i2c);
-
- /* Enable Receive Interrupt */
- LL_I2C_EnableIT_RX(handle->i2c);
- }
- else if (LL_I2C_GetTransferDirection(handle->i2c) == LL_I2C_DIRECTION_READ)
- {
- /* Clear ADDR flag value in ISR register */
- LL_I2C_ClearFlag_ADDR(handle->i2c);
-
- /* Enable Transmit Interrupt */
- LL_I2C_EnableIT_TX(handle->i2c);
- }
- }
- else
- {
- /* Clear ADDR flag value in ISR register */
- LL_I2C_ClearFlag_ADDR(handle->i2c);
-
- /* Call Error function */
- DBG_ASSERT(FALSE __DBG_LINE);
- }
- }
- /* Check NACK flag value in ISR register */
- else if (LL_I2C_IsActiveFlag_NACK(handle->i2c))
- {
- /* End of Transfer */
- LL_I2C_ClearFlag_NACK(handle->i2c);
- }
- /* Check RXNE flag value in ISR register */
- else if (LL_I2C_IsActiveFlag_RXNE(handle->i2c))
- {
- /* Call function Slave Reception Callback */
- }
- /* Check TXIS flag value in ISR register */
- else if (LL_I2C_IsActiveFlag_TXIS(handle->i2c))
- {
- /* Call function Slave Ready to Transmit Callback */
- }
- /* Check STOP flag value in ISR register */
- else if (LL_I2C_IsActiveFlag_STOP(handle->i2c))
- {
- /* End of Transfer */
- LL_I2C_ClearFlag_STOP(handle->i2c);
-
- /* Check TXE flag value in ISR register */
- if (!LL_I2C_IsActiveFlag_TXE(handle->i2c))
- {
- /* Flush TX buffer */
- LL_I2C_ClearFlag_TXE(handle->i2c);
- }
-
- /* Call function Slave Complete Callback */
- }
- /* Check TXE flag value in ISR register */
- else if (!LL_I2C_IsActiveFlag_TXE(handle->i2c))
- {
- /* Do nothing */
- /* This Flag will be set by hardware when the TXDR register is empty */
- /* If needed, use LL_I2C_ClearFlag_TXE() interface to flush the TXDR register */
- }
- else
- {
- /* Call Error function */
- DBG_ASSERT(FALSE __DBG_LINE);
- }
-}
-
-/*下面是内部实现方法*/
-
-/**
- * @brief 此方法是一个简单的延迟函数,它使用循环来执行指定数量的NOP(无操作)指令。这个延迟函数的目的是在程序的执行中引入延迟,这在需要精确定时的某些应用中很有用。延迟时间由输入参数“count”的值决定,该参数指定要执行的NOP指令的数量。延迟时间通常以微秒或毫秒为单位测量,具体取决于使用延迟的环境。
- * @param {uint16_t} count NOP指令的数量
- * @return {*}
- */
-static inline void delay(i2c_t *handle)
-{
- // 断言参数handle不为空
- DBG_ASSERT(handle != NULL __DBG_LINE);
- // 定义循环计数变量count
- uint16_t count = 0;
- // 设置循环计数变量count的值为handle->delay_ticks
- count = handle->delay_ticks;
- // 循环计数变量count的值,直到count的值为0
- while (count--)
- {
- // 每次循环调用__NOP()函数
- __NOP();
- }
-}
-
-/**
- * @brief 发送ACK信号
- * @param {i2c_t} *handle I2C总线的句柄
- * @return {*} 无
- * @note: 该函数用于在I2C总线上发送ACK信号。它首先断言handle不为空,然后获取gpios和scl、sda的指针。接着重置sda,延时1ms,设置scl为1,延时1ms,重置scl,确保正确的结束传输。
- */
-static inline void _ack(i2c_t *handle)
-{
- // 断言handle不为空
- DBG_ASSERT(handle != NULL __DBG_LINE);
- // 获取gpios指针
- i2c_gpio_group_t *gpios = &handle->gpios;
- // 获取scl指针
- gpio_t *scl = gpios->scl;
- // 获取sda指针
- gpio_t *sda = gpios->sda;
-
- // 重置sda
- gpios->sda->reset(*sda);
- // 延时
- delay(handle);
- // 设置scl
- gpios->scl->set(*scl);
- // 延时
- delay(handle);
- // 重置scl
- gpios->scl->reset(*scl);
-}
-
-/**
- * @brief 发送NACK信号
- * @param {i2c_t} *handle I2C总线的句柄
- * @return {*} 无
- * @note: 该函数用于在I2C总线上发送NACK信号。它首先断言handle不为空,然后获取gpios和scl、sda的指针。接着设置sda为1,延时1ms,设置scl为1,延时1ms,重置scl,确保正确的结束传输。
- */
-static inline void _nack(i2c_t *handle)
-{
- DBG_ASSERT(handle != NULL __DBG_LINE);
- // 获取gpios指针
- i2c_gpio_group_t *gpios = &handle->gpios;
- // 获取scl指针
- gpio_t *scl = gpios->scl;
- // 获取sda指针
- gpio_t *sda = gpios->sda;
-
- // 设置sda引脚
- gpios->sda->set(*sda);
- // 等待延时
- delay(handle);
- // 设置scl引脚
- gpios->scl->set(*scl);
- // 等待延时
- delay(handle);
- // 重置scl引脚
- gpios->scl->reset(*scl);
-}
diff --git a/User/system/bsp/i2cs.h b/User/system/bsp/i2cs.h
index 4c6e58e..bf83806 100644
--- a/User/system/bsp/i2cs.h
+++ b/User/system/bsp/i2cs.h
@@ -26,53 +26,53 @@ typedef void i2cs_dma_callback(i2c_t *handle);
typedef struct
{
- void (*start)(i2c_t *handle); // Function pointer to start the I2C communication.
- void (*stop)(i2c_t *handle); // Function pointer to stop the I2C communication.
+ void (*start)(i2c_t *handle); ///< Function pointer to start the I2C communication.
+ void (*stop)(i2c_t *handle); ///< Function pointer to stop the I2C communication.
BOOL(*wait_ack)
- (i2c_t *handle); // Function pointer to wait for the acknowledgment from the I2C bus.
+ (i2c_t *handle); ///< Function pointer to wait for the acknowledgment from the I2C bus.
- void (*write_byte)(i2c_t *handle, uint8_t data); // Function pointer to write a byte of data to the I2C bus.
- uint8_t (*read_byte)(i2c_t *handle, BOOL ack); // Function pointer to read a byte of data from the I2C bus.
+ void (*write_byte)(i2c_t *handle, uint8_t data); ///< Function pointer to write a byte of data to the I2C bus.
+ uint8_t (*read_byte)(i2c_t *handle, BOOL ack); ///< Function pointer to read a byte of data from the I2C bus.
- void (*write_word)(i2c_t *handle, uint16_t data); // Function pointer to write two bytes of data to the I2C bus.
+ void (*write_word)(i2c_t *handle, uint16_t data); ///< Function pointer to write two bytes of data to the I2C bus.
BOOL(*write_mem_dma)
- (i2c_t *handle, uint16_t mem_address, uint16_t mem_addsize, uint8_t *data, uint16_t size); // Function pointer to write multiple bytes of data to a memory address using DMA.
+ (i2c_t *handle, uint16_t mem_address, uint16_t mem_addsize, uint8_t *data, uint16_t size); ///< Function pointer to write multiple bytes of data to a memory address using DMA.
BOOL(*read_mem_dma)
- (i2c_t *handle, uint16_t mem_address, uint16_t mem_addsize, uint8_t *data, uint16_t size); // Function pointer to read multiple bytes of data from a memory address using DMA.
+ (i2c_t *handle, uint16_t mem_address, uint16_t mem_addsize, uint8_t *data, uint16_t size); ///< Function pointer to read multiple bytes of data from a memory address using DMA.
} i2c_interface_t;
typedef struct
{
- struct GPIO *scl; // Pointer to the GPIO pin used for the I2C clock (SCL).
- struct GPIO *sda; // Pointer to the GPIO pin used for the I2C data (SDA).
+ struct GPIO *scl; ///< Pointer to the GPIO pin used for the I2C clock (SCL).
+ struct GPIO *sda; ///< Pointer to the GPIO pin used for the I2C data (SDA).
} i2c_gpio_group_t;
struct I2CS
{
- // Analog part definition
- i2c_gpio_group_t gpios; // Structure containing the GPIO pins used for the I2C communication.
- uint16_t delay_ticks; // Number of NOP instructions to delay the I2C communication.
+ ///< Analog part definition
+ i2c_gpio_group_t gpios; ///< Structure containing the GPIO pins used for the I2C communication.
+ uint16_t delay_ticks; ///< Number of NOP instructions to delay the I2C communication.
- // Hardware part definition
- I2C_TypeDef *i2c; // Pointer to the I2C peripheral.
- DMA_TypeDef *dma; // Pointer to the DMA peripheral.
- uint32_t dma_rx_channel; // DMA channel used for receiving data.
- uint32_t dma_tx_channel; // DMA channel used for transmitting data.
- uint8_t *rxbuf; // Pointer to the receive buffer.
- uint16_t rxsize; // Size of the receive buffer.
- uint8_t *txbuf; // Pointer to the transmit buffer.
- uint16_t txsize; // Size of the transmit buffer.
- uint8_t w_address; // 7-bit write address.
- uint8_t r_address; // 7-bit read address.
- __IO BOOL rx_dma_ok; // Flag indicating the completion of receive DMA.
- __IO BOOL tx_dma_ok; // Flag indicating the completion of transmit DMA.
+ ///< Hardware part definition
+ I2C_TypeDef *i2c; ///< Pointer to the I2C peripheral.
+ DMA_TypeDef *dma; ///< Pointer to the DMA peripheral.
+ uint32_t dma_rx_channel; ///< DMA channel used for receiving data.
+ uint32_t dma_tx_channel; ///< DMA channel used for transmitting data.
+ uint8_t *rxbuf; ///< Pointer to the receive buffer.
+ uint16_t rxsize; ///< Size of the receive buffer.
+ uint8_t *txbuf; ///< Pointer to the transmit buffer.
+ uint16_t txsize; ///< Size of the transmit buffer.
+ uint8_t w_address; ///< 7-bit write address.
+ uint8_t r_address; ///< 7-bit read address.
+ __IO BOOL rx_dma_ok; ///< Flag indicating the completion of receive DMA.
+ __IO BOOL tx_dma_ok; ///< Flag indicating the completion of transmit DMA.
- i2cs_dma_callback *dma_rx_cb; // Callback function called when receive DMA is completed.
- i2cs_dma_callback *dma_tx_cb; // Callback function called when transmit DMA is completed.
+ i2cs_dma_callback *dma_rx_cb; ///< Callback function called when receive DMA is completed.
+ i2cs_dma_callback *dma_tx_cb; ///< Callback function called when transmit DMA is completed.
- i2c_interface_t interface; // Structure containing the function pointers for the I2C interface.
- uint16_t dead_count; // Counter for the number of deadlocks.
+ i2c_interface_t interface; ///< Structure containing the function pointers for the I2C interface.
+ uint16_t dead_count; ///< Counter for the number of deadlocks.
};
/**
@@ -124,4 +124,4 @@ extern void i2c_ev_callback(i2c_t *handle);
*/
extern void i2c_dma_callback(i2c_t *handle);
-#endif // __I2CS_H__
+#endif ///< __I2CS_H__
diff --git a/User/system/bsp/iwdgs.c b/User/system/bsp/iwdgs.c
deleted file mode 100644
index 8b4228b..0000000
--- a/User/system/bsp/iwdgs.c
+++ /dev/null
@@ -1,39 +0,0 @@
-#include "iwdgs.h"
-
-/**
- * @brief 检查判断CPU复位是否是看门狗复位
- * @return {BOOL}
- * @note
- */
-BOOL check_watchdog_reset(void)
-{
- if (LL_RCC_IsActiveFlag_IWDGRST() == SET) // cpu is reset due to iwdg
- {
- LL_RCC_ClearResetFlags(); // clear flag
- return TRUE;
- }
- else
- {
- return FALSE;
- }
-}
-
-/**
- * @brief 调试模式冻结看门狗
- * @return {*}
- * @note
- */
-void debug_freeze_watchdog(void)
-{
- LL_DBGMCU_APB1_GRP1_FreezePeriph(LL_DBGMCU_APB1_GRP1_IWDG_STOP);
-}
-
-/**
- * @brief 调试模式恢复看门狗
- * @return {*}
- * @note
- */
-void debug_unfreeze_watchdog(void)
-{
- LL_DBGMCU_APB1_GRP1_UnFreezePeriph(LL_DBGMCU_APB1_GRP1_IWDG_STOP);
-}
diff --git a/User/system/bsp/pwms.c b/User/system/bsp/pwms.c
deleted file mode 100644
index e69de29..0000000
diff --git a/User/system/bsp/pwms.h b/User/system/bsp/pwms.h
index 94b5160..fee50c0 100644
--- a/User/system/bsp/pwms.h
+++ b/User/system/bsp/pwms.h
@@ -51,4 +51,4 @@
LL_TIM_OC_SetCompareCH##CHx(TIMx, DUTY); \
} while (__LINE__ == -1)
-#endif // __PWMS_H__
+#endif ///< __PWMS_H__
diff --git a/User/system/bsp/spis.c b/User/system/bsp/spis.c
deleted file mode 100644
index 92db8b6..0000000
--- a/User/system/bsp/spis.c
+++ /dev/null
@@ -1,491 +0,0 @@
-#include "spis.h"
-static inline void spi_delay(spi_t *handle); // 延时函数
-
-static inline void spi_rdy_high(spi_t *handle); // RDY高电平
-static inline void spi_rdy_low(spi_t *handle); // RDY低电平
-static inline void spi_cs_high(spi_t *handle); // CS高电平
-static inline void spi_cs_low(spi_t *handle); // CS低电平
-static inline void spi_mosi_high(spi_t *handle); // MOSI高电平
-static inline void spi_mosi_low(spi_t *handle); // MOSI低电平
-static inline void spi_sck_high(spi_t *handle); // SCK高电平
-static inline void spi_sck_low(spi_t *handle); // SCK低电平
-static inline uint8_t spi_miso_read(spi_t *handle); // 读取MISO电平
-
-static uint8_t spi_read_write_byte(spi_t *handle, uint8_t tx_data); // 读写一个字节
-
-static void _hardware_enable(spi_t *handle, SPI_TypeDef *spi); // 硬件SPI
-static void _dma_enable(spi_t *handle, DMA_TypeDef *dma, uint32_t dma_rx_channel, spis_dma_callback *dma_rx_cb,
- uint32_t dma_tx_channel, spis_dma_callback *dma_tx_cb); // DMA SPI
-static void _spi_dma_callback(spi_t *handle); // DMA发送完成回调
-static void _spi_dma_send(spi_t *handle, uint8_t *data, uint16_t length); // DMA发送数据
-static uint8_t _read_drdy(spi_t *handle); // 读取DRDY电平
-static uint8_t _write_regs(spi_t *handle, uint8_t reg, uint8_t *data, uint8_t len); // 写多个寄存器
-static uint8_t _read_regs(spi_t *handle, uint8_t reg, uint8_t *data, uint8_t len); // 读多个寄存器
-static uint8_t _spi_write_reg(spi_t *handle, uint8_t reg, uint8_t data); // 写单个寄存器
-static uint8_t _spi_read_reg(spi_t *handle, uint8_t reg); // 读单个寄存器
-static uint8_t _spi_write_cmd(spi_t *handle, uint8_t cmd); // 写命令
-static uint8_t _spi_write_data(spi_t *handle, uint8_t *data, uint16_t len); // 写数据
-
-/**
- * @brief 创建一个SPI总线设备
- * @param {spi_type_e} spi_type SPI总线的类型
- * @param {spi_gpio_group_t} gpios SPI总线的GPIO配置
- * @param {uint16_t} delay_ticks SPI总线的延时参数
- * @return {*} 创建的SPI总线设备句柄
- * @note: 该函数用于创建一个SPI总线设备。它首先断言spi_type在有效的范围内,然后创建一个spi_t结构体,并将gpios和delay_ticks的内存地址复制到handle结构体中。接着,根据spi_type的值,设置不同的接口函数。最后,返回handle结构体。
- */
-spi_t *spi_create(spi_type_e spi_type, spi_gpio_group_t gpios, uint16_t delay_ticks)
-{
- DBG_ASSERT(spi_type < SPI_TYPE_MAX __DBG_LINE);
- spi_t *handle = (spi_t *)osel_mem_alloc(sizeof(spi_t));
- osel_memcpy((uint8_t *)&handle->gpios, (uint8_t *)&gpios, sizeof(spi_gpio_group_t));
- handle->delay_ticks = delay_ticks;
- handle->spi_type = spi_type;
- handle->simualte_gpio = TRUE;
- handle->interface.hardware_enable = _hardware_enable;
- handle->interface.dma_enable = _dma_enable;
- handle->interface.spi_dma_send = _spi_dma_send;
- handle->interface.spi_dma_callback = _spi_dma_callback;
- if (spi_type == SPI_TYPE_NORMAL)
- {
- handle->interface.u.normal.write_reg = _spi_write_reg;
- handle->interface.u.normal.read_reg = _spi_read_reg;
- handle->interface.u.normal.write_regs = _write_regs;
- handle->interface.u.normal.read_regs = _read_regs;
- handle->interface.u.normal.read_drdy = _read_drdy;
-
- handle->interface.u.normal.spi_send = spi_read_write_byte;
- }
- else if (spi_type == SPI_TYPE_LCD)
- {
- handle->interface.u.lcd.write_cmd = _spi_write_cmd;
- handle->interface.u.lcd.write_data = _spi_write_data;
- }
- else
- {
- DBG_ASSERT(FALSE __DBG_LINE);
- }
- return handle;
-}
-
-void spi_free(spi_t *handle)
-{
- if (handle != NULL)
- {
- gpio_free(handle->gpios.cs);
- gpio_free(handle->gpios.rdy);
- gpio_free(handle->gpios.rst);
- gpio_free(handle->gpios.mosi);
- gpio_free(handle->gpios.miso);
- gpio_free(handle->gpios.sck);
-
- osel_mem_free(handle);
- }
-}
-
-/**
- * @brief 硬件SPI模式
- * @param {spi_t} *handle SPI总线设备句柄
- * @param {SPI_TypeDef} *spi SPI总线的寄存器结构体指针
- * @return {*} 无
- * @note: 该函数用于设置SPI总线的硬件模式。它首先断言handle不为空,然后断言spix不为空。接着,将handle的simulate_gpio设置为FALSE,并将spix的地址赋值给handle->spix。最后,调用SPI_ENABLE函数启用SPI总线。
- */
-static void _hardware_enable(spi_t *handle, SPI_TypeDef *spi)
-{
- DBG_ASSERT(handle != NULL __DBG_LINE);
- DBG_ASSERT(spi != NULL __DBG_LINE);
- handle->simualte_gpio = FALSE;
- handle->spi = spi;
- SPI_ENABLE(spi);
-}
-
-static void _dma_enable(spi_t *handle, DMA_TypeDef *dma, uint32_t dma_rx_channel, spis_dma_callback *dma_rx_cb,
- uint32_t dma_tx_channel, spis_dma_callback *dma_tx_cb)
-{
- DBG_ASSERT(handle != NULL __DBG_LINE);
- DBG_ASSERT(dma != NULL __DBG_LINE);
- DBG_ASSERT(handle->spi != NULL __DBG_LINE);
- handle->dma = dma;
- handle->dma_rx_channel = dma_rx_channel;
- handle->dma_tx_channel = dma_tx_channel;
- handle->rx_dma_ok = TRUE;
- handle->tx_dma_ok = TRUE;
- if (dma_rx_cb != NULL)
- {
- handle->dma_rx_cb = dma_rx_cb;
- }
- if (dma_tx_cb != NULL)
- {
- handle->dma_tx_cb = dma_tx_cb;
- }
-
- LL_DMA_SetPeriphAddress(dma, dma_tx_channel, LL_SPI_DMA_GetRegAddr(handle->spi));
- LL_DMA_ClearFlag_GI1(dma);
- LL_DMA_ClearFlag_TC1(dma);
- LL_DMA_EnableIT_TC(dma, dma_tx_channel);
- LL_SPI_EnableDMAReq_TX(handle->spi);
- LL_SPI_Enable(handle->spi);
-}
-
-static void _spi_dma_callback(spi_t *handle)
-{
- DBG_ASSERT(handle != NULL __DBG_LINE);
- if (handle->dma_tx_cb != NULL)
- {
- handle->dma_tx_cb(handle);
- }
-
- if (handle->dma_rx_cb != NULL)
- {
- handle->dma_rx_cb(handle);
- }
-}
-
-static void _spi_dma_send(spi_t *handle, uint8_t *data, uint16_t length)
-{
- handle->tx_dma_ok = FALSE;
- LL_DMA_DisableChannel(handle->dma, handle->dma_tx_channel);
-
- LL_DMA_SetMemoryAddress(handle->dma, handle->dma_tx_channel, (uint32_t)data);
- LL_DMA_SetDataLength(handle->dma, handle->dma_tx_channel, length);
-
- LL_DMA_EnableChannel(handle->dma, handle->dma_tx_channel);
-
- uint16_t i = 0;
- while (handle->tx_dma_ok == FALSE)
- {
- i++;
- if (i > 20000)
- {
- __NOP();
- break;
- }
- }
-}
-
-/**
- * @brief 读取数据准备好信号
- * @param {spi_t} *handle SPI总线设备句柄
- * @return {uint8_t} 数据准备好信号的值
- * @note: 该函数用于读取SPI总线的数据准备好信号。它首先断言handle不为空,然后返回handle的gpios.rdy的读取结果。
- */
-static uint8_t _read_drdy(spi_t *handle)
-{
- DBG_ASSERT(handle != NULL __DBG_LINE);
- return handle->gpios.rdy->read(*handle->gpios.rdy);
-}
-
-/**
- * @brief 写入单个寄存器
- * @param {spi_t} *handle SPI总线设备句柄
- * @param {uint8_t} reg 寄存器号
- * @param {uint8_t} data 寄存器值
- * @return {*} 操作结果
- * @note: 该函数用于写入SPI总线的单个寄存器。它首先断言handle不为空,然后断言data不为空。接着,将SPI总线的CS引脚设置为低电平,发送寄存器号和寄存器值,最后将SPI总线的CS引脚设置为高电平,返回操作结果。
- */
-static uint8_t _write_regs(spi_t *handle, uint8_t reg, uint8_t *data, uint8_t len)
-{
- uint8_t status = 0;
- DBG_ASSERT(handle != NULL __DBG_LINE);
- DBG_ASSERT(data != NULL __DBG_LINE);
- DBG_ASSERT(len != 0 __DBG_LINE);
- spi_cs_low(handle);
- status = spi_read_write_byte(handle, reg); // 发送寄存器号
- while (len--)
- {
- spi_read_write_byte(handle, *data); // 写入寄存器的值
- data++;
- }
- spi_cs_high(handle);
-
- return status;
-}
-
-/**
- * @brief 读取多个寄存器
- * @param {spi_t} *handle SPI总线设备句柄
- * @param {uint8_t} reg 寄存器号
- * @param {uint8_t} *data 寄存器值的指针
- * @param {uint8_t} len 寄存器值的个数
- * @return {uint8_t} 操作结果
- * @note: 该函数用于读取SPI总线的多个寄存器。它首先断言handle不为空,然后断言data不为空,接着断言len大于0。接着,将SPI总线的CS引脚设置为低电平,发送寄存器号,然后循环读取多个寄存器的值,最后将SPI总线的CS引脚设置为高电平,返回操作结果。
- */
-static uint8_t _read_regs(spi_t *handle, uint8_t reg, uint8_t *data, uint8_t len)
-{
- uint8_t status = 0;
-
- DBG_ASSERT(handle != NULL __DBG_LINE);
- DBG_ASSERT(data != NULL __DBG_LINE);
- DBG_ASSERT(len != 0 __DBG_LINE);
-
- spi_cs_low(handle);
- status = spi_read_write_byte(handle, reg);
- for (uint8_t i = 0; i < len; i++)
- {
- data[i] = spi_read_write_byte(handle, 0xff); // 读出数据
- }
- spi_cs_high(handle);
-
- return status;
-}
-
-/**
- * @brief 写入单个寄存器
- * @param {spi_t} *handle SPI总线设备句柄
- * @param {uint8_t} reg 寄存器号
- * @param {uint8_t} data 寄存器值
- * @return {*} 操作结果
- * @note: 该函数用于写入SPI总线的单个寄存器。它首先断言handle不为空,然后将SPI总线的CS引脚设置为低电平,发送寄存器号和寄存器值,最后将SPI总线的CS引脚设置为高电平,返回操作结果。
- */
-static uint8_t _spi_write_reg(spi_t *handle, uint8_t reg, uint8_t data)
-{
- uint8_t status = 0;
- DBG_ASSERT(handle != NULL __DBG_LINE);
-
- spi_cs_low(handle);
- status = spi_read_write_byte(handle, reg); // 发送寄存器号
- spi_read_write_byte(handle, data); // 写入寄存器的值
-
- spi_cs_high(handle);
-
- return status;
-}
-
-/**
- * @brief 读取单个寄存器
- * @param {spi_t} *handle SPI总线设备句柄
- * @param {uint8_t} reg 寄存器号
- * @return {*} 寄存器值
- * @note: 该函数用于读取SPI总线的单个寄存器。它首先断言handle不为空,然后将SPI总线的CS引脚设置为低电平,发送寄存器号,接着读取寄存器的值,最后将SPI总线的CS引脚设置为高电平,返回寄存器值。
- */
-static uint8_t _spi_read_reg(spi_t *handle, uint8_t reg)
-{
- uint8_t reg_val = 0;
- DBG_ASSERT(handle != NULL __DBG_LINE);
-
- spi_cs_low(handle);
- spi_read_write_byte(handle, reg); // 发送寄存器号
- reg_val = spi_read_write_byte(handle, 0);
- spi_cs_high(handle);
-
- return reg_val;
-}
-
-/**
- * @brief 写入命令
- * @param {spi_t} *handle SPI总线设备句柄
- * @param {uint8_t} cmd 命令
- * @return {*} 操作结果
- * @note: 该函数用于写入SPI总线的命令。它首先断言handle不为空,然后将SPI总线的RDY引脚设置为低电平,发送命令,最后将SPI总线的CS引脚设置为高电平,返回操作结果。
- */
-static uint8_t _spi_write_cmd(spi_t *handle, uint8_t cmd)
-{
- uint8_t status = 0;
-
- DBG_ASSERT(handle != NULL __DBG_LINE);
- spi_rdy_low(handle);
- spi_cs_low(handle);
- status = spi_read_write_byte(handle, cmd); // 发送命令
- spi_cs_high(handle);
- return status;
-}
-
-/**
- * @brief 写入数据
- * @param {spi_t} *handle SPI总线设备句柄
- * @param {uint8_t} *data 要写入的数据的指针
- * @param {uint16_t} len 要写入的数据的长度
- * @return {*} 操作结果
- * @note: 该函数用于写入SPI总线的数据。它首先断言handle不为空,然后将SPI总线的RDY引脚设置为高电平,发送数据,最后将SPI总线的CS引脚设置为高电平,返回操作结果。
- */
-static uint8_t _spi_write_data(spi_t *handle, uint8_t *data, uint16_t len)
-{
- uint8_t status = 0;
- DBG_ASSERT(handle != NULL __DBG_LINE);
- spi_rdy_high(handle);
- spi_cs_low(handle);
- for (uint16_t i = 0; i < len; i++)
- {
- status = spi_read_write_byte(handle, *data);
- data++;
- }
- spi_cs_high(handle);
- return status;
-}
-
-/**
- * @brief SPI延时函数
- * @param {spi_t} *handle SPI总线设备句柄
- * @return {*} 无
- * @note: 该函数用于SPI总线的延时。它首先断言handle不为空,然后根据handle的delay_ticks的值,循环执行NOP指令。
- */
-static inline void spi_delay(spi_t *handle)
-{
- uint16_t count = 0;
- DBG_ASSERT(handle != NULL __DBG_LINE);
- count = handle->delay_ticks;
- while (count--)
- {
- __NOP();
- }
-}
-
-/**
- * @brief 读写一个字节
- * @param {spi_t} *handle SPI总线设备句柄
- * @param {uint8_t} tx_data 要写入的数据
- * @return {*} 读取到的数据
- * @note: 该函数用于SPI总线的读写一个字节。它首先断言handle不为空,然后根据handle的simulate_gpio的值,选择模拟SPI或硬件SPI。最后,返回读取到的数据。
- */
-static uint8_t spi_read_write_byte(spi_t *handle, uint8_t tx_data)
-{
- uint8_t bit_ctr;
- uint8_t rdata = 0xff;
- uint16_t i = 0;
- DBG_ASSERT(handle != NULL __DBG_LINE);
- if (handle->simualte_gpio == TRUE)
- {
- // 模拟SPI
- for (bit_ctr = 0; bit_ctr < 8; bit_ctr++)
- {
- spi_sck_low(handle);
- spi_delay(handle);
-
- if (tx_data & 0x80)
- spi_mosi_high(handle);
- else
- spi_mosi_low(handle);
-
- spi_delay(handle);
- spi_sck_high(handle);
- spi_delay(handle);
- tx_data = (tx_data << 1);
- rdata = rdata << 1;
-
- if (NULL != handle->gpios.miso->port)
- {
- if (spi_miso_read(handle) == 1)
- rdata += 0x01;
- }
- }
- return (rdata);
- }
- else
- {
- // 硬件SPI
- LL_SPI_TransmitData8(handle->spi, tx_data);
- while (LL_SPI_IsActiveFlag_TXE(handle->spi) == 0)
- {
- i++;
- if (i > 2000)
- break;
- }
- i = 0;
- while (LL_SPI_IsActiveFlag_RXNE(handle->spi) == 0)
- {
- i++;
- if (i > 2000)
- break;
- }
- return LL_SPI_ReceiveData8(handle->spi);
- }
-}
-
-/**
- * @brief 用于将SPI(串行外围接口)设备的复位(RST)引脚设置为高
- * @param {spi_id_e} id
- * @return {*}
- */
-static inline void spi_rdy_high(spi_t *handle)
-{
- DBG_ASSERT(handle != NULL __DBG_LINE);
- handle->gpios.rdy->set(*handle->gpios.rdy);
-}
-
-/**
- * @brief 用于将SPI(串行外围接口)设备的复位(RST)引脚设置为低
- * @param {spi_id_e} id
- * @return {*}
- */
-static inline void spi_rdy_low(spi_t *handle)
-{
- DBG_ASSERT(handle != NULL __DBG_LINE);
- handle->gpios.rdy->reset(*handle->gpios.rdy);
-}
-
-/**
- * @brief 用于将SPI(串行外围接口)设备的芯片选择(CS)引脚设置为高
- * @param {spi_id_e} id
- * @return {*}
- */
-static inline void spi_cs_high(spi_t *handle)
-{
- DBG_ASSERT(handle != NULL __DBG_LINE);
- handle->gpios.cs->set(*handle->gpios.cs);
-}
-
-/**
- * @brief 用于将SPI(串行外围接口)设备的芯片选择(CS)引脚设置为低
- * @param {spi_id_e} id
- * @return {*}
- */
-static inline void spi_cs_low(spi_t *handle)
-{
- DBG_ASSERT(handle != NULL __DBG_LINE);
- handle->gpios.cs->reset(*handle->gpios.cs);
-}
-
-/**
- * @brief 用于将SPI(串行外围接口)设备的时钟(SCK)引脚设置为高
- * @param {spi_id_e} id
- * @return {*}
- */
-static inline void spi_mosi_high(spi_t *handle)
-{
- DBG_ASSERT(handle != NULL __DBG_LINE);
- handle->gpios.mosi->set(*handle->gpios.mosi);
-}
-
-/**
- * @brief 用于将SPI(串行外围接口)设备的输出(MOSI)引脚设置为低
- * @param {spi_id_e} id
- * @return {*}
- */
-static inline void spi_mosi_low(spi_t *handle)
-{
- DBG_ASSERT(handle != NULL __DBG_LINE);
- handle->gpios.mosi->reset(*handle->gpios.mosi);
-}
-
-/**
- * @brief 用于将SPI(串行外围接口)设备的时钟(SCK)引脚设置为高
- * @param {spi_id_e} id
- * @return {*}
- */
-static inline void spi_sck_high(spi_t *handle)
-{
- DBG_ASSERT(handle != NULL __DBG_LINE);
- handle->gpios.sck->set(*handle->gpios.sck);
-}
-
-/**
- * @brief 用于将SPI(串行外围接口)设备的时钟(SCK)引脚设置为低
- * @param {spi_id_e} id
- * @return {*}
- */
-static inline void spi_sck_low(spi_t *handle)
-{
- DBG_ASSERT(handle != NULL __DBG_LINE);
- handle->gpios.sck->reset(*handle->gpios.sck);
-}
-
-/**
- * @brief 用于读取SPI(串行外围接口)设备的输入(MISO)引脚的电平
- * @param {spi_id_e} id
- * @return {*}
- */
-static inline uint8_t spi_miso_read(spi_t *handle)
-{
- DBG_ASSERT(handle != NULL __DBG_LINE);
- return handle->gpios.miso->read(*handle->gpios.miso);
-}
diff --git a/User/system/bsp/spis.h b/User/system/bsp/spis.h
index 1f9136c..ac2d77e 100644
--- a/User/system/bsp/spis.h
+++ b/User/system/bsp/spis.h
@@ -27,8 +27,8 @@ typedef void spis_dma_callback(spi_t *handle);
*/
typedef enum
{
- SPI_TYPE_NORMAL = 0, // SPI1:NORMAL
- SPI_TYPE_LCD, // SPI2:LCD
+ SPI_TYPE_NORMAL = 0, ///< SPI1:NORMAL
+ SPI_TYPE_LCD, ///< SPI2:LCD
SPI_TYPE_MAX,
} spi_type_e;
@@ -37,12 +37,12 @@ typedef enum
*/
typedef struct
{
- gpio_t *mosi; // MOSI
- gpio_t *miso; // MISO
- gpio_t *sck; // SCK
- gpio_t *cs; // CS
- gpio_t *rst; // RST
- gpio_t *rdy; // DRDY
+ gpio_t *mosi; ///< MOSI
+ gpio_t *miso; ///< MISO
+ gpio_t *sck; ///< SCK
+ gpio_t *cs; ///< CS
+ gpio_t *rst; ///< RST
+ gpio_t *rdy; ///< DRDY
} spi_gpio_group_t;
/**
@@ -50,12 +50,22 @@ typedef struct
*/
typedef struct
{
- uint8_t (*write_reg)(spi_t *handle, uint8_t reg, uint8_t data); // Write a single register via SPI
- uint8_t (*read_reg)(spi_t *handle, uint8_t reg); // Read the value of a single register via SPI
- uint8_t (*read_drdy)(spi_t *handle); // Get the value of the SPI DRDY pin
- uint8_t (*write_regs)(spi_t *handle, uint8_t reg, uint8_t *data, uint8_t len); // Write multiple registers via SPI
- uint8_t (*read_regs)(spi_t *handle, uint8_t reg, uint8_t *data, uint8_t len); // Read multiple registers via SPI
- uint8_t (*spi_send)(spi_t *handle, uint8_t data); // Send data via SPI
+ uint8_t (*write_reg)(spi_t *handle, uint8_t reg, uint8_t data); ///< Write a single register via SPI
+ uint8_t (*read_reg)(spi_t *handle, uint8_t reg); ///< Read the value of a single register via SPI
+ uint8_t (*read_drdy)(spi_t *handle); ///< Get the value of the SPI DRDY pin
+ uint8_t (*write_regs)(spi_t *handle, uint8_t reg, uint8_t *data, uint8_t len); ///< Write multiple registers via SPI
+ uint8_t (*read_regs)(spi_t *handle, uint8_t reg, uint8_t *data, uint8_t len); ///< Read multiple registers via SPI
+ uint8_t (*spi_send)(spi_t *handle, uint8_t data); ///< Send data via SPI
+ void (*spi_reset)(spi_t *handle); ///< Reset SPI
+
+ BOOL(*spi_write)
+ (spi_t *handle, uint32_t write_addr, uint8_t *data, uint16_t length); ///< Write data via SPI
+
+ BOOL(*spi_read)
+ (spi_t *handle, uint32_t read_addr, uint8_t *data, uint16_t length); ///< Read data via SPI
+
+ void (*spi_write_reg)(spi_t *handle, uint8_t reg, uint8_t data); ///< Write a single register via SPI
+ uint8_t (*spi_read_reg)(spi_t *handle, uint8_t reg); ///< Read a single register via SPI
} spi_normal_interface_t;
/**
@@ -63,8 +73,8 @@ typedef struct
*/
typedef struct
{
- uint8_t (*write_cmd)(spi_t *handle, uint8_t cmd); // Write a command via SPI
- uint8_t (*write_data)(spi_t *handle, uint8_t *data, uint16_t len); // Write data via SPI
+ uint8_t (*write_cmd)(spi_t *handle, uint8_t cmd); ///< Write a command via SPI
+ uint8_t (*write_data)(spi_t *handle, uint8_t *data, uint16_t len); ///< Write data via SPI
} spi_lcd_interface_t;
/**
@@ -77,11 +87,12 @@ typedef struct
spi_normal_interface_t normal;
spi_lcd_interface_t lcd;
} u;
- void (*hardware_enable)(spi_t *handle, SPI_TypeDef *spi); // Enable hardware SPI
+ void (*hardware_enable)(spi_t *handle, SPI_TypeDef *spi); ///< Enable hardware SPI
void (*dma_enable)(spi_t *handle, DMA_TypeDef *dma, uint32_t dma_rx_channel, spis_dma_callback *dma_rx_cb,
- uint32_t dma_tx_channel, spis_dma_callback *dma_tx_cb); // Enable DMA SPI
- void (*spi_dma_callback)(spi_t *spi); // DMA send completion callback
- void (*spi_dma_send)(spi_t *handle, uint8_t *data, uint16_t length); // DMA send
+ uint32_t dma_tx_channel, spis_dma_callback *dma_tx_cb); ///< Enable DMA SPI
+ void (*spi_dma_callback)(spi_t *spi); ///< DMA send completion callback
+ BOOL(*spi_dma_send)
+ (spi_t *handle, uint8_t *data, uint16_t length); ///< DMA send
} spi_interface_t;
/**
@@ -94,23 +105,44 @@ typedef struct SPIS spi_t;
*/
typedef void spis_dma_callback(spi_t *handle);
+typedef struct
+{
+ // CMD
+ uint8_t cmd_rdsr; ///< Read Status Register instruction
+ uint8_t cmd_wrsr; ///< Write Status Register instruction
+ uint8_t cmd_wren; ///< Write enable instruction
+ uint8_t cmd_wrdi; ///< Write disable instruction
+ uint8_t cmd_read; ///< Read from Memory instruction
+ uint8_t cmd_write; ///< Write to Memory instruction
+
+ uint8_t dummy_byte; ///< Dummy byte
+
+ uint8_t address_bytes;
+ uint32_t page_size;
+ uint32_t total_size;
+ uint8_t ticks; ///< Delay in NOP ticks
+ BOOL continuous_write; ///< Continuous write
+} spi_normal_config_t;
+
struct SPIS
{
- spi_type_e spi_type; // SPI type
- uint16_t delay_ticks; // Delay in NOP ticks
- spi_gpio_group_t gpios; // SPI GPIOs
- spi_interface_t interface; // SPI interface
- SPI_TypeDef *spi; // SPI peripheral
- BOOL simualte_gpio; // Simulate GPIO
-
- // DMA
- DMA_TypeDef *dma; // External setting
- uint32_t dma_rx_channel; // External setting
- uint32_t dma_tx_channel; // External setting
+ spi_type_e spi_type; ///< SPI type
+ uint16_t delay_ticks; ///< Delay in NOP ticks
+ spi_gpio_group_t gpios; ///< SPI GPIOs
+ spi_interface_t interface; ///< SPI interface
+ SPI_TypeDef *spi; ///< SPI peripheral
+ BOOL simualte_gpio; ///< Simulate GPIO
+ spi_normal_config_t cfg; ///< Normal SPI configuration
+ ///< DMA
+ DMA_TypeDef *dma; ///< External setting
+ uint32_t dma_rx_channel; ///< External setting
+ uint32_t dma_tx_channel; ///< External setting
__IO BOOL rx_dma_ok;
__IO BOOL tx_dma_ok;
- spis_dma_callback *dma_rx_cb; // DMA receive callback function
- spis_dma_callback *dma_tx_cb; // DMA send callback function
+ spis_dma_callback *dma_rx_cb; ///< DMA receive callback function
+ spis_dma_callback *dma_tx_cb; ///< DMA send callback function
+
+ void *params; ///< 扩展参数
};
/**
@@ -130,4 +162,4 @@ extern spi_t *spi_create(spi_type_e spi_type, spi_gpio_group_t gpios, uint16_t d
*/
extern void spi_free(spi_t *spi);
-#endif // __SPIS_H__
+#endif ///< __SPIS_H__
diff --git a/User/system/bsp/tims.c b/User/system/bsp/tims.c
deleted file mode 100644
index 03d544d..0000000
--- a/User/system/bsp/tims.c
+++ /dev/null
@@ -1 +0,0 @@
-#include "tims.h"
diff --git a/User/system/bsp/tims.h b/User/system/bsp/tims.h
index 08e9230..a63cef5 100644
--- a/User/system/bsp/tims.h
+++ b/User/system/bsp/tims.h
@@ -102,4 +102,4 @@ With these calculated values, both ARR and PSC are within the range of 0 to 6553
} \
} while (__LINE__ == -1)
-#endif // __TIMS_H__
+#endif ///< __TIMS_H__
diff --git a/User/system/bsp/uarts.c b/User/system/bsp/uarts.c
deleted file mode 100644
index c428b49..0000000
--- a/User/system/bsp/uarts.c
+++ /dev/null
@@ -1,392 +0,0 @@
-/*
- * @Author:
- * @Date: 2023-07-31 11:47:35
- * @LastEditors: xxx
- * @LastEditTime: 2023-08-25 15:30:33
- * @Description: LL库的串口驱动
- * email:
- * Copyright (c) 2023 by xxx, All Rights Reserved.
- */
-#include "uarts.h"
-
-/**
- * @brief 清除DMA传输完成标志
- * @param {DMA_HandleTypeDef} *DMAX DMA总线句柄
- * @param {uint32_t} CHx DMA通道号
- * @return {*} 操作结果
- * @note: 该宏用于清除DMA总线的传输完成标志。它首先检查DMA总线的传输完成标志是否已置位,如果已置位,则清除该标志。
- */
-#define DMA_ClEAR_FLAG_TC(DMAX, CHx) \
- do \
- { \
- if (LL_DMA_IsActiveFlag_TC##CHx(DMAX)) \
- { \
- LL_DMA_ClearFlag_TC##CHx(DMAX); \
- } \
- } while (__LINE__ == -1)
-
-/**
- * @brief 清除DMA传输错误标志
- * @param {DMA_HandleTypeDef} *DMAX DMA总线句柄
- * @param {uint32_t} CHx DMA通道号
- * @return {*} 操作结果
- * @note: 该宏用于清除DMA总线的传输错误标志。它首先检查DMA总线的传输错误标志是否已置位,如果已置位,则清除该标志。
- */
-#define DMA_ClEAR_FLAG_TE(DMAX, CHx) \
- do \
- { \
- if (LL_DMA_IsActiveFlag_TE##CHx(DMAX)) \
- { \
- LL_DMA_ClearFlag_TE##CHx(DMAX); \
- } \
- } while (__LINE__ == -1)
-
-/**
- * @file uarts.c
- * @brief This file contains the implementation of DMA_CLEAR_FLAG_TC_CHANNEL macro.
- */
-
-/**
- * @brief Clear the Transfer Complete (TC) flag of a specific DMA channel.
- *
- * @param dma The DMA peripheral.
- * @param channel The DMA channel number.
- */
-#define DMA_CLEAR_FLAG_TC_CHANNEL(dma, channel) \
- switch (channel) \
- { \
- case LL_DMA_CHANNEL_1: \
- DMA_ClEAR_FLAG_TC(dma, 1); \
- break; \
- case LL_DMA_CHANNEL_2: \
- DMA_ClEAR_FLAG_TC(dma, 2); \
- break; \
- case LL_DMA_CHANNEL_3: \
- DMA_ClEAR_FLAG_TC(dma, 3); \
- break; \
- case LL_DMA_CHANNEL_4: \
- DMA_ClEAR_FLAG_TC(dma, 4); \
- break; \
- case LL_DMA_CHANNEL_5: \
- DMA_ClEAR_FLAG_TC(dma, 5); \
- break; \
- case LL_DMA_CHANNEL_6: \
- DMA_ClEAR_FLAG_TC(dma, 6); \
- break; \
- case LL_DMA_CHANNEL_7: \
- DMA_ClEAR_FLAG_TC(dma, 7); \
- break; \
- default: \
- break; \
- }
-
-/**
- * @brief Clear the Transfer Error (TE) flag for the specified DMA channel.
- *
- * @param dma The DMA peripheral.
- * @param channel The DMA channel number.
- */
-#define DMA_CLEAR_FLAG_TE_CHANNEL(dma, channel) \
- switch (channel) \
- { \
- case 1: \
- DMA_ClEAR_FLAG_TE(dma, 1); \
- break; \
- case 2: \
- DMA_ClEAR_FLAG_TE(dma, 2); \
- break; \
- case 3: \
- DMA_ClEAR_FLAG_TE(dma, 3); \
- break; \
- case 4: \
- DMA_ClEAR_FLAG_TE(dma, 4); \
- break; \
- case 5: \
- DMA_ClEAR_FLAG_TE(dma, 5); \
- break; \
- case 6: \
- DMA_ClEAR_FLAG_TE(dma, 6); \
- break; \
- case 7: \
- DMA_ClEAR_FLAG_TE(dma, 7); \
- break; \
- default: \
- break; \
- }
-
-/**
- * @brief 创建一个UART设备
- * @param {USART_TypeDef} *huart USART总线设备句柄
- * @param {BOOL} rx_dma_en 接收DMA使能标志
- * @param {uint16_t} rxsize 接收缓冲区大小
- * @param {rx_interrupt_cb_t} rx_cb 接收中断回调函数
- * @param {BOOL} tx_dma_en 发送DMA使能标志
- * @param {uint16_t} txsize 发送缓冲区大小
- * @param {tx_complete_cb_t} tx_complete_cb 发送完成回调函数
- * @return {*} 创建的UART设备指针
- * @note: 该函数用于创建一个UART设备。它首先断言huart不为空,然后分配内存用于接收缓冲区和发送缓冲区,并设置相关标志。最后,返回创建的UART设备指针。
- */
-uart_t *uart_create(USART_TypeDef *huart, BOOL rx_dma_en, uint16_t rxsize, rx_interupt_cb_t rx_cb,
- BOOL tx_dma_en, uint16_t txsize, tx_complete_cb_t tx_complete_cb)
-{
- DBG_ASSERT(huart != NULL __DBG_LINE);
- // 分配内存
- uart_t *uart = (uart_t *)osel_mem_alloc(sizeof(uart_t));
- DBG_ASSERT(uart != NULL __DBG_LINE);
-
- // 设置接收回调函数
- uart->rx_interupt_cb = rx_cb;
- // 设置接收数据大小
- uart->rxsize = rxsize;
-
- // 设置发送完成回调函数
- uart->tx_complete_cb = tx_complete_cb;
- // 设置发送数据大小
- uart->txsize = txsize;
- // 如果接收大小大于0,则分配内存
- if (rxsize > 0)
- {
- uart->rxbuf = (uint8_t *)osel_mem_alloc(rxsize);
- DBG_ASSERT(uart->rxbuf != NULL __DBG_LINE);
- }
-
- // 如果发送大小大于0,则分配内存
- if (txsize > 0)
- {
- uart->txbuf = (uint8_t *)osel_mem_alloc(txsize);
- DBG_ASSERT(uart->txbuf != NULL __DBG_LINE);
- }
- // 设置接收DMA禁用
- uart->rx_dma_en = rx_dma_en;
- // 设置发送DMA禁用
- uart->tx_dma_en = tx_dma_en;
-
- // 设置huart
- uart->huart = huart;
- // 返回uart
- return uart;
-}
-
-/**
- * @brief 使能UART接收
- * @param {uart_t} *uart UART设备句柄
- * @return {*} 操作结果
- * @note: 该函数用于使能UART设备的接收功能。它首先检查UART设备的接收DMA使能标志,然后禁用接收中断,配置RX DMA并启用RX DMA通道。最后,检查UART设备的发送DMA使能标志,配置TX DMA并启用TX DMA通道。
- */
-void uart_recv_en(uart_t *uart)
-{
- if (FALSE == uart->rx_dma_en)
- {
- LL_USART_EnableIT_RXNE(uart->huart); // 使用接收中断处理
- }
- else
- {
- LL_USART_ClearFlag_IDLE(uart->huart);
- // LL_USART_EnableIT_RXNE(uart->huart); // 加上这个,否则第一条数据会接受不到
-
- // 配置RX DMA
- LL_DMA_DisableChannel(uart->dma, uart->dma_tx_channel);
- LL_DMA_DisableChannel(uart->dma, uart->dma_rx_channel);
-
- // 配置RX DMA
- LL_DMA_SetPeriphAddress(uart->dma, uart->dma_rx_channel, LL_USART_DMA_GetRegAddr(uart->huart, LL_USART_DMA_REG_DATA_RECEIVE));
- LL_DMA_SetMemoryAddress(uart->dma, uart->dma_rx_channel, (uint32_t)uart->rxbuf);
- LL_DMA_SetDataLength(uart->dma, uart->dma_rx_channel, uart->rxsize);
- LL_DMA_EnableIT_TC(uart->dma, uart->dma_rx_channel);
- LL_DMA_EnableChannel(uart->dma, uart->dma_rx_channel);
- LL_USART_EnableDMAReq_RX(uart->huart);
- LL_USART_EnableIT_IDLE(uart->huart);
-
- // 配置TX DMA
- LL_DMA_SetPeriphAddress(uart->dma, uart->dma_tx_channel, LL_USART_DMA_GetRegAddr(uart->huart, LL_USART_DMA_REG_DATA_TRANSMIT));
- // 配置内存地址
- LL_DMA_SetMemoryAddress(uart->dma, uart->dma_tx_channel, (uint32_t)uart->txbuf);
- LL_DMA_EnableIT_TC(uart->dma, uart->dma_tx_channel);
- LL_USART_EnableDMAReq_TX(uart->huart);
-
- uart->tx_dma_ok = TRUE;
- }
-}
-
-/**
- * @brief 释放UART设备资源
- * @param {uart_t} *uart UART设备句柄
- * @return {*} 操作结果
- * @note: 该函数用于释放UART设备的接收缓冲区、发送缓冲区和UART设备本身。
- */
-void uart_free(uart_t *uart)
-{
- if (uart != NULL)
- {
- if (uart->rxbuf != NULL)
- {
- osel_mem_free(uart->rxbuf);
- }
- if (uart->txbuf != NULL)
- {
- osel_mem_free(uart->txbuf);
- }
- osel_mem_free(uart);
- }
-}
-
-/**
- * @brief 设置波特率
- * @param {uart_t} *uart
- * @param {uint32_t} baudrate 波特率
- * @return {*}
- * @note
- */
-void uart_set_baudrate(uart_t *uart, uint32_t baudrate)
-{
- LL_USART_SetBaudRate(uart->huart, SystemCoreClock, LL_USART_OVERSAMPLING_16, baudrate);
-}
-
-/**
- * @brief 发送数据
- * @param {uart_t} *uart UART设备句柄
- * @param {uint8_t} *data 要发送的数据
- * @param {uint16_t} len 要发送的数据长度
- * @return {*} 操作结果
- * @note: 该函数用于发送数据。首先检查UART设备的发送DMA使能标志,然后禁用发送中断,配置TX DMA并启用TX DMA通道。最后,发送数据直到发送缓冲区满或发送中断发生。
- */
-void uart_send_data(uart_t *uart, uint8_t *data, uint16_t len)
-{
- DBG_ASSERT(uart != NULL __DBG_LINE);
- DBG_ASSERT(data != NULL __DBG_LINE);
- DBG_ASSERT(len > 0 __DBG_LINE);
- uint8_t count = 0;
- if (TRUE == uart->tx_dma_en)
- {
- if (uart->tx_dma_ok == FALSE)
- {
- return;
- }
- uart->tx_dma_ok = FALSE;
- osel_memcpy(uart->txbuf, data, len); // 拷贝数据到发送缓冲区
- LL_DMA_DisableChannel(uart->dma, uart->dma_tx_channel);
- // 配置数据长度
- LL_DMA_SetDataLength(uart->dma, uart->dma_tx_channel, len);
- // 使能DMA STREAM 也就是发送数据
- LL_DMA_EnableChannel(uart->dma, uart->dma_tx_channel);
- }
- else
- {
- count = 0;
- for (uint16_t i = 0; i < len; i++)
- {
- count = 0;
- while (!LL_USART_IsActiveFlag_TXE(uart->huart))
- {
- if (count++ >= 0xFE)
- {
- return;
- }
- }
- LL_USART_TransmitData8(uart->huart, data[i]);
- }
- count = 0;
- while (!LL_USART_IsActiveFlag_TC(uart->huart))
- {
- if (count++ >= 0xFE)
- {
- return;
- }
- }
- }
-}
-
-/**
- * @brief 接收中断回调函数
- * @param {uart_t} *uart UART设备句柄
- * @return {*} 操作结果
- * @note: 该函数用于处理接收中断。首先检查接收DMA使能标志,然后禁用接收中断,配置RX DMA并启用RX DMA通道。当接收到数据时,将数据复制到接收缓冲区,并调用接收中断回调函数。当接收缓冲区满时,关闭RX DMA通道并重置接收索引。
- */
-void uart_reception_callback(uart_t *uart)
-{
- DBG_ASSERT(uart != NULL __DBG_LINE);
- if (LL_USART_IsEnabledIT_RXNE(uart->huart) && LL_USART_IsActiveFlag_RXNE(uart->huart))
- {
- uart->rxbuf[uart->rx_index++] = LL_USART_ReceiveData8(uart->huart);
- if (uart->rx_dma_en == FALSE) // 中断方式:一个字节一个字节的接收
- {
- if (uart->rx_interupt_cb != NULL)
- {
- uart->rx_interupt_cb(uart->uart_index, uart->rxbuf, uart->rx_index);
- }
- uart->rx_index = 0;
- }
- }
- else if (LL_USART_IsEnabledIT_IDLE(uart->huart) && LL_USART_IsActiveFlag_IDLE(uart->huart))
- {
- if (uart->rx_dma_en == TRUE)
- {
- LL_DMA_DisableChannel(uart->dma, uart->dma_rx_channel);
- uart->rx_index = uart->rxsize - LL_DMA_GetDataLength(uart->dma, uart->dma_rx_channel);
- if (uart->rx_interupt_cb != NULL && (uart->rx_index > 0 && uart->rx_index <= uart->rxsize))
- {
- uart->rx_interupt_cb(uart->uart_index, uart->rxbuf, uart->rx_index);
- osel_memset(uart->rxbuf, 0, uart->rxsize);
- }
- LL_DMA_SetDataLength(uart->dma, uart->dma_rx_channel, uart->rxsize); // 这个不能少 先关闭DMA才能重新设置长度
- LL_DMA_EnableChannel(uart->dma, uart->dma_rx_channel);
- }
-
- uart->rx_index = 0;
- LL_USART_ClearFlag_IDLE(uart->huart);
- }
-
- if (LL_USART_IsEnabledIT_TC(uart->huart) && LL_USART_IsActiveFlag_TC(uart->huart))
- {
- if (uart->tx_complete_cb != NULL)
- {
- uart->tx_complete_cb();
- }
- LL_USART_ClearFlag_TC(uart->huart);
- }
-
- if (LL_USART_IsEnabledIT_PE(uart->huart) && LL_USART_IsActiveFlag_PE(uart->huart))
- {
- LL_USART_ClearFlag_PE(uart->huart);
- }
-
- if (LL_USART_IsActiveFlag_FE(uart->huart) && LL_USART_IsActiveFlag_FE(uart->huart))
- {
- LL_USART_ClearFlag_FE(uart->huart);
- }
-
- if (LL_USART_IsActiveFlag_NE(uart->huart) && LL_USART_IsActiveFlag_NE(uart->huart))
- {
- LL_USART_ClearFlag_NE(uart->huart);
- }
-
- if (LL_USART_IsActiveFlag_ORE(uart->huart) && LL_USART_IsActiveFlag_ORE(uart->huart))
- {
- LL_USART_ClearFlag_ORE(uart->huart);
- }
-}
-
-/**
- * @brief 用于处理串口DMA接收中断的回调函数
- * @param {uart_t} *uart - 串口对象
- * @return {*} 无
- * @note:
- */
-void uart_dma_reception_callback(uart_t *uart)
-{
- // 检查输入参数是否为空
- DBG_ASSERT(uart != NULL __DBG_LINE);
-
- // 禁用串口DMA的发送通道
- LL_DMA_DisableChannel(uart->dma, uart->dma_tx_channel);
-
- // 清除发送中断标志位
- DMA_CLEAR_FLAG_TC_CHANNEL(uart->dma, uart->dma_tx_channel);
-
- // 使能发送中断,用于关闭发送使能引脚
- LL_USART_EnableIT_TC(uart->huart); // 使能发送中断,用于关闭发送使能引脚
- uart->tx_dma_ok = TRUE;
-
- // 清除传输错误标志
- DMA_CLEAR_FLAG_TE_CHANNEL(uart->dma, uart->dma_tx_channel);
-}
diff --git a/User/system/bsp/uarts.h b/User/system/bsp/uarts.h
index 19e3cb8..fb17c39 100644
--- a/User/system/bsp/uarts.h
+++ b/User/system/bsp/uarts.h
@@ -12,6 +12,38 @@
#include "lib.h"
#include "main.h"
+// 串口中断用于接收超时的参数
+#define RX_TIMEOUT_TICK (1U) /* 10ms的tick */
+#define RX_TIMEOUT_MSEC (20U / RX_TIMEOUT_TICK) /* 20毫秒需要的tick,可以根据需求添加其他时间更短的宏 */
+
+/**
+ * @brief Enumeration for UART status.
+ */
+typedef enum
+{
+ UART_OK = 0x00u, /**< The action was successful. */
+ UART_ERROR = 0xFFu /**< Generic error. */
+} uart_status_e;
+
+typedef enum
+{
+ // 无错误
+ UART_NO_ERROR = BIT0,
+ // 奇偶校验错误中断
+ UART_PARITY_ERROR = BIT1,
+ // 帧错误中断
+ UART_FRAME_ERROR = BIT2,
+ // 噪声错误中断
+ UART_NOISE_ERROR = BIT3,
+ // 溢出错误中断
+ UART_OVERRUN_ERROR = BIT4,
+} uarts_interupt_error_e; ///< UART中断错误枚举
+
+typedef struct
+{
+ uarts_interupt_error_e err; ///< 错误标志
+ uint16_t index; ///< 接收到的第几个字节
+} uarts_interupt_error_t;
/**
* @brief Callback function type for UART receive interrupt.
@@ -20,6 +52,7 @@
* The callback function is called when data is received on the UART.
*
* @param uart_index The index of the UART.
+ * @param uart_error The error code.
* @param data The received data.
* @param len The length of the received data.
*/
@@ -33,34 +66,37 @@ typedef void (*rx_interupt_cb_t)(uint8_t uart_index, uint8_t *data, uint16_t len
*/
typedef void (*tx_complete_cb_t)(void);
-/**
- * @brief Enumeration for UART status.
- */
-typedef enum
-{
- UART_OK = 0x00u, /**< The action was successful. */
- UART_ERROR = 0xFFu /**< Generic error. */
-} uart_status_e;
-
/**
* @brief Structure representing a UART instance.
*/
typedef struct
{
- uint8_t uart_index; /**< The index of the UART. */
- USART_TypeDef *huart; /**< The UART peripheral. */
- DMA_TypeDef *dma; /**< The DMA peripheral. */
- uint32_t dma_rx_channel; /**< The DMA receive channel. */
- uint32_t dma_tx_channel; /**< The DMA transmit channel. */
- uint16_t rx_index; /**< The receive data index. */
- BOOL rx_dma_en; /**< Flag indicating if DMA reception is enabled. */
- uint8_t *rxbuf; /**< The receive buffer. */
- uint16_t rxsize; /**< The size of the receive buffer. */
- uint16_t tx_index; /**< The transmit data index. */
- BOOL tx_dma_en; /**< Flag indicating if DMA transmission is enabled. */
- uint8_t *txbuf; /**< The transmit buffer. */
- uint16_t txsize; /**< The size of the transmit buffer. */
- __IO BOOL tx_dma_ok; /**< Flag indicating if DMA transmission is complete. */
+ uint8_t uart_index; /**< The index of the UART. */
+ USART_TypeDef *huart; /**< The UART peripheral. */
+ DMA_TypeDef *dma; /**< The DMA peripheral. */
+ uint32_t dma_rx_channel; /**< The DMA receive channel. */
+ uint32_t dma_tx_channel; /**< The DMA transmit channel. */
+
+ //*******************RX*************************/
+ BOOL rx_cd_en; /**< Flag indicating if carrier detect is enabled. */
+ BOOL rx_dma_en; /**< Flag indicating if DMA reception is enabled. */
+ BOOL rx_err_en; /**< Flag indicating if error interrupt is enabled. */
+ __IO BOOL rx_interupt_timeout; /**< Flag indicating if receive interrupt timeout. */
+ __IO uint8_t rx_interupt_cnt; /**< The receive interrupt count. */
+ uint8_t *rxbuf; /**< The receive buffer. */
+ uint16_t rxsize; /**< The size of the receive buffer. */
+ uarts_interupt_error_t *rx_error; /**< The receive error. */
+ uint16_t rx_error_count; /**< The receive error count. */
+ __IO uint16_t rx_index; /**< The receive data index. */
+
+ //*******************TX*************************/
+
+ BOOL tx_dma_en; /**< Flag indicating if DMA transmission is enabled. */
+ uint8_t *txbuf; /**< The transmit buffer. */
+ uint16_t txsize; /**< The size of the transmit buffer. */
+ uint16_t tx_index; /**< The transmit data index. */
+ __IO BOOL tx_dma_ok; /**< Flag indicating if DMA transmission is complete. */
+
rx_interupt_cb_t rx_interupt_cb; /**< The receive interrupt callback function. */
tx_complete_cb_t tx_complete_cb; /**< The transmit complete callback function. */
} uart_t;
@@ -99,7 +135,7 @@ extern void uart_free(uart_t *uart);
* @param uart The UART instance.
* @param baudrate The baudrate.
*/
-extern void uart_set_baudrate(uart_t *uart, uint32_t baudrate);
+extern void uart_set_baudrate(USART_TypeDef *uart, uint32_t baudrate);
/**
* @brief Enables UART reception.
@@ -108,7 +144,7 @@ extern void uart_set_baudrate(uart_t *uart, uint32_t baudrate);
*
* @param uart The UART instance.
*/
-extern void uart_recv_en(uart_t *uart);
+extern void uart_recv_en(uart_t *uart, BOOL rx_err_en);
/**
* @brief Sends data over UART.
@@ -121,6 +157,23 @@ extern void uart_recv_en(uart_t *uart);
*/
extern void uart_send_data(uart_t *uart, uint8_t *data, uint16_t len);
+/**
+ * @brief UART receive carrier detect callback.
+ *
+ * This function is the callback for UART receive carrier detect.
+ *
+ * @param uart The UART instance.
+ */
+extern void uart_rx_cd_callback(uart_t *uart);
+
+/**
+ * @brief UART receive timeout timer.
+ *
+ * This function is the timer callback for UART receive timeout.
+ *
+ * @param uart The UART instance.
+ */
+extern void uart_rx_timeout_timer(uart_t *uart);
/**
* @brief UART receive interrupt callback.
*
@@ -130,6 +183,29 @@ extern void uart_send_data(uart_t *uart, uint8_t *data, uint16_t len);
*/
extern void uart_reception_callback(uart_t *uart);
+/**
+ * @brief Get the UART error count.
+ *
+ * This function returns the number of errors that have occurred on the specified UART instance.
+ *
+ * @param uart The UART instance.
+ * @return The number of errors.
+ */
+extern uint16_t uart_get_error_count(uart_t *uart);
+
+/**
+ * @brief Get UART interrupt error.
+ *
+ * This function gets the UART interrupt error.
+ *
+ * @param uart The UART instance.
+ * @param count The error count.
+ * @return The error.
+ */
+extern uarts_interupt_error_t *uart_get_error(uart_t *uart);
+
+extern void uart_data_storage_reset(uart_t *uart);
+
/**
* @brief DMA receive interrupt callback.
*
@@ -139,4 +215,4 @@ extern void uart_reception_callback(uart_t *uart);
*/
extern void uart_dma_reception_callback(uart_t *uart);
-#endif // __UARTS_H__
+#endif ///< __UARTS_H__
diff --git a/User/system/inc/btn.h b/User/system/inc/btn.h
index 9f6991b..c78b8bb 100644
--- a/User/system/inc/btn.h
+++ b/User/system/inc/btn.h
@@ -47,7 +47,7 @@ while(1) {
// 根据您的需求修改常量。
#define TICKS_INTERVAL 10 // 按钮扫描间隔,单位ms
-#define DEBOUNCE_TICKS 3 // 按键去抖动时间,单位ms
+#define DEBOUNCE_TICKS 20 / TICKS_INTERVAL // 按键去抖动时间,单位ms
#define SHORT_TICKS (100 / TICKS_INTERVAL) // 短按时间阈值,单位ms
#define LONG_TICKS (500 / TICKS_INTERVAL) // 长按时间阈值,单位ms
@@ -96,6 +96,7 @@ typedef struct Button
uint8_t active_level : 1; // 激活电平
uint8_t button_level : 1; // 按钮电平
uint8_t button_id; // 按钮ID
+ uint8_t button_id_reverse; // 按钮ID反转
uint8_t (*hal_button_Level)(uint8_t button_id_); // 获取按钮引脚电平函数
BtnCallback cb[number_of_event]; // 回调函数数组
struct Button *next; // 下一个按钮句柄
@@ -115,7 +116,7 @@ extern "C"
* @retval 0: 成功
* @retval -1: 失败
*/
- void button_init(struct Button *handle, uint8_t (*pin_level)(uint8_t), active_level_e active_level, uint8_t button_id);
+ void button_init(struct Button *handle, uint8_t (*pin_level)(uint8_t), active_level_e active_level, uint8_t button_id, uint8_t button_id_reverse);
/**
* @brief 附加按钮事件处理函数
diff --git a/User/system/inc/sys.h b/User/system/inc/sys.h
index bcbba2a..163a5cb 100644
--- a/User/system/inc/sys.h
+++ b/User/system/inc/sys.h
@@ -34,6 +34,13 @@ typedef struct
uint32_t sysclk_change; // 改变后的系统时钟 这个参数由change_system_clock函数设置,作为内部观察使用
} clock_config_t; /* 时钟配置结构体 */
+typedef struct
+{
+ uint32_t ticks_max; // 最大ticks
+ uint32_t ticks_current; // 当前使用的ticks
+ uint32_t uticks; // 使用的ticks,用于计算
+} utime_ticks_t;
+
void sys_nvic_set_vector_table(uint32_t baseaddr, uint32_t offset); /* 设置中断偏移量 */
void sys_standby(void); /* 进入待机模式 */
void sys_soft_reset(void); /* 系统软复位 */
diff --git a/User/system/readme.txt b/User/system/readme.txt
index f9c613d..65bff25 100644
--- a/User/system/readme.txt
+++ b/User/system/readme.txt
@@ -1,4 +1,4 @@
1,delay文件夹:存放延时相关的驱动代码。
2,sys文件夹:存放系统相关驱动代码。
3,uart文件夹:存放串口相关代码。
-
\ No newline at end of file
+4,rt-thread:https://zhuanlan.zhihu.com/p/653746487?utm_campaign=shareopn&utm_medium=social&utm_psn=1827650748781039617&utm_source=wechat_session
diff --git a/User/system/rt-thread/bsp/board.c b/User/system/rt-thread/bsp/board.c
new file mode 100644
index 0000000..25d2ed1
--- /dev/null
+++ b/User/system/rt-thread/bsp/board.c
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2006-2019, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2021-05-24 the first version
+ */
+
+#include
+#include
+
+#if defined(RT_USING_USER_MAIN) && defined(RT_USING_HEAP)
+/*
+ * Please modify RT_HEAP_SIZE if you enable RT_USING_HEAP
+ * the RT_HEAP_SIZE max value = (sram size - ZI size), 1024 means 1024 bytes
+ */
+#define RT_HEAP_SIZE (15 * 1024)
+static rt_uint8_t rt_heap[RT_HEAP_SIZE];
+
+RT_WEAK void *rt_heap_begin_get(void)
+{
+ return rt_heap;
+}
+
+RT_WEAK void *rt_heap_end_get(void)
+{
+ return rt_heap + RT_HEAP_SIZE;
+}
+#endif
+
+void rt_os_tick_callback(void)
+{
+ rt_interrupt_enter();
+
+ rt_tick_increase();
+
+ rt_interrupt_leave();
+}
+
+/**
+ * This function will initial your board.
+ */
+void rt_hw_board_init(void)
+{
+ extern void SystemClock_Config(void);
+
+ SystemClock_Config();
+ // #error "TODO 1: OS Tick Configuration."
+ /*
+ * TODO 1: OS Tick Configuration
+ * Enable the hardware timer and call the rt_os_tick_callback function
+ * periodically with the frequency RT_TICK_PER_SECOND.
+ */
+
+ /* Call components board initial (use INIT_BOARD_EXPORT()) */
+#ifdef RT_USING_COMPONENTS_INIT
+ rt_components_board_init();
+#endif
+
+#if defined(RT_USING_USER_MAIN) && defined(RT_USING_HEAP)
+ rt_system_heap_init(rt_heap_begin_get(), rt_heap_end_get());
+#endif
+}
+
+#ifdef RT_USING_CONSOLE
+
+static int uart_init(void)
+{
+#error "TODO 2: Enable the hardware uart and config baudrate."
+ return 0;
+}
+INIT_BOARD_EXPORT(uart_init);
+
+void rt_hw_console_output(const char *str)
+{
+#error "TODO 3: Output the string 'str' through the uart."
+}
+
+#endif
diff --git a/User/system/rt-thread/bsp/rtconfig.h b/User/system/rt-thread/bsp/rtconfig.h
new file mode 100644
index 0000000..39d315f
--- /dev/null
+++ b/User/system/rt-thread/bsp/rtconfig.h
@@ -0,0 +1,143 @@
+/* RT-Thread config file */
+
+#ifndef __RTTHREAD_CFG_H__
+#define __RTTHREAD_CFG_H__
+
+// <<< Use Configuration Wizard in Context Menu >>>
+
+// Basic Configuration
+// Maximal level of thread priority <8-256>
+// Default: 32
+#define RT_THREAD_PRIORITY_MAX 32
+// OS tick per second
+// Default: 1000 (1ms)
+#define RT_TICK_PER_SECOND 1000
+// Alignment size for CPU architecture data access
+// Default: 4
+#define RT_ALIGN_SIZE 4
+// the max length of object name<2-16>
+// Default: 8
+#define RT_NAME_MAX 8
+// Using RT-Thread components initialization
+// Using RT-Thread components initialization
+#define RT_USING_COMPONENTS_INIT
+//
+
+#define RT_USING_USER_MAIN
+
+// the stack size of main thread<1-4086>
+// Default: 512
+#define RT_MAIN_THREAD_STACK_SIZE 256
+
+//
+
+// Debug Configuration
+// enable kernel debug configuration
+// Default: enable kernel debug configuration
+//#define RT_DEBUG
+//
+// enable components initialization debug configuration<0-1>
+// Default: 0
+#define RT_DEBUG_INIT 0
+// thread stack over flow detect
+// Diable Thread stack over flow detect
+//#define RT_USING_OVERFLOW_CHECK
+//
+//
+
+// Hook Configuration
+// using hook
+// using hook
+//#define RT_USING_HOOK
+//
+// using idle hook
+// using idle hook
+//#define RT_USING_IDLE_HOOK
+//
+//
+
+// Software timers Configuration
+// Enables user timers
+#define RT_USING_TIMER_SOFT 0
+#if RT_USING_TIMER_SOFT == 0
+ #undef RT_USING_TIMER_SOFT
+#endif
+// The priority level of timer thread <0-31>
+// Default: 4
+#define RT_TIMER_THREAD_PRIO 4
+// The stack size of timer thread <0-8192>
+// Default: 512
+#define RT_TIMER_THREAD_STACK_SIZE 512
+//
+
+// IPC(Inter-process communication) Configuration
+// Using Semaphore
+// Using Semaphore
+#define RT_USING_SEMAPHORE
+//
+// Using Mutex
+// Using Mutex
+//#define RT_USING_MUTEX
+//
+// Using Event
+// Using Event
+//#define RT_USING_EVENT
+//
+// Using MailBox
+// Using MailBox
+//#define RT_USING_SIGNALS
+//
+// Using Signals
+// Using Signals
+#define RT_USING_MAILBOX
+//
+// Using Message Queue
+// Using Message Queue
+//#define RT_USING_MESSAGEQUEUE
+//
+//
+
+// Memory Management Configuration
+// Memory Pool Management
+// Memory Pool Management
+//#define RT_USING_MEMPOOL
+//
+// Dynamic Heap Management(Algorithm: small memory )
+// Dynamic Heap Management
+#define RT_USING_HEAP
+#define RT_USING_SMALL_MEM
+//
+// using tiny size of memory
+// using tiny size of memory
+//#define RT_USING_TINY_SIZE
+//
+//
+
+// Console Configuration
+// Using console
+// Using console
+//#define RT_USING_CONSOLE
+//
+// the buffer size of console <1-1024>
+// the buffer size of console
+// Default: 128 (128Byte)
+#define RT_CONSOLEBUF_SIZE 256
+//
+
+// FinSH Configuration
+// include finsh config
+// Select this choice if you using FinSH
+//#include "finsh_config.h"
+//
+//
+
+// Device Configuration
+// using device framework
+// using device framework
+//#define RT_USING_DEVICE
+//
+//
+
+// <<< end of configuration section >>>
+
+#endif
diff --git a/User/system/rt-thread/components/finsh/cmd.c b/User/system/rt-thread/components/finsh/cmd.c
new file mode 100644
index 0000000..799d7b3
--- /dev/null
+++ b/User/system/rt-thread/components/finsh/cmd.c
@@ -0,0 +1,994 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2006-04-30 Bernard first implementation
+ * 2006-05-04 Bernard add list_thread,
+ * list_sem,
+ * list_timer
+ * 2006-05-20 Bernard add list_mutex,
+ * list_mailbox,
+ * list_msgqueue,
+ * list_event,
+ * list_fevent,
+ * list_mempool
+ * 2006-06-03 Bernard display stack information in list_thread
+ * 2006-08-10 Bernard change version to invoke rt_show_version
+ * 2008-09-10 Bernard update the list function for finsh syscall
+ * list and sysvar list
+ * 2009-05-30 Bernard add list_device
+ * 2010-04-21 yi.qiu add list_module
+ * 2012-04-29 goprife improve the command line auto-complete feature.
+ * 2012-06-02 lgnq add list_memheap
+ * 2012-10-22 Bernard add MS VC++ patch.
+ * 2016-06-02 armink beautify the list_thread command
+ * 2018-11-22 Jesven list_thread add smp support
+ * 2018-12-27 Jesven Fix the problem that disable interrupt too long in list_thread
+ * Provide protection for the "first layer of objects" when list_*
+ * 2020-04-07 chenhui add clear
+ * 2022-07-02 Stanley Lwin add list command
+ */
+
+#include
+#include
+#include
+
+#ifdef RT_USING_FINSH
+#include
+
+#define LIST_FIND_OBJ_NR 8
+
+static long clear(void)
+{
+ rt_kprintf("\x1b[2J\x1b[H");
+
+ return 0;
+}
+MSH_CMD_EXPORT(clear, clear the terminal screen);
+
+extern void rt_show_version(void);
+long version(void)
+{
+ rt_show_version();
+
+ return 0;
+}
+MSH_CMD_EXPORT(version, show RT-Thread version information);
+
+rt_inline void object_split(int len)
+{
+ while (len--) rt_kprintf("-");
+}
+
+typedef struct
+{
+ rt_list_t *list;
+ rt_list_t **array;
+ rt_uint8_t type;
+ int nr; /* input: max nr, can't be 0 */
+ int nr_out; /* out: got nr */
+} list_get_next_t;
+
+static void list_find_init(list_get_next_t *p, rt_uint8_t type, rt_list_t **array, int nr)
+{
+ struct rt_object_information *info;
+ rt_list_t *list;
+
+ info = rt_object_get_information((enum rt_object_class_type)type);
+ list = &info->object_list;
+
+ p->list = list;
+ p->type = type;
+ p->array = array;
+ p->nr = nr;
+ p->nr_out = 0;
+}
+
+static rt_list_t *list_get_next(rt_list_t *current, list_get_next_t *arg)
+{
+ int first_flag = 0;
+ rt_base_t level;
+ rt_list_t *node, *list;
+ rt_list_t **array;
+ int nr;
+
+ arg->nr_out = 0;
+
+ if (!arg->nr || !arg->type)
+ {
+ return (rt_list_t *)RT_NULL;
+ }
+
+ list = arg->list;
+
+ if (!current) /* find first */
+ {
+ node = list;
+ first_flag = 1;
+ }
+ else
+ {
+ node = current;
+ }
+
+ level = rt_hw_interrupt_disable();
+
+ if (!first_flag)
+ {
+ struct rt_object *obj;
+ /* The node in the list? */
+ obj = rt_list_entry(node, struct rt_object, list);
+ if ((obj->type & ~RT_Object_Class_Static) != arg->type)
+ {
+ rt_hw_interrupt_enable(level);
+ return (rt_list_t *)RT_NULL;
+ }
+ }
+
+ nr = 0;
+ array = arg->array;
+ while (1)
+ {
+ node = node->next;
+
+ if (node == list)
+ {
+ node = (rt_list_t *)RT_NULL;
+ break;
+ }
+ nr++;
+ *array++ = node;
+ if (nr == arg->nr)
+ {
+ break;
+ }
+ }
+
+ rt_hw_interrupt_enable(level);
+ arg->nr_out = nr;
+ return node;
+}
+
+long list_thread(void)
+{
+ rt_base_t level;
+ list_get_next_t find_arg;
+ rt_list_t *obj_list[LIST_FIND_OBJ_NR];
+ rt_list_t *next = (rt_list_t *)RT_NULL;
+ const char *item_title = "thread";
+ int maxlen;
+
+ list_find_init(&find_arg, RT_Object_Class_Thread, obj_list, sizeof(obj_list) / sizeof(obj_list[0]));
+
+ maxlen = RT_NAME_MAX;
+
+#ifdef RT_USING_SMP
+ rt_kprintf("%-*.s cpu bind pri status sp stack size max used left tick error\n", maxlen, item_title);
+ object_split(maxlen);
+ rt_kprintf(" --- ---- --- ------- ---------- ---------- ------ ---------- ---\n");
+#else
+ rt_kprintf("%-*.s pri status sp stack size max used left tick error\n", maxlen, item_title);
+ object_split(maxlen);
+ rt_kprintf(" --- ------- ---------- ---------- ------ ---------- ---\n");
+#endif /*RT_USING_SMP*/
+
+ do
+ {
+ next = list_get_next(next, &find_arg);
+ {
+ int i;
+ for (i = 0; i < find_arg.nr_out; i++)
+ {
+ struct rt_object *obj;
+ struct rt_thread thread_info, *thread;
+
+ obj = rt_list_entry(obj_list[i], struct rt_object, list);
+ level = rt_hw_interrupt_disable();
+
+ if ((obj->type & ~RT_Object_Class_Static) != find_arg.type)
+ {
+ rt_hw_interrupt_enable(level);
+ continue;
+ }
+ /* copy info */
+ rt_memcpy(&thread_info, obj, sizeof thread_info);
+ rt_hw_interrupt_enable(level);
+
+ thread = (struct rt_thread *)obj;
+ {
+ rt_uint8_t stat;
+ rt_uint8_t *ptr;
+
+#ifdef RT_USING_SMP
+ if (thread->oncpu != RT_CPU_DETACHED)
+ rt_kprintf("%-*.*s %3d %3d %4d ", maxlen, RT_NAME_MAX, thread->name, thread->oncpu, thread->bind_cpu, thread->current_priority);
+ else
+ rt_kprintf("%-*.*s N/A %3d %4d ", maxlen, RT_NAME_MAX, thread->name, thread->bind_cpu, thread->current_priority);
+
+#else
+ rt_kprintf("%-*.*s %3d ", maxlen, RT_NAME_MAX, thread->name, thread->current_priority);
+#endif /*RT_USING_SMP*/
+ stat = (thread->stat & RT_THREAD_STAT_MASK);
+ if (stat == RT_THREAD_READY) rt_kprintf(" ready ");
+ else if (stat == RT_THREAD_SUSPEND) rt_kprintf(" suspend");
+ else if (stat == RT_THREAD_INIT) rt_kprintf(" init ");
+ else if (stat == RT_THREAD_CLOSE) rt_kprintf(" close ");
+ else if (stat == RT_THREAD_RUNNING) rt_kprintf(" running");
+
+#if defined(ARCH_CPU_STACK_GROWS_UPWARD)
+ ptr = (rt_uint8_t *)thread->stack_addr + thread->stack_size - 1;
+ while (*ptr == '#')ptr --;
+
+ rt_kprintf(" 0x%08x 0x%08x %02d%% 0x%08x %03d\n",
+ ((rt_ubase_t)thread->sp - (rt_ubase_t)thread->stack_addr),
+ thread->stack_size,
+ ((rt_ubase_t)ptr - (rt_ubase_t)thread->stack_addr) * 100 / thread->stack_size,
+ thread->remaining_tick,
+ thread->error);
+#else
+ ptr = (rt_uint8_t *)thread->stack_addr;
+ while (*ptr == '#') ptr ++;
+ rt_kprintf(" 0x%08x 0x%08x %02d%% 0x%08x %s\n",
+ thread->stack_size + ((rt_ubase_t)thread->stack_addr - (rt_ubase_t)thread->sp),
+ thread->stack_size,
+ (thread->stack_size - ((rt_ubase_t) ptr - (rt_ubase_t) thread->stack_addr)) * 100
+ / thread->stack_size,
+ thread->remaining_tick,
+ rt_strerror(thread->error));
+#endif
+ }
+ }
+ }
+ }
+ while (next != (rt_list_t *)RT_NULL);
+
+ return 0;
+}
+MSH_CMD_EXPORT(list_thread, list thread);
+
+static void show_wait_queue(struct rt_list_node *list)
+{
+ struct rt_thread *thread;
+ struct rt_list_node *node;
+
+ for (node = list->next; node != list; node = node->next)
+ {
+ thread = rt_list_entry(node, struct rt_thread, tlist);
+ rt_kprintf("%.*s", RT_NAME_MAX, thread->name);
+
+ if (node->next != list)
+ rt_kprintf("/");
+ }
+}
+
+#ifdef RT_USING_SEMAPHORE
+long list_sem(void)
+{
+ rt_base_t level;
+ list_get_next_t find_arg;
+ rt_list_t *obj_list[LIST_FIND_OBJ_NR];
+ rt_list_t *next = (rt_list_t *)RT_NULL;
+
+ int maxlen;
+ const char *item_title = "semaphore";
+
+ list_find_init(&find_arg, RT_Object_Class_Semaphore, obj_list, sizeof(obj_list) / sizeof(obj_list[0]));
+
+ maxlen = RT_NAME_MAX;
+
+ rt_kprintf("%-*.s v suspend thread\n", maxlen, item_title);
+ object_split(maxlen);
+ rt_kprintf(" --- --------------\n");
+
+ do
+ {
+ next = list_get_next(next, &find_arg);
+ {
+ int i;
+ for (i = 0; i < find_arg.nr_out; i++)
+ {
+ struct rt_object *obj;
+ struct rt_semaphore *sem;
+
+ obj = rt_list_entry(obj_list[i], struct rt_object, list);
+ level = rt_hw_interrupt_disable();
+ if ((obj->type & ~RT_Object_Class_Static) != find_arg.type)
+ {
+ rt_hw_interrupt_enable(level);
+ continue;
+ }
+ rt_hw_interrupt_enable(level);
+
+ sem = (struct rt_semaphore *)obj;
+ if (!rt_list_isempty(&sem->parent.suspend_thread))
+ {
+ rt_kprintf("%-*.*s %03d %d:",
+ maxlen, RT_NAME_MAX,
+ sem->parent.parent.name,
+ sem->value,
+ rt_list_len(&sem->parent.suspend_thread));
+ show_wait_queue(&(sem->parent.suspend_thread));
+ rt_kprintf("\n");
+ }
+ else
+ {
+ rt_kprintf("%-*.*s %03d %d\n",
+ maxlen, RT_NAME_MAX,
+ sem->parent.parent.name,
+ sem->value,
+ rt_list_len(&sem->parent.suspend_thread));
+ }
+ }
+ }
+ }
+ while (next != (rt_list_t *)RT_NULL);
+
+ return 0;
+}
+MSH_CMD_EXPORT(list_sem, list semaphore in system);
+#endif
+
+#ifdef RT_USING_EVENT
+long list_event(void)
+{
+ rt_base_t level;
+ list_get_next_t find_arg;
+ rt_list_t *obj_list[LIST_FIND_OBJ_NR];
+ rt_list_t *next = (rt_list_t *)RT_NULL;
+
+ int maxlen;
+ const char *item_title = "event";
+
+ list_find_init(&find_arg, RT_Object_Class_Event, obj_list, sizeof(obj_list) / sizeof(obj_list[0]));
+
+ maxlen = RT_NAME_MAX;
+
+ rt_kprintf("%-*.s set suspend thread\n", maxlen, item_title);
+ object_split(maxlen);
+ rt_kprintf(" ---------- --------------\n");
+
+ do
+ {
+ next = list_get_next(next, &find_arg);
+ {
+ int i;
+ for (i = 0; i < find_arg.nr_out; i++)
+ {
+ struct rt_object *obj;
+ struct rt_event *e;
+
+ obj = rt_list_entry(obj_list[i], struct rt_object, list);
+ level = rt_hw_interrupt_disable();
+ if ((obj->type & ~RT_Object_Class_Static) != find_arg.type)
+ {
+ rt_hw_interrupt_enable(level);
+ continue;
+ }
+
+ rt_hw_interrupt_enable(level);
+
+ e = (struct rt_event *)obj;
+ if (!rt_list_isempty(&e->parent.suspend_thread))
+ {
+ rt_kprintf("%-*.*s 0x%08x %03d:",
+ maxlen, RT_NAME_MAX,
+ e->parent.parent.name,
+ e->set,
+ rt_list_len(&e->parent.suspend_thread));
+ show_wait_queue(&(e->parent.suspend_thread));
+ rt_kprintf("\n");
+ }
+ else
+ {
+ rt_kprintf("%-*.*s 0x%08x 0\n",
+ maxlen, RT_NAME_MAX, e->parent.parent.name, e->set);
+ }
+ }
+ }
+ }
+ while (next != (rt_list_t *)RT_NULL);
+
+ return 0;
+}
+MSH_CMD_EXPORT(list_event, list event in system);
+#endif
+
+#ifdef RT_USING_MUTEX
+long list_mutex(void)
+{
+ rt_base_t level;
+ list_get_next_t find_arg;
+ rt_list_t *obj_list[LIST_FIND_OBJ_NR];
+ rt_list_t *next = (rt_list_t *)RT_NULL;
+
+ int maxlen;
+ const char *item_title = "mutex";
+
+ list_find_init(&find_arg, RT_Object_Class_Mutex, obj_list, sizeof(obj_list) / sizeof(obj_list[0]));
+
+ maxlen = RT_NAME_MAX;
+
+ rt_kprintf("%-*.s owner hold suspend thread\n", maxlen, item_title);
+ object_split(maxlen);
+ rt_kprintf(" -------- ---- --------------\n");
+
+ do
+ {
+ next = list_get_next(next, &find_arg);
+ {
+ int i;
+ for (i = 0; i < find_arg.nr_out; i++)
+ {
+ struct rt_object *obj;
+ struct rt_mutex *m;
+
+ obj = rt_list_entry(obj_list[i], struct rt_object, list);
+ level = rt_hw_interrupt_disable();
+ if ((obj->type & ~RT_Object_Class_Static) != find_arg.type)
+ {
+ rt_hw_interrupt_enable(level);
+ continue;
+ }
+
+ rt_hw_interrupt_enable(level);
+
+ m = (struct rt_mutex *)obj;
+ rt_kprintf("%-*.*s %-8.*s %04d %d\n",
+ maxlen, RT_NAME_MAX,
+ m->parent.parent.name,
+ RT_NAME_MAX,
+ m->owner->name,
+ m->hold,
+ rt_list_len(&m->parent.suspend_thread));
+
+ }
+ }
+ }
+ while (next != (rt_list_t *)RT_NULL);
+
+ return 0;
+}
+MSH_CMD_EXPORT(list_mutex, list mutex in system);
+#endif
+
+#ifdef RT_USING_MAILBOX
+long list_mailbox(void)
+{
+ rt_base_t level;
+ list_get_next_t find_arg;
+ rt_list_t *obj_list[LIST_FIND_OBJ_NR];
+ rt_list_t *next = (rt_list_t *)RT_NULL;
+
+ int maxlen;
+ const char *item_title = "mailbox";
+
+ list_find_init(&find_arg, RT_Object_Class_MailBox, obj_list, sizeof(obj_list) / sizeof(obj_list[0]));
+
+ maxlen = RT_NAME_MAX;
+
+ rt_kprintf("%-*.s entry size suspend thread\n", maxlen, item_title);
+ object_split(maxlen);
+ rt_kprintf(" ---- ---- --------------\n");
+
+ do
+ {
+ next = list_get_next(next, &find_arg);
+ {
+ int i;
+ for (i = 0; i < find_arg.nr_out; i++)
+ {
+ struct rt_object *obj;
+ struct rt_mailbox *m;
+
+ obj = rt_list_entry(obj_list[i], struct rt_object, list);
+ level = rt_hw_interrupt_disable();
+ if ((obj->type & ~RT_Object_Class_Static) != find_arg.type)
+ {
+ rt_hw_interrupt_enable(level);
+ continue;
+ }
+
+ rt_hw_interrupt_enable(level);
+
+ m = (struct rt_mailbox *)obj;
+ if (!rt_list_isempty(&m->parent.suspend_thread))
+ {
+ rt_kprintf("%-*.*s %04d %04d %d:",
+ maxlen, RT_NAME_MAX,
+ m->parent.parent.name,
+ m->entry,
+ m->size,
+ rt_list_len(&m->parent.suspend_thread));
+ show_wait_queue(&(m->parent.suspend_thread));
+ rt_kprintf("\n");
+ }
+ else
+ {
+ rt_kprintf("%-*.*s %04d %04d %d\n",
+ maxlen, RT_NAME_MAX,
+ m->parent.parent.name,
+ m->entry,
+ m->size,
+ rt_list_len(&m->parent.suspend_thread));
+ }
+
+ }
+ }
+ }
+ while (next != (rt_list_t *)RT_NULL);
+
+ return 0;
+}
+MSH_CMD_EXPORT(list_mailbox, list mail box in system);
+#endif
+
+#ifdef RT_USING_MESSAGEQUEUE
+long list_msgqueue(void)
+{
+ rt_base_t level;
+ list_get_next_t find_arg;
+ rt_list_t *obj_list[LIST_FIND_OBJ_NR];
+ rt_list_t *next = (rt_list_t *)RT_NULL;
+
+ int maxlen;
+ const char *item_title = "msgqueue";
+
+ list_find_init(&find_arg, RT_Object_Class_MessageQueue, obj_list, sizeof(obj_list) / sizeof(obj_list[0]));
+
+ maxlen = RT_NAME_MAX;
+
+ rt_kprintf("%-*.s entry suspend thread\n", maxlen, item_title);
+ object_split(maxlen);
+ rt_kprintf(" ---- --------------\n");
+ do
+ {
+ next = list_get_next(next, &find_arg);
+ {
+ int i;
+ for (i = 0; i < find_arg.nr_out; i++)
+ {
+ struct rt_object *obj;
+ struct rt_messagequeue *m;
+
+ obj = rt_list_entry(obj_list[i], struct rt_object, list);
+ level = rt_hw_interrupt_disable();
+ if ((obj->type & ~RT_Object_Class_Static) != find_arg.type)
+ {
+ rt_hw_interrupt_enable(level);
+ continue;
+ }
+
+ rt_hw_interrupt_enable(level);
+
+ m = (struct rt_messagequeue *)obj;
+ if (!rt_list_isempty(&m->parent.suspend_thread))
+ {
+ rt_kprintf("%-*.*s %04d %d:",
+ maxlen, RT_NAME_MAX,
+ m->parent.parent.name,
+ m->entry,
+ rt_list_len(&m->parent.suspend_thread));
+ show_wait_queue(&(m->parent.suspend_thread));
+ rt_kprintf("\n");
+ }
+ else
+ {
+ rt_kprintf("%-*.*s %04d %d\n",
+ maxlen, RT_NAME_MAX,
+ m->parent.parent.name,
+ m->entry,
+ rt_list_len(&m->parent.suspend_thread));
+ }
+ }
+ }
+ }
+ while (next != (rt_list_t *)RT_NULL);
+
+ return 0;
+}
+MSH_CMD_EXPORT(list_msgqueue, list message queue in system);
+#endif
+
+#ifdef RT_USING_MEMHEAP
+long list_memheap(void)
+{
+ rt_base_t level;
+ list_get_next_t find_arg;
+ rt_list_t *obj_list[LIST_FIND_OBJ_NR];
+ rt_list_t *next = (rt_list_t *)RT_NULL;
+
+ int maxlen;
+ const char *item_title = "memheap";
+
+ list_find_init(&find_arg, RT_Object_Class_MemHeap, obj_list, sizeof(obj_list) / sizeof(obj_list[0]));
+
+ maxlen = RT_NAME_MAX;
+
+ rt_kprintf("%-*.s pool size max used size available size\n", maxlen, item_title);
+ object_split(maxlen);
+ rt_kprintf(" ---------- ------------- --------------\n");
+ do
+ {
+ next = list_get_next(next, &find_arg);
+ {
+ int i;
+ for (i = 0; i < find_arg.nr_out; i++)
+ {
+ struct rt_object *obj;
+ struct rt_memheap *mh;
+
+ obj = rt_list_entry(obj_list[i], struct rt_object, list);
+ level = rt_hw_interrupt_disable();
+ if ((obj->type & ~RT_Object_Class_Static) != find_arg.type)
+ {
+ rt_hw_interrupt_enable(level);
+ continue;
+ }
+
+ rt_hw_interrupt_enable(level);
+
+ mh = (struct rt_memheap *)obj;
+
+ rt_kprintf("%-*.*s %-010d %-013d %-05d\n",
+ maxlen, RT_NAME_MAX,
+ mh->parent.name,
+ mh->pool_size,
+ mh->max_used_size,
+ mh->available_size);
+
+ }
+ }
+ }
+ while (next != (rt_list_t *)RT_NULL);
+
+ return 0;
+}
+MSH_CMD_EXPORT(list_memheap, list memory heap in system);
+#endif
+
+#ifdef RT_USING_MEMPOOL
+long list_mempool(void)
+{
+ rt_base_t level;
+ list_get_next_t find_arg;
+ rt_list_t *obj_list[LIST_FIND_OBJ_NR];
+ rt_list_t *next = (rt_list_t *)RT_NULL;
+
+ int maxlen;
+ const char *item_title = "mempool";
+
+ list_find_init(&find_arg, RT_Object_Class_MemPool, obj_list, sizeof(obj_list) / sizeof(obj_list[0]));
+
+ maxlen = RT_NAME_MAX;
+
+ rt_kprintf("%-*.s block total free suspend thread\n", maxlen, item_title);
+ object_split(maxlen);
+ rt_kprintf(" ---- ---- ---- --------------\n");
+ do
+ {
+ next = list_get_next(next, &find_arg);
+ {
+ int i;
+ for (i = 0; i < find_arg.nr_out; i++)
+ {
+ struct rt_object *obj;
+ struct rt_mempool *mp;
+ int suspend_thread_count;
+ rt_list_t *node;
+
+ obj = rt_list_entry(obj_list[i], struct rt_object, list);
+ level = rt_hw_interrupt_disable();
+ if ((obj->type & ~RT_Object_Class_Static) != find_arg.type)
+ {
+ rt_hw_interrupt_enable(level);
+ continue;
+ }
+
+ rt_hw_interrupt_enable(level);
+
+ mp = (struct rt_mempool *)obj;
+
+ suspend_thread_count = 0;
+ rt_list_for_each(node, &mp->suspend_thread)
+ {
+ suspend_thread_count++;
+ }
+
+ if (suspend_thread_count > 0)
+ {
+ rt_kprintf("%-*.*s %04d %04d %04d %d:",
+ maxlen, RT_NAME_MAX,
+ mp->parent.name,
+ mp->block_size,
+ mp->block_total_count,
+ mp->block_free_count,
+ suspend_thread_count);
+ show_wait_queue(&(mp->suspend_thread));
+ rt_kprintf("\n");
+ }
+ else
+ {
+ rt_kprintf("%-*.*s %04d %04d %04d %d\n",
+ maxlen, RT_NAME_MAX,
+ mp->parent.name,
+ mp->block_size,
+ mp->block_total_count,
+ mp->block_free_count,
+ suspend_thread_count);
+ }
+ }
+ }
+ }
+ while (next != (rt_list_t *)RT_NULL);
+
+ return 0;
+}
+MSH_CMD_EXPORT(list_mempool, list memory pool in system);
+#endif
+
+long list_timer(void)
+{
+ rt_base_t level;
+ list_get_next_t find_arg;
+ rt_list_t *obj_list[LIST_FIND_OBJ_NR];
+ rt_list_t *next = (rt_list_t *)RT_NULL;
+
+ int maxlen;
+ const char *item_title = "timer";
+
+ list_find_init(&find_arg, RT_Object_Class_Timer, obj_list, sizeof(obj_list) / sizeof(obj_list[0]));
+
+ maxlen = RT_NAME_MAX;
+
+ rt_kprintf("%-*.s periodic timeout activated mode\n", maxlen, item_title);
+ object_split(maxlen);
+ rt_kprintf(" ---------- ---------- ----------- ---------\n");
+ do
+ {
+ next = list_get_next(next, &find_arg);
+ {
+ int i;
+ for (i = 0; i < find_arg.nr_out; i++)
+ {
+ struct rt_object *obj;
+ struct rt_timer *timer;
+
+ obj = rt_list_entry(obj_list[i], struct rt_object, list);
+ level = rt_hw_interrupt_disable();
+ if ((obj->type & ~RT_Object_Class_Static) != find_arg.type)
+ {
+ rt_hw_interrupt_enable(level);
+ continue;
+ }
+
+ rt_hw_interrupt_enable(level);
+
+ timer = (struct rt_timer *)obj;
+ rt_kprintf("%-*.*s 0x%08x 0x%08x ",
+ maxlen, RT_NAME_MAX,
+ timer->parent.name,
+ timer->init_tick,
+ timer->timeout_tick);
+ if (timer->parent.flag & RT_TIMER_FLAG_ACTIVATED)
+ rt_kprintf("activated ");
+ else
+ rt_kprintf("deactivated ");
+ if (timer->parent.flag & RT_TIMER_FLAG_PERIODIC)
+ rt_kprintf("periodic\n");
+ else
+ rt_kprintf("one shot\n");
+
+ }
+ }
+ }
+ while (next != (rt_list_t *)RT_NULL);
+
+ rt_kprintf("current tick:0x%08x\n", rt_tick_get());
+
+ return 0;
+}
+MSH_CMD_EXPORT(list_timer, list timer in system);
+
+#ifdef RT_USING_DEVICE
+static char *const device_type_str[RT_Device_Class_Unknown] =
+{
+ "Character Device",
+ "Block Device",
+ "Network Interface",
+ "MTD Device",
+ "CAN Device",
+ "RTC",
+ "Sound Device",
+ "Graphic Device",
+ "I2C Bus",
+ "USB Slave Device",
+ "USB Host Bus",
+ "USB OTG Bus",
+ "SPI Bus",
+ "SPI Device",
+ "SDIO Bus",
+ "PM Pseudo Device",
+ "Pipe",
+ "Portal Device",
+ "Timer Device",
+ "Miscellaneous Device",
+ "Sensor Device",
+ "Touch Device",
+ "Phy Device",
+ "Security Device",
+ "WLAN Device",
+ "Pin Device",
+ "ADC Device",
+ "DAC Device",
+ "WDT Device",
+ "PWM Device",
+};
+
+long list_device(void)
+{
+ rt_base_t level;
+ list_get_next_t find_arg;
+ rt_list_t *obj_list[LIST_FIND_OBJ_NR];
+ rt_list_t *next = (rt_list_t *)RT_NULL;
+ const char *device_type;
+
+ int maxlen;
+ const char *item_title = "device";
+
+ list_find_init(&find_arg, RT_Object_Class_Device, obj_list, sizeof(obj_list) / sizeof(obj_list[0]));
+
+ maxlen = RT_NAME_MAX;
+
+ rt_kprintf("%-*.s type ref count\n", maxlen, item_title);
+ object_split(maxlen);
+ rt_kprintf(" -------------------- ----------\n");
+ do
+ {
+ next = list_get_next(next, &find_arg);
+ {
+ int i;
+ for (i = 0; i < find_arg.nr_out; i++)
+ {
+ struct rt_object *obj;
+ struct rt_device *device;
+
+ obj = rt_list_entry(obj_list[i], struct rt_object, list);
+ level = rt_hw_interrupt_disable();
+ if ((obj->type & ~RT_Object_Class_Static) != find_arg.type)
+ {
+ rt_hw_interrupt_enable(level);
+ continue;
+ }
+
+ rt_hw_interrupt_enable(level);
+
+ device = (struct rt_device *)obj;
+ device_type = "Unknown";
+ if (device->type < RT_Device_Class_Unknown &&
+ device_type_str[device->type] != RT_NULL)
+ {
+ device_type = device_type_str[device->type];
+ }
+ rt_kprintf("%-*.*s %-20s %-8d\n",
+ maxlen, RT_NAME_MAX,
+ device->parent.name,
+ device_type,
+ device->ref_count);
+
+ }
+ }
+ }
+ while (next != (rt_list_t *)RT_NULL);
+
+ return 0;
+}
+MSH_CMD_EXPORT(list_device, list device in system);
+#endif
+
+int cmd_list(int argc, char **argv)
+{
+ if(argc == 2)
+ {
+ if(strcmp(argv[1], "thread") == 0)
+ {
+ list_thread();
+ }
+ else if(strcmp(argv[1], "timer") == 0)
+ {
+ list_timer();
+ }
+#ifdef RT_USING_SEMAPHORE
+ else if(strcmp(argv[1], "sem") == 0)
+ {
+ list_sem();
+ }
+#endif /* RT_USING_SEMAPHORE */
+#ifdef RT_USING_EVENT
+ else if(strcmp(argv[1], "event") == 0)
+ {
+ list_event();
+ }
+#endif /* RT_USING_EVENT */
+#ifdef RT_USING_MUTEX
+ else if(strcmp(argv[1], "mutex") == 0)
+ {
+ list_mutex();
+ }
+#endif /* RT_USING_MUTEX */
+#ifdef RT_USING_MAILBOX
+ else if(strcmp(argv[1], "mailbox") == 0)
+ {
+ list_mailbox();
+ }
+#endif /* RT_USING_MAILBOX */
+#ifdef RT_USING_MESSAGEQUEUE
+ else if(strcmp(argv[1], "msgqueue") == 0)
+ {
+ list_msgqueue();
+ }
+#endif /* RT_USING_MESSAGEQUEUE */
+#ifdef RT_USING_MEMPOOL
+ else if(strcmp(argv[1], "mempool") == 0)
+ {
+ list_mempool();
+ }
+#endif /* RT_USING_MEMPOOL */
+#ifdef RT_USING_DEVICE
+ else if(strcmp(argv[1], "device") == 0)
+ {
+ list_device();
+ }
+#endif /* RT_USING_DEVICE */
+#ifdef RT_USING_DFS
+ else if(strcmp(argv[1], "fd") == 0)
+ {
+ extern int list_fd(void);
+ list_fd();
+ }
+#endif /* RT_USING_DFS */
+ else
+ {
+ goto _usage;
+ }
+
+ return 0;
+ }
+
+_usage:
+ rt_kprintf("Usage: list [options]\n");
+ rt_kprintf("[options]:\n");
+ rt_kprintf(" thread - list threads\n");
+ rt_kprintf(" timer - list timers\n");
+#ifdef RT_USING_SEMAPHORE
+ rt_kprintf(" sem - list semaphores\n");
+#endif /* RT_USING_SEMAPHORE */
+#ifdef RT_USING_MUTEX
+ rt_kprintf(" mutex - list mutexs\n");
+#endif /* RT_USING_MUTEX */
+#ifdef RT_USING_EVENT
+ rt_kprintf(" event - list events\n");
+#endif /* RT_USING_EVENT */
+#ifdef RT_USING_MAILBOX
+ rt_kprintf(" mailbox - list mailboxs\n");
+#endif /* RT_USING_MAILBOX */
+#ifdef RT_USING_MESSAGEQUEUE
+ rt_kprintf(" msgqueue - list message queues\n");
+#endif /* RT_USING_MESSAGEQUEUE */
+#ifdef RT_USING_MEMPOOL
+ rt_kprintf(" mempool - list memory pools\n");
+#endif /* RT_USING_MEMPOOL */
+#ifdef RT_USING_DEVICE
+ rt_kprintf(" device - list devices\n");
+#endif /* RT_USING_DEVICE */
+#ifdef RT_USING_DFS
+ rt_kprintf(" fd - list file descriptors\n");
+#endif /* RT_USING_DFS */
+
+ return 0;
+}
+MSH_CMD_EXPORT_ALIAS(cmd_list, list, list objects);
+
+#endif /* RT_USING_FINSH */
diff --git a/User/system/rt-thread/components/finsh/finsh.h b/User/system/rt-thread/components/finsh/finsh.h
new file mode 100644
index 0000000..a26b26f
--- /dev/null
+++ b/User/system/rt-thread/components/finsh/finsh.h
@@ -0,0 +1,175 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2010-03-22 Bernard first version
+ */
+#ifndef __FINSH_H__
+#define __FINSH_H__
+
+#include
+
+#ifdef _MSC_VER
+#pragma section("FSymTab$f",read)
+#endif /* _MSC_VER */
+
+typedef long (*syscall_func)(void);
+#ifdef FINSH_USING_SYMTAB
+#ifdef __TI_COMPILER_VERSION__
+#define __TI_FINSH_EXPORT_FUNCTION(f) PRAGMA(DATA_SECTION(f,"FSymTab"))
+#endif /* __TI_COMPILER_VERSION__ */
+#ifdef FINSH_USING_DESCRIPTION
+#ifdef _MSC_VER
+#define MSH_FUNCTION_EXPORT_CMD(name, cmd, desc) \
+ const char __fsym_##cmd##_name[] = #cmd; \
+ const char __fsym_##cmd##_desc[] = #desc; \
+ __declspec(allocate("FSymTab$f")) \
+ const struct finsh_syscall __fsym_##cmd = \
+ { \
+ __fsym_##cmd##_name, \
+ __fsym_##cmd##_desc, \
+ (syscall_func)&name \
+ };
+#pragma comment(linker, "/merge:FSymTab=mytext")
+
+#elif defined(__TI_COMPILER_VERSION__)
+#define MSH_FUNCTION_EXPORT_CMD(name, cmd, desc) \
+ __TI_FINSH_EXPORT_FUNCTION(__fsym_##cmd); \
+ const char __fsym_##cmd##_name[] = #cmd; \
+ const char __fsym_##cmd##_desc[] = #desc; \
+ const struct finsh_syscall __fsym_##cmd = \
+ { \
+ __fsym_##cmd##_name, \
+ __fsym_##cmd##_desc, \
+ (syscall_func)&name \
+ };
+
+#else
+#define MSH_FUNCTION_EXPORT_CMD(name, cmd, desc) \
+ const char __fsym_##cmd##_name[] RT_SECTION(".rodata.name") = #cmd; \
+ const char __fsym_##cmd##_desc[] RT_SECTION(".rodata.name") = #desc; \
+ RT_USED const struct finsh_syscall __fsym_##cmd RT_SECTION("FSymTab")= \
+ { \
+ __fsym_##cmd##_name, \
+ __fsym_##cmd##_desc, \
+ (syscall_func)&name \
+ };
+
+#endif
+#else
+#ifdef _MSC_VER
+#define MSH_FUNCTION_EXPORT_CMD(name, cmd, desc) \
+ const char __fsym_##cmd##_name[] = #cmd; \
+ __declspec(allocate("FSymTab$f")) \
+ const struct finsh_syscall __fsym_##cmd = \
+ { \
+ __fsym_##cmd##_name, \
+ (syscall_func)&name \
+ };
+#pragma comment(linker, "/merge:FSymTab=mytext")
+
+#elif defined(__TI_COMPILER_VERSION__)
+#define MSH_FUNCTION_EXPORT_CMD(name, cmd, desc) \
+ __TI_FINSH_EXPORT_FUNCTION(__fsym_##cmd); \
+ const char __fsym_##cmd##_name[] = #cmd; \
+ const struct finsh_syscall __fsym_##cmd = \
+ { \
+ __fsym_##cmd##_name, \
+ (syscall_func)&name \
+ };
+
+#else
+#define MSH_FUNCTION_EXPORT_CMD(name, cmd, desc) \
+ const char __fsym_##cmd##_name[] = #cmd; \
+ RT_USED const struct finsh_syscall __fsym_##cmd RT_SECTION("FSymTab")= \
+ { \
+ __fsym_##cmd##_name, \
+ (syscall_func)&name \
+ };
+
+#endif
+#endif /* end of FINSH_USING_DESCRIPTION */
+#endif /* end of FINSH_USING_SYMTAB */
+
+/**
+ * @ingroup finsh
+ *
+ * This macro exports a system function to finsh shell.
+ *
+ * @param name the name of function.
+ * @param desc the description of function, which will show in help.
+ */
+#define FINSH_FUNCTION_EXPORT(name, desc)
+
+/**
+ * @ingroup finsh
+ *
+ * This macro exports a system function with an alias name to finsh shell.
+ *
+ * @param name the name of function.
+ * @param alias the alias name of function.
+ * @param desc the description of function, which will show in help.
+ */
+#define FINSH_FUNCTION_EXPORT_ALIAS(name, alias, desc)
+
+/**
+ * @ingroup msh
+ *
+ * This macro exports a command to module shell.
+ *
+ * @param command is the name of the command.
+ * @param desc is the description of the command, which will show in help list.
+ */
+#define MSH_CMD_EXPORT(command, desc) \
+ MSH_FUNCTION_EXPORT_CMD(command, command, desc)
+
+/**
+ * @ingroup msh
+ *
+ * This macro exports a command with alias to module shell.
+ *
+ * @param command is the name of the command.
+ * @param alias is the alias of the command.
+ * @param desc is the description of the command, which will show in help list.
+ */
+#define MSH_CMD_EXPORT_ALIAS(command, alias, desc) \
+ MSH_FUNCTION_EXPORT_CMD(command, alias, desc)
+
+/* system call table */
+struct finsh_syscall
+{
+ const char *name; /* the name of system call */
+#if defined(FINSH_USING_DESCRIPTION) && defined(FINSH_USING_SYMTAB)
+ const char *desc; /* description of system call */
+#endif
+ syscall_func func; /* the function address of system call */
+};
+
+/* system call item */
+struct finsh_syscall_item
+{
+ struct finsh_syscall_item *next; /* next item */
+ struct finsh_syscall syscall; /* syscall */
+};
+
+extern struct finsh_syscall_item *global_syscall_list;
+extern struct finsh_syscall *_syscall_table_begin, *_syscall_table_end;
+
+#if defined(_MSC_VER) || (defined(__GNUC__) && defined(__x86_64__))
+ struct finsh_syscall *finsh_syscall_next(struct finsh_syscall *call);
+ #define FINSH_NEXT_SYSCALL(index) index=finsh_syscall_next(index)
+#else
+ #define FINSH_NEXT_SYSCALL(index) index++
+#endif
+
+/* find out system call, which should be implemented in user program */
+struct finsh_syscall *finsh_syscall_lookup(const char *name);
+
+#if !defined(RT_USING_POSIX_STDIO) && defined(RT_USING_DEVICE)
+void finsh_set_device(const char *device_name);
+#endif
+
+#endif
diff --git a/User/system/rt-thread/components/finsh/msh.c b/User/system/rt-thread/components/finsh/msh.c
new file mode 100644
index 0000000..22e2cf5
--- /dev/null
+++ b/User/system/rt-thread/components/finsh/msh.c
@@ -0,0 +1,606 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2013-03-30 Bernard the first verion for finsh
+ * 2014-01-03 Bernard msh can execute module.
+ * 2017-07-19 Aubr.Cool limit argc to RT_FINSH_ARG_MAX
+ */
+#include
+#include
+
+#ifdef RT_USING_FINSH
+
+#ifndef FINSH_ARG_MAX
+#define FINSH_ARG_MAX 8
+#endif /* FINSH_ARG_MAX */
+
+#include "msh.h"
+#include "shell.h"
+#ifdef DFS_USING_POSIX
+#include
+#include
+#include
+#endif /* DFS_USING_POSIX */
+#ifdef RT_USING_MODULE
+#include
+#endif /* RT_USING_MODULE */
+
+typedef int (*cmd_function_t)(int argc, char **argv);
+
+int msh_help(int argc, char **argv)
+{
+ rt_kprintf("RT-Thread shell commands:\n");
+ {
+ struct finsh_syscall *index;
+
+ for (index = _syscall_table_begin;
+ index < _syscall_table_end;
+ FINSH_NEXT_SYSCALL(index))
+ {
+#if defined(FINSH_USING_DESCRIPTION) && defined(FINSH_USING_SYMTAB)
+ rt_kprintf("%-16s - %s\n", index->name, index->desc);
+#else
+ rt_kprintf("%s ", index->name);
+#endif
+ }
+ }
+ rt_kprintf("\n");
+
+ return 0;
+}
+MSH_CMD_EXPORT_ALIAS(msh_help, help, RT-Thread shell help.);
+
+#ifdef MSH_USING_BUILT_IN_COMMANDS
+int cmd_ps(int argc, char **argv)
+{
+ extern long list_thread(void);
+ extern int list_module(void);
+
+#ifdef RT_USING_MODULE
+ if ((argc == 2) && (strcmp(argv[1], "-m") == 0))
+ list_module();
+ else
+#endif
+ list_thread();
+ return 0;
+}
+MSH_CMD_EXPORT_ALIAS(cmd_ps, ps, List threads in the system.);
+
+#ifdef RT_USING_HEAP
+int cmd_free(int argc, char **argv)
+{
+#ifdef RT_USING_MEMHEAP_AS_HEAP
+ extern void list_memheap(void);
+ list_memheap();
+#else
+ rt_size_t total = 0, used = 0, max_used = 0;
+
+ rt_memory_info(&total, &used, &max_used);
+ rt_kprintf("total : %d\n", total);
+ rt_kprintf("used : %d\n", used);
+ rt_kprintf("maximum : %d\n", max_used);
+ rt_kprintf("available: %d\n", total - used);
+#endif
+ return 0;
+}
+MSH_CMD_EXPORT_ALIAS(cmd_free, free, Show the memory usage in the system.);
+#endif /* RT_USING_HEAP */
+#endif /* MSH_USING_BUILT_IN_COMMANDS */
+
+static int msh_split(char *cmd, rt_size_t length, char *argv[FINSH_ARG_MAX])
+{
+ char *ptr;
+ rt_size_t position;
+ rt_size_t argc;
+ rt_size_t i;
+
+ ptr = cmd;
+ position = 0;
+ argc = 0;
+
+ while (position < length)
+ {
+ /* strip bank and tab */
+ while ((*ptr == ' ' || *ptr == '\t') && position < length)
+ {
+ *ptr = '\0';
+ ptr ++;
+ position ++;
+ }
+
+ if (argc >= FINSH_ARG_MAX)
+ {
+ rt_kprintf("Too many args ! We only Use:\n");
+ for (i = 0; i < argc; i++)
+ {
+ rt_kprintf("%s ", argv[i]);
+ }
+ rt_kprintf("\n");
+ break;
+ }
+
+ if (position >= length) break;
+
+ /* handle string */
+ if (*ptr == '"')
+ {
+ ptr ++;
+ position ++;
+ argv[argc] = ptr;
+ argc ++;
+
+ /* skip this string */
+ while (*ptr != '"' && position < length)
+ {
+ if (*ptr == '\\')
+ {
+ if (*(ptr + 1) == '"')
+ {
+ ptr ++;
+ position ++;
+ }
+ }
+ ptr ++;
+ position ++;
+ }
+ if (position >= length) break;
+
+ /* skip '"' */
+ *ptr = '\0';
+ ptr ++;
+ position ++;
+ }
+ else
+ {
+ argv[argc] = ptr;
+ argc ++;
+ while ((*ptr != ' ' && *ptr != '\t') && position < length)
+ {
+ ptr ++;
+ position ++;
+ }
+ if (position >= length) break;
+ }
+ }
+
+ return argc;
+}
+
+static cmd_function_t msh_get_cmd(char *cmd, int size)
+{
+ struct finsh_syscall *index;
+ cmd_function_t cmd_func = RT_NULL;
+
+ for (index = _syscall_table_begin;
+ index < _syscall_table_end;
+ FINSH_NEXT_SYSCALL(index))
+ {
+ if (strncmp(index->name, cmd, size) == 0 &&
+ index->name[size] == '\0')
+ {
+ cmd_func = (cmd_function_t)index->func;
+ break;
+ }
+ }
+
+ return cmd_func;
+}
+
+#if defined(RT_USING_MODULE) && defined(DFS_USING_POSIX)
+/* Return 0 on module executed. Other value indicate error.
+ */
+int msh_exec_module(const char *cmd_line, int size)
+{
+ int ret;
+ int fd = -1;
+ char *pg_name;
+ int length, cmd_length = 0;
+
+ if (size == 0)
+ return -RT_ERROR;
+ /* get the length of command0 */
+ while ((cmd_line[cmd_length] != ' ' && cmd_line[cmd_length] != '\t') && cmd_length < size)
+ cmd_length ++;
+
+ /* get name length */
+ length = cmd_length + 32;
+
+ /* allocate program name memory */
+ pg_name = (char *) rt_malloc(length);
+ if (pg_name == RT_NULL)
+ return -RT_ENOMEM;
+
+ /* copy command0 */
+ rt_memcpy(pg_name, cmd_line, cmd_length);
+ pg_name[cmd_length] = '\0';
+
+ if (strstr(pg_name, ".mo") != RT_NULL || strstr(pg_name, ".MO") != RT_NULL)
+ {
+ /* try to open program */
+ fd = open(pg_name, O_RDONLY, 0);
+
+ /* search in /bin path */
+ if (fd < 0)
+ {
+ rt_snprintf(pg_name, length - 1, "/bin/%.*s", cmd_length, cmd_line);
+ fd = open(pg_name, O_RDONLY, 0);
+ }
+ }
+ else
+ {
+ /* add .mo and open program */
+
+ /* try to open program */
+ strcat(pg_name, ".mo");
+ fd = open(pg_name, O_RDONLY, 0);
+
+ /* search in /bin path */
+ if (fd < 0)
+ {
+ rt_snprintf(pg_name, length - 1, "/bin/%.*s.mo", cmd_length, cmd_line);
+ fd = open(pg_name, O_RDONLY, 0);
+ }
+ }
+
+ if (fd >= 0)
+ {
+ /* found program */
+ close(fd);
+ dlmodule_exec(pg_name, cmd_line, size);
+ ret = 0;
+ }
+ else
+ {
+ ret = -1;
+ }
+
+ rt_free(pg_name);
+ return ret;
+}
+#endif /* defined(RT_USING_MODULE) && defined(DFS_USING_POSIX) */
+
+static int _msh_exec_cmd(char *cmd, rt_size_t length, int *retp)
+{
+ int argc;
+ rt_size_t cmd0_size = 0;
+ cmd_function_t cmd_func;
+ char *argv[FINSH_ARG_MAX];
+
+ RT_ASSERT(cmd);
+ RT_ASSERT(retp);
+
+ /* find the size of first command */
+ while ((cmd[cmd0_size] != ' ' && cmd[cmd0_size] != '\t') && cmd0_size < length)
+ cmd0_size ++;
+ if (cmd0_size == 0)
+ return -RT_ERROR;
+
+ cmd_func = msh_get_cmd(cmd, cmd0_size);
+ if (cmd_func == RT_NULL)
+ return -RT_ERROR;
+
+ /* split arguments */
+ rt_memset(argv, 0x00, sizeof(argv));
+ argc = msh_split(cmd, length, argv);
+ if (argc == 0)
+ return -RT_ERROR;
+
+ /* exec this command */
+ *retp = cmd_func(argc, argv);
+ return 0;
+}
+
+#if defined(RT_USING_LWP) && defined(DFS_USING_POSIX)
+static int _msh_exec_lwp(char *cmd, rt_size_t length)
+{
+ int argc;
+ int cmd0_size = 0;
+ char *argv[FINSH_ARG_MAX];
+ int fd = -1;
+ char *pg_name;
+
+ extern int exec(char *, int, char **);
+
+ /* find the size of first command */
+ while ((cmd[cmd0_size] != ' ' && cmd[cmd0_size] != '\t') && cmd0_size < length)
+ cmd0_size ++;
+ if (cmd0_size == 0)
+ return -1;
+
+ /* split arguments */
+ rt_memset(argv, 0x00, sizeof(argv));
+ argc = msh_split(cmd, length, argv);
+ if (argc == 0)
+ return -1;
+
+ pg_name = argv[0];
+ /* try to open program */
+ fd = open(pg_name, O_RDONLY, 0);
+
+ if (fd < 0)
+ return -1;
+
+ /* found program */
+ close(fd);
+ exec(pg_name, argc, argv);
+
+ return 0;
+}
+#endif /* defined(RT_USING_LWP) && defined(DFS_USING_POSIX) */
+
+int msh_exec(char *cmd, rt_size_t length)
+{
+ int cmd_ret;
+
+ /* strim the beginning of command */
+ while ((length > 0) && (*cmd == ' ' || *cmd == '\t'))
+ {
+ cmd++;
+ length--;
+ }
+
+ if (length == 0)
+ return 0;
+
+ /* Exec sequence:
+ * 1. built-in command
+ * 2. module(if enabled)
+ */
+ if (_msh_exec_cmd(cmd, length, &cmd_ret) == 0)
+ {
+ return cmd_ret;
+ }
+#ifdef DFS_USING_POSIX
+#ifdef DFS_USING_WORKDIR
+ if (msh_exec_script(cmd, length) == 0)
+ {
+ return 0;
+ }
+#endif
+
+#ifdef RT_USING_MODULE
+ if (msh_exec_module(cmd, length) == 0)
+ {
+ return 0;
+ }
+#endif /* RT_USING_MODULE */
+
+#ifdef RT_USING_LWP
+ if (_msh_exec_lwp(cmd, length) == 0)
+ {
+ return 0;
+ }
+#endif /* RT_USING_LWP */
+#endif /* DFS_USING_POSIX */
+
+ /* truncate the cmd at the first space. */
+ {
+ char *tcmd;
+ tcmd = cmd;
+ while (*tcmd != ' ' && *tcmd != '\0')
+ {
+ tcmd++;
+ }
+ *tcmd = '\0';
+ }
+ rt_kprintf("%s: command not found.\n", cmd);
+ return -1;
+}
+
+static int str_common(const char *str1, const char *str2)
+{
+ const char *str = str1;
+
+ while ((*str != 0) && (*str2 != 0) && (*str == *str2))
+ {
+ str ++;
+ str2 ++;
+ }
+
+ return (str - str1);
+}
+
+#ifdef DFS_USING_POSIX
+void msh_auto_complete_path(char *path)
+{
+ DIR *dir = RT_NULL;
+ struct dirent *dirent = RT_NULL;
+ char *full_path, *ptr, *index;
+
+ if (!path)
+ return;
+
+ full_path = (char *)rt_malloc(256);
+ if (full_path == RT_NULL) return; /* out of memory */
+
+ if (*path != '/')
+ {
+ getcwd(full_path, 256);
+ if (full_path[rt_strlen(full_path) - 1] != '/')
+ strcat(full_path, "/");
+ }
+ else *full_path = '\0';
+
+ index = RT_NULL;
+ ptr = path;
+ for (;;)
+ {
+ if (*ptr == '/') index = ptr + 1;
+ if (!*ptr) break;
+
+ ptr ++;
+ }
+ if (index == RT_NULL) index = path;
+
+ if (index != RT_NULL)
+ {
+ char *dest = index;
+
+ /* fill the parent path */
+ ptr = full_path;
+ while (*ptr) ptr ++;
+
+ for (index = path; index != dest;)
+ *ptr++ = *index++;
+ *ptr = '\0';
+
+ dir = opendir(full_path);
+ if (dir == RT_NULL) /* open directory failed! */
+ {
+ rt_free(full_path);
+ return;
+ }
+
+ /* restore the index position */
+ index = dest;
+ }
+
+ /* auto complete the file or directory name */
+ if (*index == '\0') /* display all of files and directories */
+ {
+ for (;;)
+ {
+ dirent = readdir(dir);
+ if (dirent == RT_NULL) break;
+
+ rt_kprintf("%s\n", dirent->d_name);
+ }
+ }
+ else
+ {
+ rt_size_t length, min_length;
+
+ min_length = 0;
+ for (;;)
+ {
+ dirent = readdir(dir);
+ if (dirent == RT_NULL) break;
+
+ /* matched the prefix string */
+ if (strncmp(index, dirent->d_name, rt_strlen(index)) == 0)
+ {
+ if (min_length == 0)
+ {
+ min_length = rt_strlen(dirent->d_name);
+ /* save dirent name */
+ strcpy(full_path, dirent->d_name);
+ }
+
+ length = str_common(dirent->d_name, full_path);
+
+ if (length < min_length)
+ {
+ min_length = length;
+ }
+ }
+ }
+
+ if (min_length)
+ {
+ if (min_length < rt_strlen(full_path))
+ {
+ /* list the candidate */
+ rewinddir(dir);
+
+ for (;;)
+ {
+ dirent = readdir(dir);
+ if (dirent == RT_NULL) break;
+
+ if (strncmp(index, dirent->d_name, rt_strlen(index)) == 0)
+ rt_kprintf("%s\n", dirent->d_name);
+ }
+ }
+
+ length = index - path;
+ rt_memcpy(index, full_path, min_length);
+ path[length + min_length] = '\0';
+ }
+ }
+
+ closedir(dir);
+ rt_free(full_path);
+}
+#endif /* DFS_USING_POSIX */
+
+void msh_auto_complete(char *prefix)
+{
+ int length, min_length;
+ const char *name_ptr, *cmd_name;
+ struct finsh_syscall *index;
+
+ min_length = 0;
+ name_ptr = RT_NULL;
+
+ if (*prefix == '\0')
+ {
+ msh_help(0, RT_NULL);
+ return;
+ }
+
+#ifdef DFS_USING_POSIX
+ /* check whether a spare in the command */
+ {
+ char *ptr;
+
+ ptr = prefix + rt_strlen(prefix);
+ while (ptr != prefix)
+ {
+ if (*ptr == ' ')
+ {
+ msh_auto_complete_path(ptr + 1);
+ break;
+ }
+
+ ptr --;
+ }
+#ifdef RT_USING_MODULE
+ /* There is a chance that the user want to run the module directly. So
+ * try to complete the file names. If the completed path is not a
+ * module, the system won't crash anyway. */
+ if (ptr == prefix)
+ {
+ msh_auto_complete_path(ptr);
+ }
+#endif /* RT_USING_MODULE */
+ }
+#endif /* DFS_USING_POSIX */
+
+ /* checks in internal command */
+ {
+ for (index = _syscall_table_begin; index < _syscall_table_end; FINSH_NEXT_SYSCALL(index))
+ {
+ /* skip finsh shell function */
+ cmd_name = (const char *) index->name;
+ if (strncmp(prefix, cmd_name, strlen(prefix)) == 0)
+ {
+ if (min_length == 0)
+ {
+ /* set name_ptr */
+ name_ptr = cmd_name;
+ /* set initial length */
+ min_length = strlen(name_ptr);
+ }
+
+ length = str_common(name_ptr, cmd_name);
+ if (length < min_length)
+ min_length = length;
+
+ rt_kprintf("%s\n", cmd_name);
+ }
+ }
+ }
+
+ /* auto complete string */
+ if (name_ptr != NULL)
+ {
+ rt_strncpy(prefix, name_ptr, min_length);
+ }
+
+ return ;
+}
+#endif /* RT_USING_FINSH */
diff --git a/User/system/rt-thread/components/finsh/msh.h b/User/system/rt-thread/components/finsh/msh.h
new file mode 100644
index 0000000..b9b0375
--- /dev/null
+++ b/User/system/rt-thread/components/finsh/msh.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2013-03-30 Bernard the first verion for FinSH
+ */
+
+#ifndef __M_SHELL__
+#define __M_SHELL__
+
+#include
+
+int msh_exec(char *cmd, rt_size_t length);
+void msh_auto_complete(char *prefix);
+
+int msh_exec_module(const char *cmd_line, int size);
+int msh_exec_script(const char *cmd_line, int size);
+
+#endif
diff --git a/User/system/rt-thread/components/finsh/msh_file.c b/User/system/rt-thread/components/finsh/msh_file.c
new file mode 100644
index 0000000..9deab4f
--- /dev/null
+++ b/User/system/rt-thread/components/finsh/msh_file.c
@@ -0,0 +1,711 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2015-09-25 Bernard the first verion for FinSH
+ * 2021-06-09 Meco Man implement tail command
+ */
+
+#include
+
+#if defined(RT_USING_FINSH) && defined(DFS_USING_POSIX)
+
+#include
+#include "msh.h"
+#include
+#include
+#include
+
+static int msh_readline(int fd, char *line_buf, int size)
+{
+ char ch;
+ int index = 0;
+
+ do
+ {
+ if (read(fd, &ch, 1) != 1)
+ {
+ /* nothing in this file */
+ return 0;
+ }
+ }
+ while (ch == '\n' || ch == '\r');
+
+ /* set the first character */
+ line_buf[index ++] = ch;
+
+ while (index < size)
+ {
+ if (read(fd, &ch, 1) == 1)
+ {
+ if (ch == '\n' || ch == '\r')
+ {
+ line_buf[index] = '\0';
+ break;
+ }
+
+ line_buf[index++] = ch;
+ }
+ else
+ {
+ line_buf[index] = '\0';
+ break;
+ }
+ }
+
+ return index;
+}
+
+int msh_exec_script(const char *cmd_line, int size)
+{
+ int ret;
+ int fd = -1;
+ char *pg_name;
+ int length, cmd_length = 0;
+
+ if (size == 0) return -RT_ERROR;
+
+ /* get the length of command0 */
+ while ((cmd_line[cmd_length] != ' ' && cmd_line[cmd_length] != '\t') && cmd_length < size)
+ cmd_length ++;
+
+ /* get name length */
+ length = cmd_length + 32;
+
+ /* allocate program name memory */
+ pg_name = (char *) rt_malloc(length);
+ if (pg_name == RT_NULL) return -RT_ENOMEM;
+
+ /* copy command0 */
+ rt_memcpy(pg_name, cmd_line, cmd_length);
+ pg_name[cmd_length] = '\0';
+
+ if (strstr(pg_name, ".sh") != RT_NULL || strstr(pg_name, ".SH") != RT_NULL)
+ {
+ /* try to open program */
+ fd = open(pg_name, O_RDONLY, 0);
+
+ /* search in /bin path */
+ if (fd < 0)
+ {
+ rt_snprintf(pg_name, length - 1, "/bin/%.*s", cmd_length, cmd_line);
+ fd = open(pg_name, O_RDONLY, 0);
+ }
+ }
+
+ rt_free(pg_name);
+ if (fd >= 0)
+ {
+ /* found script */
+ char *line_buf;
+ int length;
+
+ line_buf = (char *) rt_malloc(RT_CONSOLEBUF_SIZE);
+ if (line_buf == RT_NULL)
+ {
+ close(fd);
+ return -RT_ENOMEM;
+ }
+
+ /* read line by line and then exec it */
+ do
+ {
+ length = msh_readline(fd, line_buf, RT_CONSOLEBUF_SIZE);
+ if (length > 0)
+ {
+ char ch = '\0';
+ int index;
+
+ for (index = 0; index < length; index ++)
+ {
+ ch = line_buf[index];
+ if (ch == ' ' || ch == '\t') continue;
+ else break;
+ }
+
+ if (ch != '#') /* not a comment */
+ msh_exec(line_buf, length);
+ }
+ }
+ while (length > 0);
+
+ close(fd);
+ rt_free(line_buf);
+
+ ret = 0;
+ }
+ else
+ {
+ ret = -1;
+ }
+
+ return ret;
+}
+
+#ifdef DFS_USING_WORKDIR
+ extern char working_directory[];
+#endif
+
+static int cmd_ls(int argc, char **argv)
+{
+ extern void ls(const char *pathname);
+
+ if (argc == 1)
+ {
+#ifdef DFS_USING_WORKDIR
+ ls(working_directory);
+#else
+ ls("/");
+#endif
+ }
+ else
+ {
+ ls(argv[1]);
+ }
+
+ return 0;
+}
+MSH_CMD_EXPORT_ALIAS(cmd_ls, ls, List information about the FILEs.);
+
+static int cmd_cp(int argc, char **argv)
+{
+ void copy(const char *src, const char *dst);
+
+ if (argc != 3)
+ {
+ rt_kprintf("Usage: cp SOURCE DEST\n");
+ rt_kprintf("Copy SOURCE to DEST.\n");
+ }
+ else
+ {
+ copy(argv[1], argv[2]);
+ }
+
+ return 0;
+}
+MSH_CMD_EXPORT_ALIAS(cmd_cp, cp, Copy SOURCE to DEST.);
+
+static int cmd_mv(int argc, char **argv)
+{
+ if (argc != 3)
+ {
+ rt_kprintf("Usage: mv SOURCE DEST\n");
+ rt_kprintf("Rename SOURCE to DEST, or move SOURCE(s) to DIRECTORY.\n");
+ }
+ else
+ {
+ int fd;
+ char *dest = RT_NULL;
+
+ rt_kprintf("%s => %s\n", argv[1], argv[2]);
+
+ fd = open(argv[2], O_DIRECTORY, 0);
+ if (fd >= 0)
+ {
+ char *src;
+
+ close(fd);
+
+ /* it's a directory */
+ dest = (char *)rt_malloc(DFS_PATH_MAX);
+ if (dest == RT_NULL)
+ {
+ rt_kprintf("out of memory\n");
+ return -RT_ENOMEM;
+ }
+
+ src = argv[1] + rt_strlen(argv[1]);
+ while (src != argv[1])
+ {
+ if (*src == '/') break;
+ src --;
+ }
+
+ rt_snprintf(dest, DFS_PATH_MAX - 1, "%s/%s", argv[2], src);
+ }
+ else
+ {
+ fd = open(argv[2], O_RDONLY, 0);
+ if (fd >= 0)
+ {
+ close(fd);
+
+ unlink(argv[2]);
+ }
+
+ dest = argv[2];
+ }
+
+ rename(argv[1], dest);
+ if (dest != RT_NULL && dest != argv[2]) rt_free(dest);
+ }
+
+ return 0;
+}
+MSH_CMD_EXPORT_ALIAS(cmd_mv, mv, Rename SOURCE to DEST.);
+
+static int cmd_cat(int argc, char **argv)
+{
+ int index;
+ extern void cat(const char *filename);
+
+ if (argc == 1)
+ {
+ rt_kprintf("Usage: cat [FILE]...\n");
+ rt_kprintf("Concatenate FILE(s)\n");
+ return 0;
+ }
+
+ for (index = 1; index < argc; index ++)
+ {
+ cat(argv[index]);
+ }
+
+ return 0;
+}
+MSH_CMD_EXPORT_ALIAS(cmd_cat, cat, Concatenate FILE(s));
+
+static void directory_delete_for_msh(const char *pathname, char f, char v)
+{
+ DIR *dir = NULL;
+ struct dirent *dirent = NULL;
+ char *full_path;
+
+ if (pathname == RT_NULL)
+ return;
+
+ full_path = (char *)rt_malloc(DFS_PATH_MAX);
+ if (full_path == RT_NULL)
+ return;
+
+ dir = opendir(pathname);
+ if (dir == RT_NULL)
+ {
+ if (f == 0)
+ {
+ rt_kprintf("cannot remove '%s'\n", pathname);
+ }
+ rt_free(full_path);
+ return;
+ }
+
+ while (1)
+ {
+ dirent = readdir(dir);
+ if (dirent == RT_NULL)
+ break;
+ if (rt_strcmp(".", dirent->d_name) != 0 &&
+ rt_strcmp("..", dirent->d_name) != 0)
+ {
+ rt_sprintf(full_path, "%s/%s", pathname, dirent->d_name);
+ if (dirent->d_type == DT_REG)
+ {
+ if (unlink(full_path) != 0)
+ {
+ if (f == 0)
+ rt_kprintf("cannot remove '%s'\n", full_path);
+ }
+ else if (v)
+ {
+ rt_kprintf("removed '%s'\n", full_path);
+ }
+ }
+ else if (dirent->d_type == DT_DIR)
+ {
+ directory_delete_for_msh(full_path, f, v);
+ }
+ }
+ }
+ closedir(dir);
+ rt_free(full_path);
+ if (unlink(pathname) != 0)
+ {
+ if (f == 0)
+ rt_kprintf("cannot remove '%s'\n", pathname);
+ }
+ else if (v)
+ {
+ rt_kprintf("removed directory '%s'\n", pathname);
+ }
+}
+
+static int cmd_rm(int argc, char **argv)
+{
+ int index, n;
+ char f = 0, r = 0, v = 0;
+
+ if (argc == 1)
+ {
+ rt_kprintf("Usage: rm option(s) FILE...\n");
+ rt_kprintf("Remove (unlink) the FILE(s).\n");
+ return 0;
+ }
+
+ if (argv[1][0] == '-')
+ {
+ for (n = 0; argv[1][n]; n++)
+ {
+ switch (argv[1][n])
+ {
+ case 'f':
+ f = 1;
+ break;
+ case 'r':
+ r = 1;
+ break;
+ case 'v':
+ v = 1;
+ break;
+ case '-':
+ break;
+ default:
+ rt_kprintf("Error: Bad option: %c\n", argv[1][n]);
+ return 0;
+ }
+ }
+ argc -= 1;
+ argv = argv + 1;
+ }
+
+ for (index = 1; index < argc; index ++)
+ {
+ struct stat s;
+ if (stat(argv[index], &s) == 0)
+ {
+ if (s.st_mode & S_IFDIR)
+ {
+ if (r == 0)
+ rt_kprintf("cannot remove '%s': Is a directory\n", argv[index]);
+ else
+ directory_delete_for_msh(argv[index], f, v);
+ }
+ else if (s.st_mode & S_IFREG)
+ {
+ if (unlink(argv[index]) != 0)
+ {
+ if (f == 0)
+ rt_kprintf("cannot remove '%s'\n", argv[index]);
+ }
+ else if (v)
+ {
+ rt_kprintf("removed '%s'\n", argv[index]);
+ }
+ }
+ }
+ else if (f == 0)
+ {
+ rt_kprintf("cannot remove '%s': No such file or directory\n", argv[index]);
+ }
+ }
+ return 0;
+}
+MSH_CMD_EXPORT_ALIAS(cmd_rm, rm, Remove(unlink) the FILE(s).);
+
+#ifdef DFS_USING_WORKDIR
+static int cmd_cd(int argc, char **argv)
+{
+ if (argc == 1)
+ {
+ rt_kprintf("%s\n", working_directory);
+ }
+ else if (argc == 2)
+ {
+ if (chdir(argv[1]) != 0)
+ {
+ rt_kprintf("No such directory: %s\n", argv[1]);
+ }
+ }
+
+ return 0;
+}
+MSH_CMD_EXPORT_ALIAS(cmd_cd, cd, Change the shell working directory.);
+
+static int cmd_pwd(int argc, char **argv)
+{
+ rt_kprintf("%s\n", working_directory);
+ return 0;
+}
+MSH_CMD_EXPORT_ALIAS(cmd_pwd, pwd, Print the name of the current working directory.);
+#endif
+
+static int cmd_mkdir(int argc, char **argv)
+{
+ if (argc == 1)
+ {
+ rt_kprintf("Usage: mkdir [OPTION] DIRECTORY\n");
+ rt_kprintf("Create the DIRECTORY, if they do not already exist.\n");
+ }
+ else
+ {
+ mkdir(argv[1], 0);
+ }
+
+ return 0;
+}
+MSH_CMD_EXPORT_ALIAS(cmd_mkdir, mkdir, Create the DIRECTORY.);
+
+static int cmd_mkfs(int argc, char **argv)
+{
+ int result = 0;
+ char *type = "elm"; /* use the default file system type as 'fatfs' */
+
+ if (argc == 2)
+ {
+ result = dfs_mkfs(type, argv[1]);
+ }
+ else if (argc == 4)
+ {
+ if (strcmp(argv[1], "-t") == 0)
+ {
+ type = argv[2];
+ result = dfs_mkfs(type, argv[3]);
+ }
+ }
+ else
+ {
+ rt_kprintf("Usage: mkfs [-t type] device\n");
+ return 0;
+ }
+
+ if (result != RT_EOK)
+ {
+ rt_kprintf("mkfs failed, result=%d\n", result);
+ }
+
+ return 0;
+}
+MSH_CMD_EXPORT_ALIAS(cmd_mkfs, mkfs, format disk with file system);
+
+extern struct dfs_filesystem filesystem_table[];
+static int cmd_mount(int argc, char **argv)
+{
+ if (argc == 1)
+ {
+ struct dfs_filesystem *iter;
+
+ /* display the mount history */
+ rt_kprintf("filesystem device mountpoint\n");
+ rt_kprintf("---------- ------ ----------\n");
+ for (iter = &filesystem_table[0];
+ iter < &filesystem_table[DFS_FILESYSTEMS_MAX]; iter++)
+ {
+ if ((iter != NULL) && (iter->path != NULL))
+ {
+ rt_kprintf("%-10s %-6s %-s\n",
+ iter->ops->name, iter->dev_id->parent.name, iter->path);
+ }
+ }
+ return 0;
+ }
+ else if (argc == 4)
+ {
+ char *device = argv[1];
+ char *path = argv[2];
+ char *fstype = argv[3];
+
+ /* mount a filesystem to the specified directory */
+ rt_kprintf("mount device %s(%s) onto %s ... ", device, fstype, path);
+ if (dfs_mount(device, path, fstype, 0, 0) == 0)
+ {
+ rt_kprintf("succeed!\n");
+ return 0;
+ }
+ else
+ {
+ rt_kprintf("failed!\n");
+ return -1;
+ }
+ }
+ else
+ {
+ rt_kprintf("Usage: mount .\n");
+ return -1;
+ }
+}
+MSH_CMD_EXPORT_ALIAS(cmd_mount, mount, mount );
+
+/* unmount the filesystem from the specified mountpoint */
+static int cmd_umount(int argc, char **argv)
+{
+ char *path = argv[1];
+
+ if (argc != 2)
+ {
+ rt_kprintf("Usage: unmount .\n");
+ return -1;
+ }
+
+ rt_kprintf("unmount %s ... ", path);
+ if (dfs_unmount(path) < 0)
+ {
+ rt_kprintf("failed!\n");
+ return -1;
+ }
+ else
+ {
+ rt_kprintf("succeed!\n");
+ return 0;
+ }
+}
+MSH_CMD_EXPORT_ALIAS(cmd_umount, umount, Unmount device from file system);
+
+extern int df(const char *path);
+static int cmd_df(int argc, char **argv)
+{
+ if (argc != 2)
+ {
+ df("/");
+ }
+ else
+ {
+ if ((strcmp(argv[1], "--help") == 0) || (strcmp(argv[1], "-h") == 0))
+ {
+ rt_kprintf("df [path]\n");
+ }
+ else
+ {
+ df(argv[1]);
+ }
+ }
+
+ return 0;
+}
+MSH_CMD_EXPORT_ALIAS(cmd_df, df, disk free);
+
+static int cmd_echo(int argc, char **argv)
+{
+ if (argc == 2)
+ {
+ rt_kprintf("%s\n", argv[1]);
+ }
+ else if (argc == 3)
+ {
+ int fd;
+
+ fd = open(argv[2], O_RDWR | O_APPEND | O_CREAT, 0);
+ if (fd >= 0)
+ {
+ write(fd, argv[1], strlen(argv[1]));
+ close(fd);
+ }
+ else
+ {
+ rt_kprintf("open file:%s failed!\n", argv[2]);
+ }
+ }
+ else
+ {
+ rt_kprintf("Usage: echo \"string\" [filename]\n");
+ }
+
+ return 0;
+}
+MSH_CMD_EXPORT_ALIAS(cmd_echo, echo, echo string to file);
+
+static int cmd_tail(int argc, char **argv)
+{
+ int fd;
+ char c = RT_NULL;
+ char *file_name = RT_NULL;
+ rt_uint32_t total_lines = 0;
+ rt_uint32_t target_line = 0;
+ rt_uint32_t current_line = 0;
+ rt_uint32_t required_lines = 0;
+ rt_uint32_t start_line = 0;
+
+ if (argc < 2)
+ {
+ rt_kprintf("Usage: tail [-n numbers] \n");
+ return -1;
+ }
+ else if (argc == 2)
+ {
+ required_lines = 10; /* default: 10 lines from tail */
+ file_name = argv[1];
+ }
+ else if (rt_strcmp(argv[1], "-n") == 0)
+ {
+ if (argv[2][0] != '+')
+ {
+ required_lines = atoi(argv[2]);
+ }
+ else
+ {
+ start_line = atoi(&argv[2][1]); /* eg: +100, to get the 100 */
+ }
+ file_name = argv[3];
+ }
+ else
+ {
+ rt_kprintf("Usage: tail [-n numbers] \n");
+ return -1;
+ }
+
+ fd = open(file_name, O_RDONLY);
+ if (fd < 0)
+ {
+ rt_kprintf("File doesn't exist\n");
+ return -1;
+ }
+
+ while ((read(fd, &c, sizeof(char))) > 0)
+ {
+ if(total_lines == 0)
+ {
+ total_lines++;
+ }
+ if (c == '\n')
+ {
+ total_lines++;
+ }
+ }
+
+ rt_kprintf("\nTotal Number of lines:%d\n", total_lines);
+
+ if (start_line != 0)
+ {
+ if (total_lines >= start_line)
+ {
+ required_lines = total_lines - start_line + 1;
+ }
+ else
+ {
+ rt_kprintf("\nError:Required lines are more than total number of lines\n");
+ close(fd);
+ return -1;
+ }
+ }
+
+ if (required_lines > total_lines)
+ {
+ rt_kprintf("\nError:Required lines are more than total number of lines\n");
+ close(fd);
+ return -1;
+ }
+ rt_kprintf("Required Number of lines:%d\n", required_lines);
+
+ target_line = total_lines - required_lines;
+ lseek(fd, 0, SEEK_SET); /* back to head */
+
+ while ((read(fd, &c, sizeof(char))) > 0)
+ {
+ if (current_line >= target_line)
+ {
+ rt_kprintf("%c", c);
+ }
+ if (c == '\n')
+ {
+ current_line++;
+ }
+ }
+ rt_kprintf("\n");
+
+ close(fd);
+ return 0;
+}
+MSH_CMD_EXPORT_ALIAS(cmd_tail, tail, print the last N - lines data of the given file);
+
+#endif /* defined(RT_USING_FINSH) && defined(DFS_USING_POSIX) */
diff --git a/User/system/rt-thread/components/finsh/msh_parse.c b/User/system/rt-thread/components/finsh/msh_parse.c
new file mode 100644
index 0000000..a0f5f5e
--- /dev/null
+++ b/User/system/rt-thread/components/finsh/msh_parse.c
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2022-05-25 WangQiang the first verion for msh parse
+ */
+
+#include
+#include
+
+#define forstrloop(str) for (; '\0' != *(str); (str)++)
+
+/**
+ * This function will check integer.
+ *
+ * @param strvalue string
+ *
+ * @return true or false
+ */
+rt_bool_t msh_isint(char *strvalue)
+{
+ if ((RT_NULL == strvalue) || ('\0' == strvalue[0]))
+ {
+ return RT_FALSE;
+ }
+ if (('+' == *strvalue) || ('-' == *strvalue))
+ {
+ strvalue++;
+ }
+ forstrloop(strvalue)
+ {
+ if (!isdigit((int)(*strvalue)))
+ {
+ return RT_FALSE;
+ }
+ }
+ return RT_TRUE;
+}
+
+/**
+ * This function will check hex.
+ *
+ * @param strvalue string
+ *
+ * @return true or false
+ */
+rt_bool_t msh_ishex(char *strvalue)
+{
+ int c;
+ if ((RT_NULL == strvalue) || ('\0' == strvalue[0]))
+ {
+ return RT_FALSE;
+ }
+ if ('0' != *(strvalue++))
+ {
+ return RT_FALSE;
+ }
+ if ('x' != *(strvalue++))
+ {
+ return RT_FALSE;
+ }
+
+ forstrloop(strvalue)
+ {
+ c = tolower(*strvalue);
+ if (!isxdigit(c))
+ {
+ return RT_FALSE;
+ }
+ }
+ return RT_TRUE;
+}
+
+/**
+ * This function will transform for string to hex.
+ *
+ * @param strvalue string
+ *
+ * @return true or false
+ */
+int msh_strtohex(char *strvalue)
+{
+ char c = 0;
+ int value = 0;
+ strvalue += 2;
+ forstrloop(strvalue)
+ {
+ value *= 16;
+ c = tolower(*strvalue);
+ value += isdigit(c) ? c - '0' : c - 'a' + 10;
+ }
+ return value;
+}
diff --git a/User/system/rt-thread/components/finsh/msh_parse.h b/User/system/rt-thread/components/finsh/msh_parse.h
new file mode 100644
index 0000000..ba14625
--- /dev/null
+++ b/User/system/rt-thread/components/finsh/msh_parse.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2022-05-25 WangQiang the first verion for msh parse
+ */
+
+#ifndef MSH_PARSE_H
+#define MSH_PARSE_H
+
+#include
+
+rt_bool_t msh_isint(char *strvalue);
+rt_bool_t msh_ishex(char *strvalue);
+int msh_strtohex(char *strvalue);
+
+#endif /* MSH_PARSE_H */
diff --git a/User/system/rt-thread/components/finsh/shell.c b/User/system/rt-thread/components/finsh/shell.c
new file mode 100644
index 0000000..fecb4f4
--- /dev/null
+++ b/User/system/rt-thread/components/finsh/shell.c
@@ -0,0 +1,803 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2006-04-30 Bernard the first version for FinSH
+ * 2006-05-08 Bernard change finsh thread stack to 2048
+ * 2006-06-03 Bernard add support for skyeye
+ * 2006-09-24 Bernard remove the code related with hardware
+ * 2010-01-18 Bernard fix down then up key bug.
+ * 2010-03-19 Bernard fix backspace issue and fix device read in shell.
+ * 2010-04-01 Bernard add prompt output when start and remove the empty history
+ * 2011-02-23 Bernard fix variable section end issue of finsh shell
+ * initialization when use GNU GCC compiler.
+ * 2016-11-26 armink add password authentication
+ * 2018-07-02 aozima add custom prompt support.
+ */
+
+#include
+#include
+#include
+
+#ifdef RT_USING_FINSH
+
+#include "shell.h"
+#include "msh.h"
+
+#ifdef DFS_USING_POSIX
+#include
+#include
+#endif /* DFS_USING_POSIX */
+
+/* finsh thread */
+#ifndef RT_USING_HEAP
+ static struct rt_thread finsh_thread;
+ ALIGN(RT_ALIGN_SIZE)
+ static char finsh_thread_stack[FINSH_THREAD_STACK_SIZE];
+ struct finsh_shell _shell;
+#endif
+
+/* finsh symtab */
+#ifdef FINSH_USING_SYMTAB
+ struct finsh_syscall *_syscall_table_begin = NULL;
+ struct finsh_syscall *_syscall_table_end = NULL;
+#endif
+
+struct finsh_shell *shell;
+static char *finsh_prompt_custom = RT_NULL;
+
+#if defined(_MSC_VER) || (defined(__GNUC__) && defined(__x86_64__))
+struct finsh_syscall *finsh_syscall_next(struct finsh_syscall *call)
+{
+ unsigned int *ptr;
+ ptr = (unsigned int *)(call + 1);
+ while ((*ptr == 0) && ((unsigned int *)ptr < (unsigned int *) _syscall_table_end))
+ ptr ++;
+
+ return (struct finsh_syscall *)ptr;
+}
+
+#endif /* defined(_MSC_VER) || (defined(__GNUC__) && defined(__x86_64__)) */
+
+#ifdef RT_USING_HEAP
+int finsh_set_prompt(const char *prompt)
+{
+ if (finsh_prompt_custom)
+ {
+ rt_free(finsh_prompt_custom);
+ finsh_prompt_custom = RT_NULL;
+ }
+
+ /* strdup */
+ if (prompt)
+ {
+ finsh_prompt_custom = (char *)rt_malloc(strlen(prompt) + 1);
+ if (finsh_prompt_custom)
+ {
+ strcpy(finsh_prompt_custom, prompt);
+ }
+ }
+
+ return 0;
+}
+#endif /* RT_USING_HEAP */
+
+#define _MSH_PROMPT "msh "
+
+const char *finsh_get_prompt(void)
+{
+ static char finsh_prompt[RT_CONSOLEBUF_SIZE + 1] = {0};
+
+ /* check prompt mode */
+ if (!shell->prompt_mode)
+ {
+ finsh_prompt[0] = '\0';
+ return finsh_prompt;
+ }
+
+ if (finsh_prompt_custom)
+ {
+ strncpy(finsh_prompt, finsh_prompt_custom, sizeof(finsh_prompt) - 1);
+ }
+ else
+ {
+ strcpy(finsh_prompt, _MSH_PROMPT);
+ }
+
+#if defined(DFS_USING_POSIX) && defined(DFS_USING_WORKDIR)
+ /* get current working directory */
+ getcwd(&finsh_prompt[rt_strlen(finsh_prompt)], RT_CONSOLEBUF_SIZE - rt_strlen(finsh_prompt));
+#endif
+
+ strcat(finsh_prompt, ">");
+
+ return finsh_prompt;
+}
+
+/**
+ * @ingroup finsh
+ *
+ * This function get the prompt mode of finsh shell.
+ *
+ * @return prompt the prompt mode, 0 disable prompt mode, other values enable prompt mode.
+ */
+rt_uint32_t finsh_get_prompt_mode(void)
+{
+ RT_ASSERT(shell != RT_NULL);
+ return shell->prompt_mode;
+}
+
+/**
+ * @ingroup finsh
+ *
+ * This function set the prompt mode of finsh shell.
+ *
+ * The parameter 0 disable prompt mode, other values enable prompt mode.
+ *
+ * @param prompt the prompt mode
+ */
+void finsh_set_prompt_mode(rt_uint32_t prompt_mode)
+{
+ RT_ASSERT(shell != RT_NULL);
+ shell->prompt_mode = prompt_mode;
+}
+
+int finsh_getchar(void)
+{
+#ifdef RT_USING_DEVICE
+ char ch = 0;
+#ifdef RT_USING_POSIX_STDIO
+ if(read(STDIN_FILENO, &ch, 1) > 0)
+ {
+ return ch;
+ }
+ else
+ {
+ return -1; /* EOF */
+ }
+#else
+ rt_device_t device;
+
+ RT_ASSERT(shell != RT_NULL);
+
+ device = shell->device;
+ if (device == RT_NULL)
+ {
+ return -1; /* EOF */
+ }
+
+ while (rt_device_read(device, -1, &ch, 1) != 1)
+ {
+ rt_sem_take(&shell->rx_sem, RT_WAITING_FOREVER);
+ if (shell->device != device)
+ {
+ device = shell->device;
+ if (device == RT_NULL)
+ {
+ return -1;
+ }
+ }
+ }
+ return ch;
+#endif /* RT_USING_POSIX_STDIO */
+#else
+ extern char rt_hw_console_getchar(void);
+ return rt_hw_console_getchar();
+#endif /* RT_USING_DEVICE */
+}
+
+#if !defined(RT_USING_POSIX_STDIO) && defined(RT_USING_DEVICE)
+static rt_err_t finsh_rx_ind(rt_device_t dev, rt_size_t size)
+{
+ RT_ASSERT(shell != RT_NULL);
+
+ /* release semaphore to let finsh thread rx data */
+ rt_sem_release(&shell->rx_sem);
+
+ return RT_EOK;
+}
+
+/**
+ * @ingroup finsh
+ *
+ * This function sets the input device of finsh shell.
+ *
+ * @param device_name the name of new input device.
+ */
+void finsh_set_device(const char *device_name)
+{
+ rt_device_t dev = RT_NULL;
+
+ RT_ASSERT(shell != RT_NULL);
+ dev = rt_device_find(device_name);
+ if (dev == RT_NULL)
+ {
+ rt_kprintf("finsh: can not find device: %s\n", device_name);
+ return;
+ }
+
+ /* check whether it's a same device */
+ if (dev == shell->device) return;
+ /* open this device and set the new device in finsh shell */
+ if (rt_device_open(dev, RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_INT_RX | \
+ RT_DEVICE_FLAG_STREAM) == RT_EOK)
+ {
+ if (shell->device != RT_NULL)
+ {
+ /* close old finsh device */
+ rt_device_close(shell->device);
+ rt_device_set_rx_indicate(shell->device, RT_NULL);
+ }
+
+ /* clear line buffer before switch to new device */
+ rt_memset(shell->line, 0, sizeof(shell->line));
+ shell->line_curpos = shell->line_position = 0;
+
+ shell->device = dev;
+ rt_device_set_rx_indicate(dev, finsh_rx_ind);
+ }
+}
+
+/**
+ * @ingroup finsh
+ *
+ * This function returns current finsh shell input device.
+ *
+ * @return the finsh shell input device name is returned.
+ */
+const char *finsh_get_device()
+{
+ RT_ASSERT(shell != RT_NULL);
+ return shell->device->parent.name;
+}
+#endif /* !defined(RT_USING_POSIX_STDIO) && defined(RT_USING_DEVICE) */
+
+/**
+ * @ingroup finsh
+ *
+ * This function set the echo mode of finsh shell.
+ *
+ * FINSH_OPTION_ECHO=0x01 is echo mode, other values are none-echo mode.
+ *
+ * @param echo the echo mode
+ */
+void finsh_set_echo(rt_uint32_t echo)
+{
+ RT_ASSERT(shell != RT_NULL);
+ shell->echo_mode = (rt_uint8_t)echo;
+}
+
+/**
+ * @ingroup finsh
+ *
+ * This function gets the echo mode of finsh shell.
+ *
+ * @return the echo mode
+ */
+rt_uint32_t finsh_get_echo()
+{
+ RT_ASSERT(shell != RT_NULL);
+
+ return shell->echo_mode;
+}
+
+#ifdef FINSH_USING_AUTH
+/**
+ * set a new password for finsh
+ *
+ * @param password new password
+ *
+ * @return result, RT_EOK on OK, -RT_ERROR on the new password length is less than
+ * FINSH_PASSWORD_MIN or greater than FINSH_PASSWORD_MAX
+ */
+rt_err_t finsh_set_password(const char *password)
+{
+ rt_base_t level;
+ rt_size_t pw_len = rt_strlen(password);
+
+ if (pw_len < FINSH_PASSWORD_MIN || pw_len > FINSH_PASSWORD_MAX)
+ return -RT_ERROR;
+
+ level = rt_hw_interrupt_disable();
+ rt_strncpy(shell->password, password, FINSH_PASSWORD_MAX);
+ rt_hw_interrupt_enable(level);
+
+ return RT_EOK;
+}
+
+/**
+ * get the finsh password
+ *
+ * @return password
+ */
+const char *finsh_get_password(void)
+{
+ return shell->password;
+}
+
+static void finsh_wait_auth(void)
+{
+ int ch;
+ rt_bool_t input_finish = RT_FALSE;
+ char password[FINSH_PASSWORD_MAX] = { 0 };
+ rt_size_t cur_pos = 0;
+ /* password not set */
+ if (rt_strlen(finsh_get_password()) == 0) return;
+
+ while (1)
+ {
+ rt_kprintf("Password for login: ");
+ while (!input_finish)
+ {
+ while (1)
+ {
+ /* read one character from device */
+ ch = (int)finsh_getchar();
+ if (ch < 0)
+ {
+ continue;
+ }
+
+ if (ch >= ' ' && ch <= '~' && cur_pos < FINSH_PASSWORD_MAX)
+ {
+ /* change the printable characters to '*' */
+ rt_kprintf("*");
+ password[cur_pos++] = ch;
+ }
+ else if (ch == '\b' && cur_pos > 0)
+ {
+ /* backspace */
+ cur_pos--;
+ password[cur_pos] = '\0';
+ rt_kprintf("\b \b");
+ }
+ else if (ch == '\r' || ch == '\n')
+ {
+ rt_kprintf("\n");
+ input_finish = RT_TRUE;
+ break;
+ }
+ }
+ }
+ if (!rt_strncmp(shell->password, password, FINSH_PASSWORD_MAX)) return;
+ else
+ {
+ /* authentication failed, delay 2S for retry */
+ rt_thread_delay(2 * RT_TICK_PER_SECOND);
+ rt_kprintf("Sorry, try again.\n");
+ cur_pos = 0;
+ input_finish = RT_FALSE;
+ rt_memset(password, '\0', FINSH_PASSWORD_MAX);
+ }
+ }
+}
+#endif /* FINSH_USING_AUTH */
+
+static void shell_auto_complete(char *prefix)
+{
+ rt_kprintf("\n");
+ msh_auto_complete(prefix);
+
+ rt_kprintf("%s%s", FINSH_PROMPT, prefix);
+}
+
+#ifdef FINSH_USING_HISTORY
+static rt_bool_t shell_handle_history(struct finsh_shell *shell)
+{
+#if defined(_WIN32)
+ int i;
+ rt_kprintf("\r");
+
+ for (i = 0; i <= 60; i++)
+ putchar(' ');
+ rt_kprintf("\r");
+
+#else
+ rt_kprintf("\033[2K\r");
+#endif
+ rt_kprintf("%s%s", FINSH_PROMPT, shell->line);
+ return RT_FALSE;
+}
+
+static void shell_push_history(struct finsh_shell *shell)
+{
+ if (shell->line_position != 0)
+ {
+ /* push history */
+ if (shell->history_count >= FINSH_HISTORY_LINES)
+ {
+ /* if current cmd is same as last cmd, don't push */
+ if (memcmp(&shell->cmd_history[FINSH_HISTORY_LINES - 1], shell->line, FINSH_CMD_SIZE))
+ {
+ /* move history */
+ int index;
+ for (index = 0; index < FINSH_HISTORY_LINES - 1; index ++)
+ {
+ rt_memcpy(&shell->cmd_history[index][0],
+ &shell->cmd_history[index + 1][0], FINSH_CMD_SIZE);
+ }
+ rt_memset(&shell->cmd_history[index][0], 0, FINSH_CMD_SIZE);
+ rt_memcpy(&shell->cmd_history[index][0], shell->line, shell->line_position);
+
+ /* it's the maximum history */
+ shell->history_count = FINSH_HISTORY_LINES;
+ }
+ }
+ else
+ {
+ /* if current cmd is same as last cmd, don't push */
+ if (shell->history_count == 0 || memcmp(&shell->cmd_history[shell->history_count - 1], shell->line, FINSH_CMD_SIZE))
+ {
+ shell->current_history = shell->history_count;
+ rt_memset(&shell->cmd_history[shell->history_count][0], 0, FINSH_CMD_SIZE);
+ rt_memcpy(&shell->cmd_history[shell->history_count][0], shell->line, shell->line_position);
+
+ /* increase count and set current history position */
+ shell->history_count ++;
+ }
+ }
+ }
+ shell->current_history = shell->history_count;
+}
+#endif
+
+void finsh_thread_entry(void *parameter)
+{
+ int ch;
+
+ /* normal is echo mode */
+#ifndef FINSH_ECHO_DISABLE_DEFAULT
+ shell->echo_mode = 1;
+#else
+ shell->echo_mode = 0;
+#endif
+
+#if !defined(RT_USING_POSIX_STDIO) && defined(RT_USING_DEVICE)
+ /* set console device as shell device */
+ if (shell->device == RT_NULL)
+ {
+ rt_device_t console = rt_console_get_device();
+ if (console)
+ {
+ finsh_set_device(console->parent.name);
+ }
+ }
+#endif /* !defined(RT_USING_POSIX_STDIO) && defined(RT_USING_DEVICE) */
+
+#ifdef FINSH_USING_AUTH
+ /* set the default password when the password isn't setting */
+ if (rt_strlen(finsh_get_password()) == 0)
+ {
+ if (finsh_set_password(FINSH_DEFAULT_PASSWORD) != RT_EOK)
+ {
+ rt_kprintf("Finsh password set failed.\n");
+ }
+ }
+ /* waiting authenticate success */
+ finsh_wait_auth();
+#endif
+
+ rt_kprintf(FINSH_PROMPT);
+
+ while (1)
+ {
+ ch = (int)finsh_getchar();
+ if (ch < 0)
+ {
+ continue;
+ }
+
+ /*
+ * handle control key
+ * up key : 0x1b 0x5b 0x41
+ * down key: 0x1b 0x5b 0x42
+ * right key:0x1b 0x5b 0x43
+ * left key: 0x1b 0x5b 0x44
+ */
+ if (ch == 0x1b)
+ {
+ shell->stat = WAIT_SPEC_KEY;
+ continue;
+ }
+ else if (shell->stat == WAIT_SPEC_KEY)
+ {
+ if (ch == 0x5b)
+ {
+ shell->stat = WAIT_FUNC_KEY;
+ continue;
+ }
+
+ shell->stat = WAIT_NORMAL;
+ }
+ else if (shell->stat == WAIT_FUNC_KEY)
+ {
+ shell->stat = WAIT_NORMAL;
+
+ if (ch == 0x41) /* up key */
+ {
+#ifdef FINSH_USING_HISTORY
+ /* prev history */
+ if (shell->current_history > 0)
+ shell->current_history --;
+ else
+ {
+ shell->current_history = 0;
+ continue;
+ }
+
+ /* copy the history command */
+ rt_memcpy(shell->line, &shell->cmd_history[shell->current_history][0],
+ FINSH_CMD_SIZE);
+ shell->line_curpos = shell->line_position = (rt_uint16_t)strlen(shell->line);
+ shell_handle_history(shell);
+#endif
+ continue;
+ }
+ else if (ch == 0x42) /* down key */
+ {
+#ifdef FINSH_USING_HISTORY
+ /* next history */
+ if (shell->current_history < shell->history_count - 1)
+ shell->current_history ++;
+ else
+ {
+ /* set to the end of history */
+ if (shell->history_count != 0)
+ shell->current_history = shell->history_count - 1;
+ else
+ continue;
+ }
+
+ rt_memcpy(shell->line, &shell->cmd_history[shell->current_history][0],
+ FINSH_CMD_SIZE);
+ shell->line_curpos = shell->line_position = (rt_uint16_t)strlen(shell->line);
+ shell_handle_history(shell);
+#endif
+ continue;
+ }
+ else if (ch == 0x44) /* left key */
+ {
+ if (shell->line_curpos)
+ {
+ rt_kprintf("\b");
+ shell->line_curpos --;
+ }
+
+ continue;
+ }
+ else if (ch == 0x43) /* right key */
+ {
+ if (shell->line_curpos < shell->line_position)
+ {
+ rt_kprintf("%c", shell->line[shell->line_curpos]);
+ shell->line_curpos ++;
+ }
+
+ continue;
+ }
+ }
+
+ /* received null or error */
+ if (ch == '\0' || ch == 0xFF) continue;
+ /* handle tab key */
+ else if (ch == '\t')
+ {
+ int i;
+ /* move the cursor to the beginning of line */
+ for (i = 0; i < shell->line_curpos; i++)
+ rt_kprintf("\b");
+
+ /* auto complete */
+ shell_auto_complete(&shell->line[0]);
+ /* re-calculate position */
+ shell->line_curpos = shell->line_position = (rt_uint16_t)strlen(shell->line);
+
+ continue;
+ }
+ /* handle backspace key */
+ else if (ch == 0x7f || ch == 0x08)
+ {
+ /* note that shell->line_curpos >= 0 */
+ if (shell->line_curpos == 0)
+ continue;
+
+ shell->line_position--;
+ shell->line_curpos--;
+
+ if (shell->line_position > shell->line_curpos)
+ {
+ int i;
+
+ rt_memmove(&shell->line[shell->line_curpos],
+ &shell->line[shell->line_curpos + 1],
+ shell->line_position - shell->line_curpos);
+ shell->line[shell->line_position] = 0;
+
+ rt_kprintf("\b%s \b", &shell->line[shell->line_curpos]);
+
+ /* move the cursor to the origin position */
+ for (i = shell->line_curpos; i <= shell->line_position; i++)
+ rt_kprintf("\b");
+ }
+ else
+ {
+ rt_kprintf("\b \b");
+ shell->line[shell->line_position] = 0;
+ }
+
+ continue;
+ }
+
+ /* handle end of line, break */
+ if (ch == '\r' || ch == '\n')
+ {
+#ifdef FINSH_USING_HISTORY
+ shell_push_history(shell);
+#endif
+ if (shell->echo_mode)
+ rt_kprintf("\n");
+ msh_exec(shell->line, shell->line_position);
+
+ rt_kprintf(FINSH_PROMPT);
+ rt_memset(shell->line, 0, sizeof(shell->line));
+ shell->line_curpos = shell->line_position = 0;
+ continue;
+ }
+
+ /* it's a large line, discard it */
+ if (shell->line_position >= FINSH_CMD_SIZE)
+ shell->line_position = 0;
+
+ /* normal character */
+ if (shell->line_curpos < shell->line_position)
+ {
+ int i;
+
+ rt_memmove(&shell->line[shell->line_curpos + 1],
+ &shell->line[shell->line_curpos],
+ shell->line_position - shell->line_curpos);
+ shell->line[shell->line_curpos] = ch;
+ if (shell->echo_mode)
+ rt_kprintf("%s", &shell->line[shell->line_curpos]);
+
+ /* move the cursor to new position */
+ for (i = shell->line_curpos; i < shell->line_position; i++)
+ rt_kprintf("\b");
+ }
+ else
+ {
+ shell->line[shell->line_position] = ch;
+ if (shell->echo_mode)
+ rt_kprintf("%c", ch);
+ }
+
+ ch = 0;
+ shell->line_position ++;
+ shell->line_curpos++;
+ if (shell->line_position >= FINSH_CMD_SIZE)
+ {
+ /* clear command line */
+ shell->line_position = 0;
+ shell->line_curpos = 0;
+ }
+ } /* end of device read */
+}
+
+void finsh_system_function_init(const void *begin, const void *end)
+{
+ _syscall_table_begin = (struct finsh_syscall *) begin;
+ _syscall_table_end = (struct finsh_syscall *) end;
+}
+
+#if defined(__ICCARM__) || defined(__ICCRX__) /* for IAR compiler */
+#ifdef FINSH_USING_SYMTAB
+ #pragma section="FSymTab"
+#endif
+#elif defined(__ADSPBLACKFIN__) /* for VisaulDSP++ Compiler*/
+#ifdef FINSH_USING_SYMTAB
+ extern "asm" int __fsymtab_start;
+ extern "asm" int __fsymtab_end;
+#endif
+#elif defined(_MSC_VER)
+#pragma section("FSymTab$a", read)
+const char __fsym_begin_name[] = "__start";
+const char __fsym_begin_desc[] = "begin of finsh";
+__declspec(allocate("FSymTab$a")) const struct finsh_syscall __fsym_begin =
+{
+ __fsym_begin_name,
+ __fsym_begin_desc,
+ NULL
+};
+
+#pragma section("FSymTab$z", read)
+const char __fsym_end_name[] = "__end";
+const char __fsym_end_desc[] = "end of finsh";
+__declspec(allocate("FSymTab$z")) const struct finsh_syscall __fsym_end =
+{
+ __fsym_end_name,
+ __fsym_end_desc,
+ NULL
+};
+#endif
+
+/*
+ * @ingroup finsh
+ *
+ * This function will initialize finsh shell
+ */
+int finsh_system_init(void)
+{
+ rt_err_t result = RT_EOK;
+ rt_thread_t tid;
+
+#ifdef FINSH_USING_SYMTAB
+#ifdef __ARMCC_VERSION /* ARM C Compiler */
+ extern const int FSymTab$$Base;
+ extern const int FSymTab$$Limit;
+ finsh_system_function_init(&FSymTab$$Base, &FSymTab$$Limit);
+#elif defined (__ICCARM__) || defined(__ICCRX__) /* for IAR Compiler */
+ finsh_system_function_init(__section_begin("FSymTab"),
+ __section_end("FSymTab"));
+#elif defined (__GNUC__) || defined(__TI_COMPILER_VERSION__) || defined(__TASKING__)
+ /* GNU GCC Compiler and TI CCS */
+ extern const int __fsymtab_start;
+ extern const int __fsymtab_end;
+ finsh_system_function_init(&__fsymtab_start, &__fsymtab_end);
+#elif defined(__ADSPBLACKFIN__) /* for VisualDSP++ Compiler */
+ finsh_system_function_init(&__fsymtab_start, &__fsymtab_end);
+#elif defined(_MSC_VER)
+ unsigned int *ptr_begin, *ptr_end;
+
+ if (shell)
+ {
+ rt_kprintf("finsh shell already init.\n");
+ return RT_EOK;
+ }
+
+ ptr_begin = (unsigned int *)&__fsym_begin;
+ ptr_begin += (sizeof(struct finsh_syscall) / sizeof(unsigned int));
+ while (*ptr_begin == 0) ptr_begin ++;
+
+ ptr_end = (unsigned int *) &__fsym_end;
+ ptr_end --;
+ while (*ptr_end == 0) ptr_end --;
+
+ finsh_system_function_init(ptr_begin, ptr_end);
+#endif
+#endif
+
+#ifdef RT_USING_HEAP
+ /* create or set shell structure */
+ shell = (struct finsh_shell *)rt_calloc(1, sizeof(struct finsh_shell));
+ if (shell == RT_NULL)
+ {
+ rt_kprintf("no memory for shell\n");
+ return -1;
+ }
+ tid = rt_thread_create(FINSH_THREAD_NAME,
+ finsh_thread_entry, RT_NULL,
+ FINSH_THREAD_STACK_SIZE, FINSH_THREAD_PRIORITY, 10);
+#else
+ shell = &_shell;
+ tid = &finsh_thread;
+ result = rt_thread_init(&finsh_thread,
+ FINSH_THREAD_NAME,
+ finsh_thread_entry, RT_NULL,
+ &finsh_thread_stack[0], sizeof(finsh_thread_stack),
+ FINSH_THREAD_PRIORITY, 10);
+#endif /* RT_USING_HEAP */
+
+ rt_sem_init(&(shell->rx_sem), "shrx", 0, 0);
+ finsh_set_prompt_mode(1);
+
+ if (tid != NULL && result == RT_EOK)
+ rt_thread_startup(tid);
+ return 0;
+}
+INIT_APP_EXPORT(finsh_system_init);
+
+#endif /* RT_USING_FINSH */
+
diff --git a/User/system/rt-thread/components/finsh/shell.h b/User/system/rt-thread/components/finsh/shell.h
new file mode 100644
index 0000000..a74f4da
--- /dev/null
+++ b/User/system/rt-thread/components/finsh/shell.h
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2011-06-02 Bernard Add finsh_get_prompt function declaration
+ */
+
+#ifndef __SHELL_H__
+#define __SHELL_H__
+
+#include
+#include "finsh.h"
+
+#ifndef FINSH_THREAD_PRIORITY
+ #define FINSH_THREAD_PRIORITY 20
+#endif
+#ifndef FINSH_THREAD_STACK_SIZE
+ #define FINSH_THREAD_STACK_SIZE 2048
+#endif
+#ifndef FINSH_CMD_SIZE
+ #define FINSH_CMD_SIZE 80
+#endif
+
+#define FINSH_OPTION_ECHO 0x01
+
+#define FINSH_PROMPT finsh_get_prompt()
+const char *finsh_get_prompt(void);
+int finsh_set_prompt(const char *prompt);
+
+#ifdef FINSH_USING_HISTORY
+ #ifndef FINSH_HISTORY_LINES
+ #define FINSH_HISTORY_LINES 5
+ #endif
+#endif
+
+#ifdef FINSH_USING_AUTH
+ #ifndef FINSH_PASSWORD_MAX
+ #define FINSH_PASSWORD_MAX RT_NAME_MAX
+ #endif
+ #ifndef FINSH_PASSWORD_MIN
+ #define FINSH_PASSWORD_MIN 6
+ #endif
+ #ifndef FINSH_DEFAULT_PASSWORD
+ #define FINSH_DEFAULT_PASSWORD "rtthread"
+ #endif
+#endif /* FINSH_USING_AUTH */
+
+#ifndef FINSH_THREAD_NAME
+ #define FINSH_THREAD_NAME "tshell"
+#endif
+
+enum input_stat
+{
+ WAIT_NORMAL,
+ WAIT_SPEC_KEY,
+ WAIT_FUNC_KEY,
+};
+struct finsh_shell
+{
+ struct rt_semaphore rx_sem;
+
+ enum input_stat stat;
+
+ rt_uint8_t echo_mode: 1;
+ rt_uint8_t prompt_mode: 1;
+
+#ifdef FINSH_USING_HISTORY
+ rt_uint16_t current_history;
+ rt_uint16_t history_count;
+
+ char cmd_history[FINSH_HISTORY_LINES][FINSH_CMD_SIZE];
+#endif
+
+ char line[FINSH_CMD_SIZE + 1];
+ rt_uint16_t line_position;
+ rt_uint16_t line_curpos;
+
+#if !defined(RT_USING_POSIX_STDIO) && defined(RT_USING_DEVICE)
+ rt_device_t device;
+#endif
+
+#ifdef FINSH_USING_AUTH
+ char password[FINSH_PASSWORD_MAX];
+#endif
+};
+
+void finsh_set_echo(rt_uint32_t echo);
+rt_uint32_t finsh_get_echo(void);
+
+int finsh_system_init(void);
+const char *finsh_get_device(void);
+int finsh_getchar(void);
+
+rt_uint32_t finsh_get_prompt_mode(void);
+void finsh_set_prompt_mode(rt_uint32_t prompt_mode);
+
+#ifdef FINSH_USING_AUTH
+ rt_err_t finsh_set_password(const char *password);
+ const char *finsh_get_password(void);
+#endif
+
+#endif
diff --git a/User/system/rt-thread/include/rtdbg.h b/User/system/rt-thread/include/rtdbg.h
new file mode 100644
index 0000000..6a6ea3d
--- /dev/null
+++ b/User/system/rt-thread/include/rtdbg.h
@@ -0,0 +1,189 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2016-11-12 Bernard The first version
+ * 2018-05-25 armink Add simple API, such as LOG_D, LOG_E
+ */
+
+/*
+ * The macro definitions for debug
+ *
+ * These macros are defined in static. If you want to use debug macro, you can
+ * use as following code:
+ *
+ * In your C/C++ file, enable/disable DEBUG_ENABLE macro, and then include this
+ * header file.
+ *
+ * #define DBG_TAG "MOD_TAG"
+ * #define DBG_LVL DBG_INFO
+ * #include // must after of DBG_LVL, DBG_TAG or other options
+ *
+ * Then in your C/C++ file, you can use LOG_X macro to print out logs:
+ * LOG_D("this is a debug log!");
+ * LOG_E("this is a error log!");
+ */
+
+#ifndef RT_DBG_H__
+#define RT_DBG_H__
+
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* the debug log will force enable when RT_DEBUG macro is defined */
+#if defined(RT_DEBUG) && !defined(DBG_ENABLE)
+#define DBG_ENABLE
+#endif
+
+/* it will force output color log when RT_DEBUG_COLOR macro is defined */
+#if defined(RT_DEBUG_COLOR) && !defined(DBG_COLOR)
+#define DBG_COLOR
+#endif
+
+#if defined(RT_USING_ULOG)
+/* using ulog compatible with rtdbg */
+#include
+#else
+
+/* DEBUG level */
+#define DBG_ERROR 0
+#define DBG_WARNING 1
+#define DBG_INFO 2
+#define DBG_LOG 3
+
+#ifdef DBG_TAG
+#ifndef DBG_SECTION_NAME
+#define DBG_SECTION_NAME DBG_TAG
+#endif
+#else
+/* compatible with old version */
+#ifndef DBG_SECTION_NAME
+#define DBG_SECTION_NAME "DBG"
+#endif
+#endif /* DBG_TAG */
+
+#ifdef DBG_ENABLE
+
+#ifdef DBG_LVL
+#ifndef DBG_LEVEL
+#define DBG_LEVEL DBG_LVL
+#endif
+#else
+/* compatible with old version */
+#ifndef DBG_LEVEL
+#define DBG_LEVEL DBG_WARNING
+#endif
+#endif /* DBG_LVL */
+
+/*
+ * The color for terminal (foreground)
+ * BLACK 30
+ * RED 31
+ * GREEN 32
+ * YELLOW 33
+ * BLUE 34
+ * PURPLE 35
+ * CYAN 36
+ * WHITE 37
+ */
+#ifdef DBG_COLOR
+#define _DBG_COLOR(n) rt_kprintf("\033["#n"m")
+#define _DBG_LOG_HDR(lvl_name, color_n) \
+ rt_kprintf("\033["#color_n"m[" lvl_name "/" DBG_SECTION_NAME "] ")
+#define _DBG_LOG_X_END \
+ rt_kprintf("\033[0m\n")
+#else
+#define _DBG_COLOR(n)
+#define _DBG_LOG_HDR(lvl_name, color_n) \
+ rt_kprintf("[" lvl_name "/" DBG_SECTION_NAME "] ")
+#define _DBG_LOG_X_END \
+ rt_kprintf("\n")
+#endif /* DBG_COLOR */
+
+/*
+ * static debug routine
+ * NOTE: This is a NOT RECOMMENDED API. Please using LOG_X API.
+ * It will be DISCARDED later. Because it will take up more resources.
+ */
+#define dbg_log(level, fmt, ...) \
+ if ((level) <= DBG_LEVEL) \
+ { \
+ switch(level) \
+ { \
+ case DBG_ERROR: _DBG_LOG_HDR("E", 31); break; \
+ case DBG_WARNING: _DBG_LOG_HDR("W", 33); break; \
+ case DBG_INFO: _DBG_LOG_HDR("I", 32); break; \
+ case DBG_LOG: _DBG_LOG_HDR("D", 0); break; \
+ default: break; \
+ } \
+ rt_kprintf(fmt, ##__VA_ARGS__); \
+ _DBG_COLOR(0); \
+ }
+
+#define dbg_here \
+ if ((DBG_LEVEL) <= DBG_LOG){ \
+ rt_kprintf(DBG_SECTION_NAME " Here %s:%d\n", \
+ __FUNCTION__, __LINE__); \
+ }
+
+#define dbg_log_line(lvl, color_n, fmt, ...) \
+ do \
+ { \
+ _DBG_LOG_HDR(lvl, color_n); \
+ rt_kprintf(fmt, ##__VA_ARGS__); \
+ _DBG_LOG_X_END; \
+ } \
+ while (0)
+
+#define dbg_raw(...) rt_kprintf(__VA_ARGS__);
+
+#else
+#define dbg_log(level, fmt, ...)
+#define dbg_here
+#define dbg_enter
+#define dbg_exit
+#define dbg_log_line(lvl, color_n, fmt, ...)
+#define dbg_raw(...)
+#endif /* DBG_ENABLE */
+
+#if (DBG_LEVEL >= DBG_LOG)
+#define LOG_D(fmt, ...) dbg_log_line("D", 0, fmt, ##__VA_ARGS__)
+#else
+#define LOG_D(...)
+#endif
+
+#if (DBG_LEVEL >= DBG_INFO)
+#define LOG_I(fmt, ...) dbg_log_line("I", 32, fmt, ##__VA_ARGS__)
+#else
+#define LOG_I(...)
+#endif
+
+#if (DBG_LEVEL >= DBG_WARNING)
+#define LOG_W(fmt, ...) dbg_log_line("W", 33, fmt, ##__VA_ARGS__)
+#else
+#define LOG_W(...)
+#endif
+
+#if (DBG_LEVEL >= DBG_ERROR)
+#define LOG_E(fmt, ...) dbg_log_line("E", 31, fmt, ##__VA_ARGS__)
+#else
+#define LOG_E(...)
+#endif
+
+#define LOG_RAW(...) dbg_raw(__VA_ARGS__)
+
+#define LOG_HEX(name, width, buf, size)
+
+#endif /* defined(RT_USING_ULOG) && define(DBG_ENABLE) */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* RT_DBG_H__ */
diff --git a/User/system/rt-thread/include/rtdebug.h b/User/system/rt-thread/include/rtdebug.h
new file mode 100644
index 0000000..ac5ba6c
--- /dev/null
+++ b/User/system/rt-thread/include/rtdebug.h
@@ -0,0 +1,157 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ */
+
+#ifndef __RTDEBUG_H__
+#define __RTDEBUG_H__
+
+#include
+
+/* Using this macro to control all kernel debug features. */
+#ifdef RT_DEBUG
+
+/* Turn on some of these (set to non-zero) to debug kernel */
+#ifndef RT_DEBUG_MEM
+#define RT_DEBUG_MEM 0
+#endif
+
+#ifndef RT_DEBUG_MEMHEAP
+#define RT_DEBUG_MEMHEAP 0
+#endif
+
+#ifndef RT_DEBUG_MODULE
+#define RT_DEBUG_MODULE 0
+#endif
+
+#ifndef RT_DEBUG_SCHEDULER
+#define RT_DEBUG_SCHEDULER 0
+#endif
+
+#ifndef RT_DEBUG_SLAB
+#define RT_DEBUG_SLAB 0
+#endif
+
+#ifndef RT_DEBUG_THREAD
+#define RT_DEBUG_THREAD 0
+#endif
+
+#ifndef RT_DEBUG_TIMER
+#define RT_DEBUG_TIMER 0
+#endif
+
+#ifndef RT_DEBUG_IRQ
+#define RT_DEBUG_IRQ 0
+#endif
+
+#ifndef RT_DEBUG_IPC
+#define RT_DEBUG_IPC 0
+#endif
+
+#ifndef RT_DEBUG_DEVICE
+#define RT_DEBUG_DEVICE 1
+#endif
+
+#ifndef RT_DEBUG_INIT
+#define RT_DEBUG_INIT 0
+#endif
+
+/* Turn on this to enable context check */
+#ifndef RT_DEBUG_CONTEXT_CHECK
+#define RT_DEBUG_CONTEXT_CHECK 1
+#endif
+
+#define RT_DEBUG_LOG(type, message) \
+do \
+{ \
+ if (type) \
+ rt_kprintf message; \
+} \
+while (0)
+
+#define RT_ASSERT(EX) \
+if (!(EX)) \
+{ \
+ rt_assert_handler(#EX, __FUNCTION__, __LINE__); \
+}
+
+/* Macro to check current context */
+#if RT_DEBUG_CONTEXT_CHECK
+#define RT_DEBUG_NOT_IN_INTERRUPT \
+do \
+{ \
+ rt_base_t level; \
+ level = rt_hw_interrupt_disable(); \
+ if (rt_interrupt_get_nest() != 0) \
+ { \
+ rt_kprintf("Function[%s] shall not be used in ISR\n", __FUNCTION__); \
+ RT_ASSERT(0) \
+ } \
+ rt_hw_interrupt_enable(level); \
+} \
+while (0)
+
+/* "In thread context" means:
+ * 1) the scheduler has been started
+ * 2) not in interrupt context.
+ */
+#define RT_DEBUG_IN_THREAD_CONTEXT \
+do \
+{ \
+ rt_base_t level; \
+ level = rt_hw_interrupt_disable(); \
+ if (rt_thread_self() == RT_NULL) \
+ { \
+ rt_kprintf("Function[%s] shall not be used before scheduler start\n", \
+ __FUNCTION__); \
+ RT_ASSERT(0) \
+ } \
+ RT_DEBUG_NOT_IN_INTERRUPT; \
+ rt_hw_interrupt_enable(level); \
+} \
+while (0)
+
+/* "scheduler available" means:
+ * 1) the scheduler has been started.
+ * 2) not in interrupt context.
+ * 3) scheduler is not locked.
+ */
+#define RT_DEBUG_SCHEDULER_AVAILABLE(need_check) \
+do \
+{ \
+ if (need_check) \
+ { \
+ rt_base_t level; \
+ level = rt_hw_interrupt_disable(); \
+ if (rt_critical_level() != 0) \
+ { \
+ rt_kprintf("Function[%s]: scheduler is not available\n", \
+ __FUNCTION__); \
+ RT_ASSERT(0) \
+ } \
+ RT_DEBUG_IN_THREAD_CONTEXT; \
+ rt_hw_interrupt_enable(level); \
+ } \
+} \
+while (0)
+#else
+#define RT_DEBUG_NOT_IN_INTERRUPT
+#define RT_DEBUG_IN_THREAD_CONTEXT
+#define RT_DEBUG_SCHEDULER_AVAILABLE(need_check)
+#endif
+
+#else /* RT_DEBUG */
+
+#define RT_ASSERT(EX)
+#define RT_DEBUG_LOG(type, message)
+#define RT_DEBUG_NOT_IN_INTERRUPT
+#define RT_DEBUG_IN_THREAD_CONTEXT
+#define RT_DEBUG_SCHEDULER_AVAILABLE(need_check)
+
+#endif /* RT_DEBUG */
+
+#endif /* __RTDEBUG_H__ */
diff --git a/User/system/rt-thread/include/rtdef.h b/User/system/rt-thread/include/rtdef.h
new file mode 100644
index 0000000..0de2c22
--- /dev/null
+++ b/User/system/rt-thread/include/rtdef.h
@@ -0,0 +1,1236 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2007-01-10 Bernard the first version
+ * 2008-07-12 Bernard remove all rt_int8, rt_uint32_t etc typedef
+ * 2010-10-26 yi.qiu add module support
+ * 2010-11-10 Bernard add cleanup callback function in thread exit.
+ * 2011-05-09 Bernard use builtin va_arg in GCC 4.x
+ * 2012-11-16 Bernard change RT_NULL from ((void*)0) to 0.
+ * 2012-12-29 Bernard change the RT_USING_MEMPOOL location and add
+ * RT_USING_MEMHEAP condition.
+ * 2012-12-30 Bernard add more control command for graphic.
+ * 2013-01-09 Bernard change version number.
+ * 2015-02-01 Bernard change version number to v2.1.0
+ * 2017-08-31 Bernard change version number to v3.0.0
+ * 2017-11-30 Bernard change version number to v3.0.1
+ * 2017-12-27 Bernard change version number to v3.0.2
+ * 2018-02-24 Bernard change version number to v3.0.3
+ * 2018-04-25 Bernard change version number to v3.0.4
+ * 2018-05-31 Bernard change version number to v3.1.0
+ * 2018-09-04 Bernard change version number to v3.1.1
+ * 2018-09-14 Bernard apply Apache License v2.0 to RT-Thread Kernel
+ * 2018-10-13 Bernard change version number to v4.0.0
+ * 2018-10-02 Bernard add 64bit arch support
+ * 2018-11-22 Jesven add smp member to struct rt_thread
+ * add struct rt_cpu
+ * add smp relevant macros
+ * 2019-01-27 Bernard change version number to v4.0.1
+ * 2019-05-17 Bernard change version number to v4.0.2
+ * 2019-12-20 Bernard change version number to v4.0.3
+ * 2020-08-10 Meco Man add macro for struct rt_device_ops
+ * 2020-10-23 Meco Man define maximum value of ipc type
+ * 2021-03-19 Meco Man add security devices
+ * 2021-05-10 armink change version number to v4.0.4
+ * 2021-11-19 Meco Man change version number to v4.1.0
+ * 2021-12-21 Meco Man re-implement RT_UNUSED
+ * 2022-01-01 Gabriel improve hooking method
+ * 2022-01-07 Gabriel move some __on_rt_xxxxx_hook to dedicated c source files
+ * 2022-01-12 Meco Man remove RT_THREAD_BLOCK
+ * 2022-04-20 Meco Man change version number to v4.1.1
+ * 2022-04-21 THEWON add macro RT_VERSION_CHECK
+ * 2022-06-29 Meco Man add RT_USING_LIBC and standard libc headers
+ */
+
+#ifndef __RT_DEF_H__
+#define __RT_DEF_H__
+
+#include
+#ifdef RT_USING_LIBC
+#include
+#include
+#include
+#endif /* RT_USING_LIBC */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @addtogroup BasicDef
+ */
+
+/**@{*/
+
+/* RT-Thread version information */
+#define RT_VERSION 4 /**< major version number */
+#define RT_SUBVERSION 1 /**< minor version number */
+#define RT_REVISION 1 /**< revise version number */
+
+/* RT-Thread version */
+#define RTTHREAD_VERSION RT_VERSION_CHECK(RT_VERSION, RT_SUBVERSION, RT_REVISION)
+
+/* e.g. #if (RTTHREAD_VERSION >= RT_VERSION_CHECK(4, 1, 0) */
+#define RT_VERSION_CHECK(major, minor, revise) ((major * 10000) + \
+ (minor * 100) + revise)
+
+/* RT-Thread basic data type definitions */
+#ifndef RT_USING_ARCH_DATA_TYPE
+#ifdef RT_USING_LIBC
+typedef int8_t rt_int8_t; /**< 8bit integer type */
+typedef int16_t rt_int16_t; /**< 16bit integer type */
+typedef int32_t rt_int32_t; /**< 32bit integer type */
+typedef uint8_t rt_uint8_t; /**< 8bit unsigned integer type */
+typedef uint16_t rt_uint16_t; /**< 16bit unsigned integer type */
+typedef uint32_t rt_uint32_t; /**< 32bit unsigned integer type */
+typedef int64_t rt_int64_t; /**< 64bit integer type */
+typedef uint64_t rt_uint64_t; /**< 64bit unsigned integer type */
+typedef size_t rt_size_t; /**< Type for size number */
+
+#else
+typedef signed char rt_int8_t; /**< 8bit integer type */
+typedef signed short rt_int16_t; /**< 16bit integer type */
+typedef signed int rt_int32_t; /**< 32bit integer type */
+typedef unsigned char rt_uint8_t; /**< 8bit unsigned integer type */
+typedef unsigned short rt_uint16_t; /**< 16bit unsigned integer type */
+typedef unsigned int rt_uint32_t; /**< 32bit unsigned integer type */
+
+#ifdef ARCH_CPU_64BIT
+typedef signed long rt_int64_t; /**< 64bit integer type */
+typedef unsigned long rt_uint64_t; /**< 64bit unsigned integer type */
+typedef unsigned long rt_size_t; /**< Type for size number */
+#else
+typedef signed long long rt_int64_t; /**< 64bit integer type */
+typedef unsigned long long rt_uint64_t; /**< 64bit unsigned integer type */
+typedef unsigned int rt_size_t; /**< Type for size number */
+#endif /* ARCH_CPU_64BIT */
+#endif /* RT_USING_LIBC */
+#endif /* RT_USING_ARCH_DATA_TYPE */
+
+typedef int rt_bool_t; /**< boolean type */
+typedef long rt_base_t; /**< Nbit CPU related date type */
+typedef unsigned long rt_ubase_t; /**< Nbit unsigned CPU related data type */
+
+typedef rt_base_t rt_err_t; /**< Type for error number */
+typedef rt_uint32_t rt_time_t; /**< Type for time stamp */
+typedef rt_uint32_t rt_tick_t; /**< Type for tick count */
+typedef rt_base_t rt_flag_t; /**< Type for flags */
+typedef rt_ubase_t rt_dev_t; /**< Type for device */
+typedef rt_base_t rt_off_t; /**< Type for offset */
+
+/* boolean type definitions */
+#define RT_TRUE 1 /**< boolean true */
+#define RT_FALSE 0 /**< boolean fails */
+
+/* null pointer definition */
+#define RT_NULL 0
+
+/**@}*/
+
+/* maximum value of base type */
+#ifdef RT_USING_LIBC
+#define RT_UINT8_MAX UINT8_MAX /**< Maximum number of UINT8 */
+#define RT_UINT16_MAX UINT16_MAX /**< Maximum number of UINT16 */
+#define RT_UINT32_MAX UINT32_MAX /**< Maximum number of UINT32 */
+#else
+#define RT_UINT8_MAX 0xff /**< Maximum number of UINT8 */
+#define RT_UINT16_MAX 0xffff /**< Maximum number of UINT16 */
+#define RT_UINT32_MAX 0xffffffff /**< Maximum number of UINT32 */
+#endif /* RT_USING_LIBC */
+
+#define RT_TICK_MAX RT_UINT32_MAX /**< Maximum number of tick */
+
+/* maximum value of ipc type */
+#define RT_SEM_VALUE_MAX RT_UINT16_MAX /**< Maximum number of semaphore .value */
+#define RT_MUTEX_VALUE_MAX RT_UINT16_MAX /**< Maximum number of mutex .value */
+#define RT_MUTEX_HOLD_MAX RT_UINT8_MAX /**< Maximum number of mutex .hold */
+#define RT_MB_ENTRY_MAX RT_UINT16_MAX /**< Maximum number of mailbox .entry */
+#define RT_MQ_ENTRY_MAX RT_UINT16_MAX /**< Maximum number of message queue .entry */
+
+#define RT_UNUSED(x) ((void)x)
+
+/* Compiler Related Definitions */
+#if defined(__ARMCC_VERSION) /* ARM Compiler */
+#define RT_SECTION(x) __attribute__((section(x)))
+#define RT_USED __attribute__((used))
+#define ALIGN(n) __attribute__((aligned(n)))
+#define RT_WEAK __attribute__((weak))
+#define rt_inline static __inline
+/* module compiling */
+#ifdef RT_USING_MODULE
+#define RTT_API __declspec(dllimport)
+#else
+#define RTT_API __declspec(dllexport)
+#endif /* RT_USING_MODULE */
+#elif defined (__IAR_SYSTEMS_ICC__) /* for IAR Compiler */
+#define RT_SECTION(x) @ x
+#define RT_USED __root
+#define PRAGMA(x) _Pragma(#x)
+#define ALIGN(n) PRAGMA(data_alignment=n)
+#define RT_WEAK __weak
+#define rt_inline static inline
+#define RTT_API
+#elif defined (__GNUC__) /* GNU GCC Compiler */
+#ifndef RT_USING_LIBC
+/* the version of GNU GCC must be greater than 4.x */
+typedef __builtin_va_list __gnuc_va_list;
+typedef __gnuc_va_list va_list;
+#define va_start(v,l) __builtin_va_start(v,l)
+#define va_end(v) __builtin_va_end(v)
+#define va_arg(v,l) __builtin_va_arg(v,l)
+#endif /* RT_USING_LIBC */
+#define RT_SECTION(x) __attribute__((section(x)))
+#define RT_USED __attribute__((used))
+#define ALIGN(n) __attribute__((aligned(n)))
+#define RT_WEAK __attribute__((weak))
+#define rt_inline static __inline
+#define RTT_API
+#elif defined (__ADSPBLACKFIN__) /* for VisualDSP++ Compiler */
+#define RT_SECTION(x) __attribute__((section(x)))
+#define RT_USED __attribute__((used))
+#define ALIGN(n) __attribute__((aligned(n)))
+#define RT_WEAK __attribute__((weak))
+#define rt_inline static inline
+#define RTT_API
+#elif defined (_MSC_VER)
+#define RT_SECTION(x)
+#define RT_USED
+#define ALIGN(n) __declspec(align(n))
+#define RT_WEAK
+#define rt_inline static __inline
+#define RTT_API
+#elif defined (__TI_COMPILER_VERSION__)
+/* The way that TI compiler set section is different from other(at least
+ * GCC and MDK) compilers. See ARM Optimizing C/C++ Compiler 5.9.3 for more
+ * details. */
+#define RT_SECTION(x)
+#define RT_USED
+#define PRAGMA(x) _Pragma(#x)
+#define ALIGN(n)
+#define RT_WEAK
+#define rt_inline static inline
+#define RTT_API
+#elif defined (__TASKING__)
+#define RT_SECTION(x) __attribute__((section(x)))
+#define RT_USED __attribute__((used, protect))
+#define PRAGMA(x) _Pragma(#x)
+#define ALIGN(n) __attribute__((__align(n)))
+#define RT_WEAK __attribute__((weak))
+#define rt_inline static inline
+#define RTT_API
+#else
+ #error not supported tool chain
+#endif /* __ARMCC_VERSION */
+
+/* initialization export */
+#ifdef RT_USING_COMPONENTS_INIT
+typedef int (*init_fn_t)(void);
+#ifdef _MSC_VER
+#pragma section("rti_fn$f",read)
+ #if RT_DEBUG_INIT
+ struct rt_init_desc
+ {
+ const char* level;
+ const init_fn_t fn;
+ const char* fn_name;
+ };
+ #define INIT_EXPORT(fn, level) \
+ const char __rti_level_##fn[] = ".rti_fn." level; \
+ const char __rti_##fn##_name[] = #fn; \
+ __declspec(allocate("rti_fn$f")) \
+ RT_USED const struct rt_init_desc __rt_init_msc_##fn = \
+ {__rti_level_##fn, fn, __rti_##fn##_name};
+ #else
+ struct rt_init_desc
+ {
+ const char* level;
+ const init_fn_t fn;
+ };
+ #define INIT_EXPORT(fn, level) \
+ const char __rti_level_##fn[] = ".rti_fn." level; \
+ __declspec(allocate("rti_fn$f")) \
+ RT_USED const struct rt_init_desc __rt_init_msc_##fn = \
+ {__rti_level_##fn, fn };
+ #endif
+#else
+ #if RT_DEBUG_INIT
+ struct rt_init_desc
+ {
+ const char* fn_name;
+ const init_fn_t fn;
+ };
+ #define INIT_EXPORT(fn, level) \
+ const char __rti_##fn##_name[] = #fn; \
+ RT_USED const struct rt_init_desc __rt_init_desc_##fn RT_SECTION(".rti_fn." level) = \
+ { __rti_##fn##_name, fn};
+ #else
+ #define INIT_EXPORT(fn, level) \
+ RT_USED const init_fn_t __rt_init_##fn RT_SECTION(".rti_fn." level) = fn
+ #endif
+#endif
+#else
+#define INIT_EXPORT(fn, level)
+#endif
+
+/* board init routines will be called in board_init() function */
+#define INIT_BOARD_EXPORT(fn) INIT_EXPORT(fn, "1")
+
+/* pre/device/component/env/app init routines will be called in init_thread */
+/* components pre-initialization (pure software initialization) */
+#define INIT_PREV_EXPORT(fn) INIT_EXPORT(fn, "2")
+/* device initialization */
+#define INIT_DEVICE_EXPORT(fn) INIT_EXPORT(fn, "3")
+/* components initialization (dfs, lwip, ...) */
+#define INIT_COMPONENT_EXPORT(fn) INIT_EXPORT(fn, "4")
+/* environment initialization (mount disk, ...) */
+#define INIT_ENV_EXPORT(fn) INIT_EXPORT(fn, "5")
+/* application initialization (rtgui application etc ...) */
+#define INIT_APP_EXPORT(fn) INIT_EXPORT(fn, "6")
+
+#if !defined(RT_USING_FINSH)
+/* define these to empty, even if not include finsh.h file */
+#define FINSH_FUNCTION_EXPORT(name, desc)
+#define FINSH_FUNCTION_EXPORT_ALIAS(name, alias, desc)
+
+#define MSH_CMD_EXPORT(command, desc)
+#define MSH_CMD_EXPORT_ALIAS(command, alias, desc)
+#elif !defined(FINSH_USING_SYMTAB)
+#define FINSH_FUNCTION_EXPORT_CMD(name, cmd, desc)
+#endif
+
+/* event length */
+#define RT_EVENT_LENGTH 32
+
+/* memory management option */
+#define RT_MM_PAGE_SIZE 4096
+#define RT_MM_PAGE_MASK (RT_MM_PAGE_SIZE - 1)
+#define RT_MM_PAGE_BITS 12
+
+/* kernel malloc definitions */
+#ifndef RT_KERNEL_MALLOC
+#define RT_KERNEL_MALLOC(sz) rt_malloc(sz)
+#endif
+
+#ifndef RT_KERNEL_FREE
+#define RT_KERNEL_FREE(ptr) rt_free(ptr)
+#endif
+
+#ifndef RT_KERNEL_REALLOC
+#define RT_KERNEL_REALLOC(ptr, size) rt_realloc(ptr, size)
+#endif
+
+/**
+ * @addtogroup Error
+ */
+
+/**@{*/
+
+/* RT-Thread error code definitions */
+#define RT_EOK 0 /**< There is no error */
+#define RT_ERROR 1 /**< A generic error happens */
+#define RT_ETIMEOUT 2 /**< Timed out */
+#define RT_EFULL 3 /**< The resource is full */
+#define RT_EEMPTY 4 /**< The resource is empty */
+#define RT_ENOMEM 5 /**< No memory */
+#define RT_ENOSYS 6 /**< No system */
+#define RT_EBUSY 7 /**< Busy */
+#define RT_EIO 8 /**< IO error */
+#define RT_EINTR 9 /**< Interrupted system call */
+#define RT_EINVAL 10 /**< Invalid argument */
+
+/**@}*/
+
+/**
+ * @ingroup BasicDef
+ *
+ * @def RT_ALIGN(size, align)
+ * Return the most contiguous size aligned at specified width. RT_ALIGN(13, 4)
+ * would return 16.
+ */
+#define RT_ALIGN(size, align) (((size) + (align) - 1) & ~((align) - 1))
+
+/**
+ * @ingroup BasicDef
+ *
+ * @def RT_ALIGN_DOWN(size, align)
+ * Return the down number of aligned at specified width. RT_ALIGN_DOWN(13, 4)
+ * would return 12.
+ */
+#define RT_ALIGN_DOWN(size, align) ((size) & ~((align) - 1))
+
+/**
+ * Double List structure
+ */
+struct rt_list_node
+{
+ struct rt_list_node *next; /**< point to next node. */
+ struct rt_list_node *prev; /**< point to prev node. */
+};
+typedef struct rt_list_node rt_list_t; /**< Type for lists. */
+
+/**
+ * Single List structure
+ */
+struct rt_slist_node
+{
+ struct rt_slist_node *next; /**< point to next node. */
+};
+typedef struct rt_slist_node rt_slist_t; /**< Type for single list. */
+
+/**
+ * @addtogroup KernelObject
+ */
+
+/**@{*/
+
+/*
+ * kernel object macros
+ */
+#define RT_OBJECT_FLAG_MODULE 0x80 /**< is module object. */
+
+/**
+ * Base structure of Kernel object
+ */
+struct rt_object
+{
+ char name[RT_NAME_MAX]; /**< name of kernel object */
+ rt_uint8_t type; /**< type of kernel object */
+ rt_uint8_t flag; /**< flag of kernel object */
+
+#ifdef RT_USING_MODULE
+ void *module_id; /**< id of application module */
+#endif /* RT_USING_MODULE */
+ rt_list_t list; /**< list node of kernel object */
+};
+typedef struct rt_object *rt_object_t; /**< Type for kernel objects. */
+
+/**
+ * The object type can be one of the follows with specific
+ * macros enabled:
+ * - Thread
+ * - Semaphore
+ * - Mutex
+ * - Event
+ * - MailBox
+ * - MessageQueue
+ * - MemHeap
+ * - MemPool
+ * - Device
+ * - Timer
+ * - Module
+ * - Unknown
+ * - Static
+ */
+enum rt_object_class_type
+{
+ RT_Object_Class_Null = 0x00, /**< The object is not used. */
+ RT_Object_Class_Thread = 0x01, /**< The object is a thread. */
+ RT_Object_Class_Semaphore = 0x02, /**< The object is a semaphore. */
+ RT_Object_Class_Mutex = 0x03, /**< The object is a mutex. */
+ RT_Object_Class_Event = 0x04, /**< The object is a event. */
+ RT_Object_Class_MailBox = 0x05, /**< The object is a mail box. */
+ RT_Object_Class_MessageQueue = 0x06, /**< The object is a message queue. */
+ RT_Object_Class_MemHeap = 0x07, /**< The object is a memory heap. */
+ RT_Object_Class_MemPool = 0x08, /**< The object is a memory pool. */
+ RT_Object_Class_Device = 0x09, /**< The object is a device. */
+ RT_Object_Class_Timer = 0x0a, /**< The object is a timer. */
+ RT_Object_Class_Module = 0x0b, /**< The object is a module. */
+ RT_Object_Class_Memory = 0x0c, /**< The object is a memory. */
+ RT_Object_Class_Unknown = 0x0e, /**< The object is unknown. */
+ RT_Object_Class_Static = 0x80 /**< The object is a static object. */
+};
+
+/**
+ * The information of the kernel object
+ */
+struct rt_object_information
+{
+ enum rt_object_class_type type; /**< object class type */
+ rt_list_t object_list; /**< object list */
+ rt_size_t object_size; /**< object size */
+};
+
+/**
+ * The hook function call macro
+ */
+#ifndef RT_USING_HOOK
+ #define __ON_HOOK_ARGS(__hook, argv)
+ #define RT_OBJECT_HOOK_CALL(func, argv)
+#else
+ #define RT_OBJECT_HOOK_CALL(func, argv) __on_##func argv
+ #ifdef RT_HOOK_USING_FUNC_PTR
+ #define __ON_HOOK_ARGS(__hook, argv) do {if ((__hook) != RT_NULL) __hook argv; } while (0)
+ #else
+ #define __ON_HOOK_ARGS(__hook, argv)
+ #endif /* RT_HOOK_USING_FUNC_PTR */
+#endif /* RT_USING_HOOK */
+
+#ifndef __on_rt_interrupt_switch_hook
+ #define __on_rt_interrupt_switch_hook() __ON_HOOK_ARGS(rt_interrupt_switch_hook, ())
+#endif
+#ifndef __on_rt_malloc_hook
+ #define __on_rt_malloc_hook(addr, size) __ON_HOOK_ARGS(rt_malloc_hook, (addr, size))
+#endif
+#ifndef __on_rt_free_hook
+ #define __on_rt_free_hook(rmem) __ON_HOOK_ARGS(rt_free_hook, (rmem))
+#endif
+
+
+/**@}*/
+
+/**
+ * @addtogroup Clock
+ */
+
+/**@{*/
+
+/**
+ * clock & timer macros
+ */
+#define RT_TIMER_FLAG_DEACTIVATED 0x0 /**< timer is deactive */
+#define RT_TIMER_FLAG_ACTIVATED 0x1 /**< timer is active */
+#define RT_TIMER_FLAG_ONE_SHOT 0x0 /**< one shot timer */
+#define RT_TIMER_FLAG_PERIODIC 0x2 /**< periodic timer */
+
+#define RT_TIMER_FLAG_HARD_TIMER 0x0 /**< hard timer,the timer's callback function will be called in tick isr. */
+#define RT_TIMER_FLAG_SOFT_TIMER 0x4 /**< soft timer,the timer's callback function will be called in timer thread. */
+
+#define RT_TIMER_CTRL_SET_TIME 0x0 /**< set timer control command */
+#define RT_TIMER_CTRL_GET_TIME 0x1 /**< get timer control command */
+#define RT_TIMER_CTRL_SET_ONESHOT 0x2 /**< change timer to one shot */
+#define RT_TIMER_CTRL_SET_PERIODIC 0x3 /**< change timer to periodic */
+#define RT_TIMER_CTRL_GET_STATE 0x4 /**< get timer run state active or deactive*/
+#define RT_TIMER_CTRL_GET_REMAIN_TIME 0x5 /**< get the remaining hang time */
+
+#ifndef RT_TIMER_SKIP_LIST_LEVEL
+#define RT_TIMER_SKIP_LIST_LEVEL 1
+#endif
+
+/* 1 or 3 */
+#ifndef RT_TIMER_SKIP_LIST_MASK
+#define RT_TIMER_SKIP_LIST_MASK 0x3
+#endif
+
+/**
+ * timer structure
+ */
+struct rt_timer
+{
+ struct rt_object parent; /**< inherit from rt_object */
+
+ rt_list_t row[RT_TIMER_SKIP_LIST_LEVEL];
+
+ void (*timeout_func)(void *parameter); /**< timeout function */
+ void *parameter; /**< timeout function's parameter */
+
+ rt_tick_t init_tick; /**< timer timeout tick */
+ rt_tick_t timeout_tick; /**< timeout tick */
+};
+typedef struct rt_timer *rt_timer_t;
+
+/**@}*/
+
+/**
+ * @addtogroup Signal
+ */
+#ifdef RT_USING_SIGNALS
+#include
+typedef unsigned long rt_sigset_t;
+typedef void (*rt_sighandler_t)(int signo);
+typedef siginfo_t rt_siginfo_t;
+
+#define RT_SIG_MAX 32
+#endif /* RT_USING_SIGNALS */
+/**@}*/
+
+/**
+ * @addtogroup Thread
+ */
+
+/**@{*/
+
+/*
+ * Thread
+ */
+
+/*
+ * thread state definitions
+ */
+#define RT_THREAD_INIT 0x00 /**< Initialized status */
+#define RT_THREAD_READY 0x01 /**< Ready status */
+#define RT_THREAD_SUSPEND 0x02 /**< Suspend status */
+#define RT_THREAD_RUNNING 0x03 /**< Running status */
+#define RT_THREAD_CLOSE 0x04 /**< Closed status */
+#define RT_THREAD_STAT_MASK 0x07
+
+#define RT_THREAD_STAT_YIELD 0x08 /**< indicate whether remaining_tick has been reloaded since last schedule */
+#define RT_THREAD_STAT_YIELD_MASK RT_THREAD_STAT_YIELD
+
+#define RT_THREAD_STAT_SIGNAL 0x10 /**< task hold signals */
+#define RT_THREAD_STAT_SIGNAL_READY (RT_THREAD_STAT_SIGNAL | RT_THREAD_READY)
+#define RT_THREAD_STAT_SIGNAL_WAIT 0x20 /**< task is waiting for signals */
+#define RT_THREAD_STAT_SIGNAL_PENDING 0x40 /**< signals is held and it has not been procressed */
+#define RT_THREAD_STAT_SIGNAL_MASK 0xf0
+
+/**
+ * thread control command definitions
+ */
+#define RT_THREAD_CTRL_STARTUP 0x00 /**< Startup thread. */
+#define RT_THREAD_CTRL_CLOSE 0x01 /**< Close thread. */
+#define RT_THREAD_CTRL_CHANGE_PRIORITY 0x02 /**< Change thread priority. */
+#define RT_THREAD_CTRL_INFO 0x03 /**< Get thread information. */
+#define RT_THREAD_CTRL_BIND_CPU 0x04 /**< Set thread bind cpu. */
+
+#ifdef RT_USING_SMP
+
+#define RT_CPU_DETACHED RT_CPUS_NR /**< The thread not running on cpu. */
+#define RT_CPU_MASK ((1 << RT_CPUS_NR) - 1) /**< All CPUs mask bit. */
+
+#ifndef RT_SCHEDULE_IPI
+#define RT_SCHEDULE_IPI 0
+#endif /* RT_SCHEDULE_IPI */
+
+#ifndef RT_STOP_IPI
+#define RT_STOP_IPI 1
+#endif /* RT_STOP_IPI */
+
+/**
+ * CPUs definitions
+ *
+ */
+struct rt_cpu
+{
+ struct rt_thread *current_thread;
+
+ rt_uint16_t irq_nest;
+ rt_uint8_t irq_switch_flag;
+
+ rt_uint8_t current_priority;
+ rt_list_t priority_table[RT_THREAD_PRIORITY_MAX];
+#if RT_THREAD_PRIORITY_MAX > 32
+ rt_uint32_t priority_group;
+ rt_uint8_t ready_table[32];
+#else
+ rt_uint32_t priority_group;
+#endif /* RT_THREAD_PRIORITY_MAX > 32 */
+
+ rt_tick_t tick;
+};
+
+#endif /* RT_USING_SMP */
+
+/**
+ * Thread structure
+ */
+struct rt_thread
+{
+ /* rt object */
+ char name[RT_NAME_MAX]; /**< the name of thread */
+ rt_uint8_t type; /**< type of object */
+ rt_uint8_t flags; /**< thread's flags */
+
+#ifdef RT_USING_MODULE
+ void *module_id; /**< id of application module */
+#endif /* RT_USING_MODULE */
+
+ rt_list_t list; /**< the object list */
+ rt_list_t tlist; /**< the thread list */
+
+ /* stack point and entry */
+ void *sp; /**< stack point */
+ void *entry; /**< entry */
+ void *parameter; /**< parameter */
+ void *stack_addr; /**< stack address */
+ rt_uint32_t stack_size; /**< stack size */
+
+ /* error code */
+ rt_err_t error; /**< error code */
+
+ rt_uint8_t stat; /**< thread status */
+
+#ifdef RT_USING_SMP
+ rt_uint8_t bind_cpu; /**< thread is bind to cpu */
+ rt_uint8_t oncpu; /**< process on cpu */
+
+ rt_uint16_t scheduler_lock_nest; /**< scheduler lock count */
+ rt_uint16_t cpus_lock_nest; /**< cpus lock count */
+ rt_uint16_t critical_lock_nest; /**< critical lock count */
+#endif /*RT_USING_SMP*/
+
+ /* priority */
+ rt_uint8_t current_priority; /**< current priority */
+#if RT_THREAD_PRIORITY_MAX > 32
+ rt_uint8_t number;
+ rt_uint8_t high_mask;
+#endif /* RT_THREAD_PRIORITY_MAX > 32 */
+ rt_uint32_t number_mask;
+
+#ifdef RT_USING_EVENT
+ /* thread event */
+ rt_uint32_t event_set;
+ rt_uint8_t event_info;
+#endif /* RT_USING_EVENT */
+
+#ifdef RT_USING_SIGNALS
+ rt_sigset_t sig_pending; /**< the pending signals */
+ rt_sigset_t sig_mask; /**< the mask bits of signal */
+
+#ifndef RT_USING_SMP
+ void *sig_ret; /**< the return stack pointer from signal */
+#endif /* RT_USING_SMP */
+ rt_sighandler_t *sig_vectors; /**< vectors of signal handler */
+ void *si_list; /**< the signal infor list */
+#endif /* RT_USING_SIGNALS */
+
+ rt_ubase_t init_tick; /**< thread's initialized tick */
+ rt_ubase_t remaining_tick; /**< remaining tick */
+
+#ifdef RT_USING_CPU_USAGE
+ rt_uint64_t duration_tick; /**< cpu usage tick */
+#endif /* RT_USING_CPU_USAGE */
+
+#ifdef RT_USING_PTHREADS
+ void *pthread_data; /**< the handle of pthread data, adapt 32/64bit */
+#endif /* RT_USING_PTHREADS */
+
+ struct rt_timer thread_timer; /**< built-in thread timer */
+
+ void (*cleanup)(struct rt_thread *tid); /**< cleanup function when thread exit */
+
+ /* light weight process if present */
+#ifdef RT_USING_LWP
+ void *lwp;
+#endif /* RT_USING_LWP */
+
+ rt_ubase_t user_data; /**< private user data beyond this thread */
+};
+typedef struct rt_thread *rt_thread_t;
+
+/**@}*/
+
+/**
+ * @addtogroup IPC
+ */
+
+/**@{*/
+
+/**
+ * IPC flags and control command definitions
+ */
+#define RT_IPC_FLAG_FIFO 0x00 /**< FIFOed IPC. @ref IPC. */
+#define RT_IPC_FLAG_PRIO 0x01 /**< PRIOed IPC. @ref IPC. */
+
+#define RT_IPC_CMD_UNKNOWN 0x00 /**< unknown IPC command */
+#define RT_IPC_CMD_RESET 0x01 /**< reset IPC object */
+
+#define RT_WAITING_FOREVER -1 /**< Block forever until get resource. */
+#define RT_WAITING_NO 0 /**< Non-block. */
+
+/**
+ * Base structure of IPC object
+ */
+struct rt_ipc_object
+{
+ struct rt_object parent; /**< inherit from rt_object */
+
+ rt_list_t suspend_thread; /**< threads pended on this resource */
+};
+
+#ifdef RT_USING_SEMAPHORE
+/**
+ * Semaphore structure
+ */
+struct rt_semaphore
+{
+ struct rt_ipc_object parent; /**< inherit from ipc_object */
+
+ rt_uint16_t value; /**< value of semaphore. */
+ rt_uint16_t reserved; /**< reserved field */
+};
+typedef struct rt_semaphore *rt_sem_t;
+#endif /* RT_USING_SEMAPHORE */
+
+#ifdef RT_USING_MUTEX
+/**
+ * Mutual exclusion (mutex) structure
+ */
+struct rt_mutex
+{
+ struct rt_ipc_object parent; /**< inherit from ipc_object */
+
+ rt_uint16_t value; /**< value of mutex */
+
+ rt_uint8_t original_priority; /**< priority of last thread hold the mutex */
+ rt_uint8_t hold; /**< numbers of thread hold the mutex */
+
+ struct rt_thread *owner; /**< current owner of mutex */
+};
+typedef struct rt_mutex *rt_mutex_t;
+#endif /* RT_USING_MUTEX */
+
+#ifdef RT_USING_EVENT
+/**
+ * flag definitions in event
+ */
+#define RT_EVENT_FLAG_AND 0x01 /**< logic and */
+#define RT_EVENT_FLAG_OR 0x02 /**< logic or */
+#define RT_EVENT_FLAG_CLEAR 0x04 /**< clear flag */
+
+/*
+ * event structure
+ */
+struct rt_event
+{
+ struct rt_ipc_object parent; /**< inherit from ipc_object */
+
+ rt_uint32_t set; /**< event set */
+};
+typedef struct rt_event *rt_event_t;
+#endif /* RT_USING_EVENT */
+
+#ifdef RT_USING_MAILBOX
+/**
+ * mailbox structure
+ */
+struct rt_mailbox
+{
+ struct rt_ipc_object parent; /**< inherit from ipc_object */
+
+ rt_ubase_t *msg_pool; /**< start address of message buffer */
+
+ rt_uint16_t size; /**< size of message pool */
+
+ rt_uint16_t entry; /**< index of messages in msg_pool */
+ rt_uint16_t in_offset; /**< input offset of the message buffer */
+ rt_uint16_t out_offset; /**< output offset of the message buffer */
+
+ rt_list_t suspend_sender_thread; /**< sender thread suspended on this mailbox */
+};
+typedef struct rt_mailbox *rt_mailbox_t;
+#endif /* RT_USING_MAILBOX */
+
+#ifdef RT_USING_MESSAGEQUEUE
+/**
+ * message queue structure
+ */
+struct rt_messagequeue
+{
+ struct rt_ipc_object parent; /**< inherit from ipc_object */
+
+ void *msg_pool; /**< start address of message queue */
+
+ rt_uint16_t msg_size; /**< message size of each message */
+ rt_uint16_t max_msgs; /**< max number of messages */
+
+ rt_uint16_t entry; /**< index of messages in the queue */
+
+ void *msg_queue_head; /**< list head */
+ void *msg_queue_tail; /**< list tail */
+ void *msg_queue_free; /**< pointer indicated the free node of queue */
+
+ rt_list_t suspend_sender_thread; /**< sender thread suspended on this message queue */
+};
+typedef struct rt_messagequeue *rt_mq_t;
+#endif /* RT_USING_MESSAGEQUEUE */
+
+/**@}*/
+
+/**
+ * @addtogroup MM
+ */
+
+/**@{*/
+
+#ifdef RT_USING_HEAP
+/*
+ * memory structure
+ */
+struct rt_memory
+{
+ struct rt_object parent; /**< inherit from rt_object */
+ const char * algorithm; /**< Memory management algorithm name */
+ rt_ubase_t address; /**< memory start address */
+ rt_size_t total; /**< memory size */
+ rt_size_t used; /**< size used */
+ rt_size_t max; /**< maximum usage */
+};
+typedef struct rt_memory *rt_mem_t;
+#endif /* RT_USING_HEAP */
+
+/*
+ * memory management
+ * heap & partition
+ */
+
+#ifdef RT_USING_SMALL_MEM
+typedef rt_mem_t rt_smem_t;
+#endif /* RT_USING_SMALL_MEM */
+
+#ifdef RT_USING_SLAB
+typedef rt_mem_t rt_slab_t;
+#endif /* RT_USING_SLAB */
+
+#ifdef RT_USING_MEMHEAP
+/**
+ * memory item on the heap
+ */
+struct rt_memheap_item
+{
+ rt_uint32_t magic; /**< magic number for memheap */
+ struct rt_memheap *pool_ptr; /**< point of pool */
+
+ struct rt_memheap_item *next; /**< next memheap item */
+ struct rt_memheap_item *prev; /**< prev memheap item */
+
+ struct rt_memheap_item *next_free; /**< next free memheap item */
+ struct rt_memheap_item *prev_free; /**< prev free memheap item */
+#ifdef RT_USING_MEMTRACE
+ rt_uint8_t owner_thread_name[4]; /**< owner thread name */
+#endif /* RT_USING_MEMTRACE */
+};
+
+/**
+ * Base structure of memory heap object
+ */
+struct rt_memheap
+{
+ struct rt_object parent; /**< inherit from rt_object */
+
+ void *start_addr; /**< pool start address and size */
+
+ rt_size_t pool_size; /**< pool size */
+ rt_size_t available_size; /**< available size */
+ rt_size_t max_used_size; /**< maximum allocated size */
+
+ struct rt_memheap_item *block_list; /**< used block list */
+
+ struct rt_memheap_item *free_list; /**< free block list */
+ struct rt_memheap_item free_header; /**< free block list header */
+
+ struct rt_semaphore lock; /**< semaphore lock */
+ rt_bool_t locked; /**< External lock mark */
+};
+#endif /* RT_USING_MEMHEAP */
+
+#ifdef RT_USING_MEMPOOL
+/**
+ * Base structure of Memory pool object
+ */
+struct rt_mempool
+{
+ struct rt_object parent; /**< inherit from rt_object */
+
+ void *start_address; /**< memory pool start */
+ rt_size_t size; /**< size of memory pool */
+
+ rt_size_t block_size; /**< size of memory blocks */
+ rt_uint8_t *block_list; /**< memory blocks list */
+
+ rt_size_t block_total_count; /**< numbers of memory block */
+ rt_size_t block_free_count; /**< numbers of free memory block */
+
+ rt_list_t suspend_thread; /**< threads pended on this resource */
+};
+typedef struct rt_mempool *rt_mp_t;
+#endif /* RT_USING_MEMPOOL */
+
+/**@}*/
+
+#ifdef RT_USING_DEVICE
+/**
+ * @addtogroup Device
+ */
+
+/**@{*/
+
+/**
+ * device (I/O) class type
+ */
+enum rt_device_class_type
+{
+ RT_Device_Class_Char = 0, /**< character device */
+ RT_Device_Class_Block, /**< block device */
+ RT_Device_Class_NetIf, /**< net interface */
+ RT_Device_Class_MTD, /**< memory device */
+ RT_Device_Class_CAN, /**< CAN device */
+ RT_Device_Class_RTC, /**< RTC device */
+ RT_Device_Class_Sound, /**< Sound device */
+ RT_Device_Class_Graphic, /**< Graphic device */
+ RT_Device_Class_I2CBUS, /**< I2C bus device */
+ RT_Device_Class_USBDevice, /**< USB slave device */
+ RT_Device_Class_USBHost, /**< USB host bus */
+ RT_Device_Class_USBOTG, /**< USB OTG bus */
+ RT_Device_Class_SPIBUS, /**< SPI bus device */
+ RT_Device_Class_SPIDevice, /**< SPI device */
+ RT_Device_Class_SDIO, /**< SDIO bus device */
+ RT_Device_Class_PM, /**< PM pseudo device */
+ RT_Device_Class_Pipe, /**< Pipe device */
+ RT_Device_Class_Portal, /**< Portal device */
+ RT_Device_Class_Timer, /**< Timer device */
+ RT_Device_Class_Miscellaneous, /**< Miscellaneous device */
+ RT_Device_Class_Sensor, /**< Sensor device */
+ RT_Device_Class_Touch, /**< Touch device */
+ RT_Device_Class_PHY, /**< PHY device */
+ RT_Device_Class_Security, /**< Security device */
+ RT_Device_Class_WLAN, /**< WLAN device */
+ RT_Device_Class_Pin, /**< Pin device */
+ RT_Device_Class_ADC, /**< ADC device */
+ RT_Device_Class_DAC, /**< DAC device */
+ RT_Device_Class_WDT, /**< WDT device */
+ RT_Device_Class_PWM, /**< PWM device */
+ RT_Device_Class_Unknown /**< unknown device */
+};
+
+/**
+ * device flags definitions
+ */
+#define RT_DEVICE_FLAG_DEACTIVATE 0x000 /**< device is not not initialized */
+
+#define RT_DEVICE_FLAG_RDONLY 0x001 /**< read only */
+#define RT_DEVICE_FLAG_WRONLY 0x002 /**< write only */
+#define RT_DEVICE_FLAG_RDWR 0x003 /**< read and write */
+
+#define RT_DEVICE_FLAG_REMOVABLE 0x004 /**< removable device */
+#define RT_DEVICE_FLAG_STANDALONE 0x008 /**< standalone device */
+#define RT_DEVICE_FLAG_ACTIVATED 0x010 /**< device is activated */
+#define RT_DEVICE_FLAG_SUSPENDED 0x020 /**< device is suspended */
+#define RT_DEVICE_FLAG_STREAM 0x040 /**< stream mode */
+
+#define RT_DEVICE_FLAG_INT_RX 0x100 /**< INT mode on Rx */
+#define RT_DEVICE_FLAG_DMA_RX 0x200 /**< DMA mode on Rx */
+#define RT_DEVICE_FLAG_INT_TX 0x400 /**< INT mode on Tx */
+#define RT_DEVICE_FLAG_DMA_TX 0x800 /**< DMA mode on Tx */
+
+#define RT_DEVICE_OFLAG_CLOSE 0x000 /**< device is closed */
+#define RT_DEVICE_OFLAG_RDONLY 0x001 /**< read only access */
+#define RT_DEVICE_OFLAG_WRONLY 0x002 /**< write only access */
+#define RT_DEVICE_OFLAG_RDWR 0x003 /**< read and write */
+#define RT_DEVICE_OFLAG_OPEN 0x008 /**< device is opened */
+#define RT_DEVICE_OFLAG_MASK 0xf0f /**< mask of open flag */
+
+/**
+ * general device commands
+ */
+#define RT_DEVICE_CTRL_RESUME 0x01 /**< resume device */
+#define RT_DEVICE_CTRL_SUSPEND 0x02 /**< suspend device */
+#define RT_DEVICE_CTRL_CONFIG 0x03 /**< configure device */
+#define RT_DEVICE_CTRL_CLOSE 0x04 /**< close device */
+
+#define RT_DEVICE_CTRL_SET_INT 0x10 /**< set interrupt */
+#define RT_DEVICE_CTRL_CLR_INT 0x11 /**< clear interrupt */
+#define RT_DEVICE_CTRL_GET_INT 0x12 /**< get interrupt status */
+
+/**
+ * device control
+ */
+#define RT_DEVICE_CTRL_BASE(Type) (RT_Device_Class_##Type * 0x100)
+
+/**
+ * special device commands
+ */
+#define RT_DEVICE_CTRL_CHAR_STREAM (RT_DEVICE_CTRL_BASE(Char) + 1) /**< stream mode on char device */
+#define RT_DEVICE_CTRL_BLK_GETGEOME (RT_DEVICE_CTRL_BASE(Block) + 1) /**< get geometry information */
+#define RT_DEVICE_CTRL_BLK_SYNC (RT_DEVICE_CTRL_BASE(Block) + 2) /**< flush data to block device */
+#define RT_DEVICE_CTRL_BLK_ERASE (RT_DEVICE_CTRL_BASE(Block) + 3) /**< erase block on block device */
+#define RT_DEVICE_CTRL_BLK_AUTOREFRESH (RT_DEVICE_CTRL_BASE(Block) + 4) /**< block device : enter/exit auto refresh mode */
+#define RT_DEVICE_CTRL_NETIF_GETMAC (RT_DEVICE_CTRL_BASE(NetIf) + 1) /**< get mac address */
+#define RT_DEVICE_CTRL_MTD_FORMAT (RT_DEVICE_CTRL_BASE(MTD) + 1) /**< format a MTD device */
+
+typedef struct rt_device *rt_device_t;
+
+#ifdef RT_USING_DEVICE_OPS
+/**
+ * operations set for device object
+ */
+struct rt_device_ops
+{
+ /* common device interface */
+ rt_err_t (*init) (rt_device_t dev);
+ rt_err_t (*open) (rt_device_t dev, rt_uint16_t oflag);
+ rt_err_t (*close) (rt_device_t dev);
+ rt_size_t (*read) (rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size);
+ rt_size_t (*write) (rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size);
+ rt_err_t (*control)(rt_device_t dev, int cmd, void *args);
+};
+#endif /* RT_USING_DEVICE_OPS */
+
+/**
+ * WaitQueue structure
+ */
+struct rt_wqueue
+{
+ rt_uint32_t flag;
+ rt_list_t waiting_list;
+};
+typedef struct rt_wqueue rt_wqueue_t;
+
+/**
+ * Device structure
+ */
+struct rt_device
+{
+ struct rt_object parent; /**< inherit from rt_object */
+
+ enum rt_device_class_type type; /**< device type */
+ rt_uint16_t flag; /**< device flag */
+ rt_uint16_t open_flag; /**< device open flag */
+
+ rt_uint8_t ref_count; /**< reference count */
+ rt_uint8_t device_id; /**< 0 - 255 */
+
+ /* device call back */
+ rt_err_t (*rx_indicate)(rt_device_t dev, rt_size_t size);
+ rt_err_t (*tx_complete)(rt_device_t dev, void *buffer);
+
+#ifdef RT_USING_DEVICE_OPS
+ const struct rt_device_ops *ops;
+#else
+ /* common device interface */
+ rt_err_t (*init) (rt_device_t dev);
+ rt_err_t (*open) (rt_device_t dev, rt_uint16_t oflag);
+ rt_err_t (*close) (rt_device_t dev);
+ rt_size_t (*read) (rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size);
+ rt_size_t (*write) (rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size);
+ rt_err_t (*control)(rt_device_t dev, int cmd, void *args);
+#endif /* RT_USING_DEVICE_OPS */
+
+#ifdef RT_USING_POSIX_DEVIO
+ const struct dfs_file_ops *fops;
+ struct rt_wqueue wait_queue;
+#endif /* RT_USING_POSIX_DEVIO */
+
+ void *user_data; /**< device private data */
+};
+
+/**
+ * block device geometry structure
+ */
+struct rt_device_blk_geometry
+{
+ rt_uint32_t sector_count; /**< count of sectors */
+ rt_uint32_t bytes_per_sector; /**< number of bytes per sector */
+ rt_uint32_t block_size; /**< number of bytes to erase one block */
+};
+
+/**
+ * sector arrange struct on block device
+ */
+struct rt_device_blk_sectors
+{
+ rt_uint32_t sector_begin; /**< begin sector */
+ rt_uint32_t sector_end; /**< end sector */
+};
+
+/**
+ * cursor control command
+ */
+#define RT_DEVICE_CTRL_CURSOR_SET_POSITION 0x10
+#define RT_DEVICE_CTRL_CURSOR_SET_TYPE 0x11
+
+/**
+ * graphic device control command
+ */
+#define RTGRAPHIC_CTRL_RECT_UPDATE (RT_DEVICE_CTRL_BASE(Graphic) + 0)
+#define RTGRAPHIC_CTRL_POWERON (RT_DEVICE_CTRL_BASE(Graphic) + 1)
+#define RTGRAPHIC_CTRL_POWEROFF (RT_DEVICE_CTRL_BASE(Graphic) + 2)
+#define RTGRAPHIC_CTRL_GET_INFO (RT_DEVICE_CTRL_BASE(Graphic) + 3)
+#define RTGRAPHIC_CTRL_SET_MODE (RT_DEVICE_CTRL_BASE(Graphic) + 4)
+#define RTGRAPHIC_CTRL_GET_EXT (RT_DEVICE_CTRL_BASE(Graphic) + 5)
+#define RTGRAPHIC_CTRL_SET_BRIGHTNESS (RT_DEVICE_CTRL_BASE(Graphic) + 6)
+#define RTGRAPHIC_CTRL_GET_BRIGHTNESS (RT_DEVICE_CTRL_BASE(Graphic) + 7)
+#define RTGRAPHIC_CTRL_GET_MODE (RT_DEVICE_CTRL_BASE(Graphic) + 8)
+#define RTGRAPHIC_CTRL_GET_STATUS (RT_DEVICE_CTRL_BASE(Graphic) + 9)
+#define RTGRAPHIC_CTRL_PAN_DISPLAY (RT_DEVICE_CTRL_BASE(Graphic) + 10)
+#define RTGRAPHIC_CTRL_WAIT_VSYNC (RT_DEVICE_CTRL_BASE(Graphic) + 11)
+
+/* graphic device */
+enum
+{
+ RTGRAPHIC_PIXEL_FORMAT_MONO = 0,
+ RTGRAPHIC_PIXEL_FORMAT_GRAY4,
+ RTGRAPHIC_PIXEL_FORMAT_GRAY16,
+ RTGRAPHIC_PIXEL_FORMAT_RGB332,
+ RTGRAPHIC_PIXEL_FORMAT_RGB444,
+ RTGRAPHIC_PIXEL_FORMAT_RGB565,
+ RTGRAPHIC_PIXEL_FORMAT_RGB565P,
+ RTGRAPHIC_PIXEL_FORMAT_BGR565 = RTGRAPHIC_PIXEL_FORMAT_RGB565P,
+ RTGRAPHIC_PIXEL_FORMAT_RGB666,
+ RTGRAPHIC_PIXEL_FORMAT_RGB888,
+ RTGRAPHIC_PIXEL_FORMAT_BGR888,
+ RTGRAPHIC_PIXEL_FORMAT_ARGB888,
+ RTGRAPHIC_PIXEL_FORMAT_ABGR888,
+ RTGRAPHIC_PIXEL_FORMAT_RESERVED,
+};
+
+/**
+ * build a pixel position according to (x, y) coordinates.
+ */
+#define RTGRAPHIC_PIXEL_POSITION(x, y) ((x << 16) | y)
+
+/**
+ * graphic device information structure
+ */
+struct rt_device_graphic_info
+{
+ rt_uint8_t pixel_format; /**< graphic format */
+ rt_uint8_t bits_per_pixel; /**< bits per pixel */
+ rt_uint16_t pitch; /**< bytes per line */
+
+ rt_uint16_t width; /**< width of graphic device */
+ rt_uint16_t height; /**< height of graphic device */
+
+ rt_uint8_t *framebuffer; /**< frame buffer */
+ rt_uint32_t smem_len; /**< allocated frame buffer size */
+};
+
+/**
+ * rectangle information structure
+ */
+struct rt_device_rect_info
+{
+ rt_uint16_t x; /**< x coordinate */
+ rt_uint16_t y; /**< y coordinate */
+ rt_uint16_t width; /**< width */
+ rt_uint16_t height; /**< height */
+};
+
+/**
+ * graphic operations
+ */
+struct rt_device_graphic_ops
+{
+ void (*set_pixel) (const char *pixel, int x, int y);
+ void (*get_pixel) (char *pixel, int x, int y);
+
+ void (*draw_hline)(const char *pixel, int x1, int x2, int y);
+ void (*draw_vline)(const char *pixel, int x, int y1, int y2);
+
+ void (*blit_line) (const char *pixel, int x, int y, rt_size_t size);
+};
+#define rt_graphix_ops(device) ((struct rt_device_graphic_ops *)(device->user_data))
+
+/**@}*/
+#endif /* RT_USING_DEVICE */
+
+#ifdef __cplusplus
+}
+#endif
+
+#ifdef __cplusplus
+/* RT-Thread definitions for C++ */
+namespace rtthread {
+
+enum TICK_WAIT {
+ WAIT_NONE = 0,
+ WAIT_FOREVER = -1,
+};
+
+}
+
+#endif /* __cplusplus */
+
+#endif /* __RT_DEF_H__ */
diff --git a/User/system/rt-thread/include/rthw.h b/User/system/rt-thread/include/rthw.h
new file mode 100644
index 0000000..b55d12e
--- /dev/null
+++ b/User/system/rt-thread/include/rthw.h
@@ -0,0 +1,199 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2006-03-18 Bernard the first version
+ * 2006-04-25 Bernard add rt_hw_context_switch_interrupt declaration
+ * 2006-09-24 Bernard add rt_hw_context_switch_to declaration
+ * 2012-12-29 Bernard add rt_hw_exception_install declaration
+ * 2017-10-17 Hichard add some macros
+ * 2018-11-17 Jesven add rt_hw_spinlock_t
+ * add smp support
+ */
+
+#ifndef __RT_HW_H__
+#define __RT_HW_H__
+
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Some macros define
+ */
+#ifndef HWREG64
+#define HWREG64(x) (*((volatile rt_uint64_t *)(x)))
+#endif
+#ifndef HWREG32
+#define HWREG32(x) (*((volatile rt_uint32_t *)(x)))
+#endif
+#ifndef HWREG16
+#define HWREG16(x) (*((volatile rt_uint16_t *)(x)))
+#endif
+#ifndef HWREG8
+#define HWREG8(x) (*((volatile rt_uint8_t *)(x)))
+#endif
+
+#ifndef RT_CPU_CACHE_LINE_SZ
+#define RT_CPU_CACHE_LINE_SZ 32
+#endif
+
+enum RT_HW_CACHE_OPS
+{
+ RT_HW_CACHE_FLUSH = 0x01,
+ RT_HW_CACHE_INVALIDATE = 0x02,
+};
+
+/*
+ * CPU interfaces
+ */
+void rt_hw_cpu_icache_enable(void);
+void rt_hw_cpu_icache_disable(void);
+rt_base_t rt_hw_cpu_icache_status(void);
+void rt_hw_cpu_icache_ops(int ops, void* addr, int size);
+
+void rt_hw_cpu_dcache_enable(void);
+void rt_hw_cpu_dcache_disable(void);
+rt_base_t rt_hw_cpu_dcache_status(void);
+void rt_hw_cpu_dcache_ops(int ops, void* addr, int size);
+
+void rt_hw_cpu_reset(void);
+void rt_hw_cpu_shutdown(void);
+
+rt_uint8_t *rt_hw_stack_init(void *entry,
+ void *parameter,
+ rt_uint8_t *stack_addr,
+ void *exit);
+
+/*
+ * Interrupt handler definition
+ */
+typedef void (*rt_isr_handler_t)(int vector, void *param);
+
+struct rt_irq_desc
+{
+ rt_isr_handler_t handler;
+ void *param;
+
+#ifdef RT_USING_INTERRUPT_INFO
+ char name[RT_NAME_MAX];
+ rt_uint32_t counter;
+#endif
+};
+
+/*
+ * Interrupt interfaces
+ */
+void rt_hw_interrupt_init(void);
+void rt_hw_interrupt_mask(int vector);
+void rt_hw_interrupt_umask(int vector);
+rt_isr_handler_t rt_hw_interrupt_install(int vector,
+ rt_isr_handler_t handler,
+ void *param,
+ const char *name);
+
+#ifdef RT_USING_SMP
+rt_base_t rt_hw_local_irq_disable();
+void rt_hw_local_irq_enable(rt_base_t level);
+
+#define rt_hw_interrupt_disable rt_cpus_lock
+#define rt_hw_interrupt_enable rt_cpus_unlock
+
+#else
+rt_base_t rt_hw_interrupt_disable(void);
+void rt_hw_interrupt_enable(rt_base_t level);
+#endif /*RT_USING_SMP*/
+
+/*
+ * Context interfaces
+ */
+#ifdef RT_USING_SMP
+void rt_hw_context_switch(rt_ubase_t from, rt_ubase_t to, struct rt_thread *to_thread);
+void rt_hw_context_switch_to(rt_ubase_t to, struct rt_thread *to_thread);
+void rt_hw_context_switch_interrupt(void *context, rt_ubase_t from, rt_ubase_t to, struct rt_thread *to_thread);
+#else
+void rt_hw_context_switch(rt_ubase_t from, rt_ubase_t to);
+void rt_hw_context_switch_to(rt_ubase_t to);
+void rt_hw_context_switch_interrupt(rt_ubase_t from, rt_ubase_t to);
+#endif /*RT_USING_SMP*/
+
+void rt_hw_console_output(const char *str);
+
+void rt_hw_backtrace(rt_uint32_t *fp, rt_ubase_t thread_entry);
+void rt_hw_show_memory(rt_uint32_t addr, rt_size_t size);
+
+/*
+ * Exception interfaces
+ */
+void rt_hw_exception_install(rt_err_t (*exception_handle)(void *context));
+
+/*
+ * delay interfaces
+ */
+void rt_hw_us_delay(rt_uint32_t us);
+
+#ifdef RT_USING_SMP
+typedef union {
+ unsigned long slock;
+ struct __arch_tickets {
+ unsigned short owner;
+ unsigned short next;
+ } tickets;
+} rt_hw_spinlock_t;
+
+struct rt_spinlock
+{
+ rt_hw_spinlock_t lock;
+};
+
+void rt_hw_spin_lock_init(rt_hw_spinlock_t *lock);
+void rt_hw_spin_lock(rt_hw_spinlock_t *lock);
+void rt_hw_spin_unlock(rt_hw_spinlock_t *lock);
+
+int rt_hw_cpu_id(void);
+
+extern rt_hw_spinlock_t _cpus_lock;
+extern rt_hw_spinlock_t _rt_critical_lock;
+
+#define __RT_HW_SPIN_LOCK_INITIALIZER(lockname) {0}
+
+#define __RT_HW_SPIN_LOCK_UNLOCKED(lockname) \
+ (rt_hw_spinlock_t) __RT_HW_SPIN_LOCK_INITIALIZER(lockname)
+
+#define RT_DEFINE_SPINLOCK(x) rt_hw_spinlock_t x = __RT_HW_SPIN_LOCK_UNLOCKED(x)
+#define RT_DECLARE_SPINLOCK(x)
+
+/**
+ * ipi function
+ */
+void rt_hw_ipi_send(int ipi_vector, unsigned int cpu_mask);
+
+/**
+ * boot secondary cpu
+ */
+void rt_hw_secondary_cpu_up(void);
+
+/**
+ * secondary cpu idle function
+ */
+void rt_hw_secondary_cpu_idle_exec(void);
+#else
+
+#define RT_DEFINE_SPINLOCK(x)
+#define RT_DECLARE_SPINLOCK(x) rt_ubase_t x
+
+#define rt_hw_spin_lock(lock) *(lock) = rt_hw_interrupt_disable()
+#define rt_hw_spin_unlock(lock) rt_hw_interrupt_enable(*(lock))
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/User/system/rt-thread/include/rtm.h b/User/system/rt-thread/include/rtm.h
new file mode 100644
index 0000000..ec05662
--- /dev/null
+++ b/User/system/rt-thread/include/rtm.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ */
+
+#ifndef __RTM_H__
+#define __RTM_H__
+
+#include
+#include
+
+#ifdef RT_USING_MODULE
+struct rt_module_symtab
+{
+ void *addr;
+ const char *name;
+};
+
+#if defined(_MSC_VER)
+#pragma section("RTMSymTab$f",read)
+#define RTM_EXPORT(symbol) \
+__declspec(allocate("RTMSymTab$f"))const char __rtmsym_##symbol##_name[] = "__vs_rtm_"#symbol;
+#pragma comment(linker, "/merge:RTMSymTab=mytext")
+
+#elif defined(__MINGW32__)
+#define RTM_EXPORT(symbol)
+
+#else
+#define RTM_EXPORT(symbol) \
+const char __rtmsym_##symbol##_name[] RT_SECTION(".rodata.name") = #symbol; \
+const struct rt_module_symtab __rtmsym_##symbol RT_SECTION("RTMSymTab")= \
+{ \
+ (void *)&symbol, \
+ __rtmsym_##symbol##_name \
+};
+#endif
+
+#else
+#define RTM_EXPORT(symbol)
+#endif
+
+#endif
diff --git a/User/system/rt-thread/include/rtservice.h b/User/system/rt-thread/include/rtservice.h
new file mode 100644
index 0000000..1524af1
--- /dev/null
+++ b/User/system/rt-thread/include/rtservice.h
@@ -0,0 +1,315 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2006-03-16 Bernard the first version
+ * 2006-09-07 Bernard move the kservice APIs to rtthread.h
+ * 2007-06-27 Bernard fix the rt_list_remove bug
+ * 2012-03-22 Bernard rename kservice.h to rtservice.h
+ * 2017-11-15 JasonJia Modify rt_slist_foreach to rt_slist_for_each_entry.
+ * Make code cleanup.
+ */
+
+#ifndef __RT_SERVICE_H__
+#define __RT_SERVICE_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @addtogroup KernelService
+ */
+
+/**@{*/
+
+/**
+ * rt_container_of - return the start address of struct type, while ptr is the
+ * member of struct type.
+ */
+#define rt_container_of(ptr, type, member) \
+ ((type *)((char *)(ptr) - (unsigned long)(&((type *)0)->member)))
+
+
+/**
+ * @brief initialize a list object
+ */
+#define RT_LIST_OBJECT_INIT(object) { &(object), &(object) }
+
+/**
+ * @brief initialize a list
+ *
+ * @param l list to be initialized
+ */
+rt_inline void rt_list_init(rt_list_t *l)
+{
+ l->next = l->prev = l;
+}
+
+/**
+ * @brief insert a node after a list
+ *
+ * @param l list to insert it
+ * @param n new node to be inserted
+ */
+rt_inline void rt_list_insert_after(rt_list_t *l, rt_list_t *n)
+{
+ l->next->prev = n;
+ n->next = l->next;
+
+ l->next = n;
+ n->prev = l;
+}
+
+/**
+ * @brief insert a node before a list
+ *
+ * @param n new node to be inserted
+ * @param l list to insert it
+ */
+rt_inline void rt_list_insert_before(rt_list_t *l, rt_list_t *n)
+{
+ l->prev->next = n;
+ n->prev = l->prev;
+
+ l->prev = n;
+ n->next = l;
+}
+
+/**
+ * @brief remove node from list.
+ * @param n the node to remove from the list.
+ */
+rt_inline void rt_list_remove(rt_list_t *n)
+{
+ n->next->prev = n->prev;
+ n->prev->next = n->next;
+
+ n->next = n->prev = n;
+}
+
+/**
+ * @brief tests whether a list is empty
+ * @param l the list to test.
+ */
+rt_inline int rt_list_isempty(const rt_list_t *l)
+{
+ return l->next == l;
+}
+
+/**
+ * @brief get the list length
+ * @param l the list to get.
+ */
+rt_inline unsigned int rt_list_len(const rt_list_t *l)
+{
+ unsigned int len = 0;
+ const rt_list_t *p = l;
+ while (p->next != l)
+ {
+ p = p->next;
+ len ++;
+ }
+
+ return len;
+}
+
+/**
+ * @brief get the struct for this entry
+ * @param node the entry point
+ * @param type the type of structure
+ * @param member the name of list in structure
+ */
+#define rt_list_entry(node, type, member) \
+ rt_container_of(node, type, member)
+
+/**
+ * rt_list_for_each - iterate over a list
+ * @pos: the rt_list_t * to use as a loop cursor.
+ * @head: the head for your list.
+ */
+#define rt_list_for_each(pos, head) \
+ for (pos = (head)->next; pos != (head); pos = pos->next)
+
+/**
+ * rt_list_for_each_safe - iterate over a list safe against removal of list entry
+ * @pos: the rt_list_t * to use as a loop cursor.
+ * @n: another rt_list_t * to use as temporary storage
+ * @head: the head for your list.
+ */
+#define rt_list_for_each_safe(pos, n, head) \
+ for (pos = (head)->next, n = pos->next; pos != (head); \
+ pos = n, n = pos->next)
+
+/**
+ * rt_list_for_each_entry - iterate over list of given type
+ * @pos: the type * to use as a loop cursor.
+ * @head: the head for your list.
+ * @member: the name of the list_struct within the struct.
+ */
+#define rt_list_for_each_entry(pos, head, member) \
+ for (pos = rt_list_entry((head)->next, typeof(*pos), member); \
+ &pos->member != (head); \
+ pos = rt_list_entry(pos->member.next, typeof(*pos), member))
+
+/**
+ * rt_list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
+ * @pos: the type * to use as a loop cursor.
+ * @n: another type * to use as temporary storage
+ * @head: the head for your list.
+ * @member: the name of the list_struct within the struct.
+ */
+#define rt_list_for_each_entry_safe(pos, n, head, member) \
+ for (pos = rt_list_entry((head)->next, typeof(*pos), member), \
+ n = rt_list_entry(pos->member.next, typeof(*pos), member); \
+ &pos->member != (head); \
+ pos = n, n = rt_list_entry(n->member.next, typeof(*n), member))
+
+/**
+ * rt_list_first_entry - get the first element from a list
+ * @ptr: the list head to take the element from.
+ * @type: the type of the struct this is embedded in.
+ * @member: the name of the list_struct within the struct.
+ *
+ * Note, that list is expected to be not empty.
+ */
+#define rt_list_first_entry(ptr, type, member) \
+ rt_list_entry((ptr)->next, type, member)
+
+#define RT_SLIST_OBJECT_INIT(object) { RT_NULL }
+
+/**
+ * @brief initialize a single list
+ *
+ * @param l the single list to be initialized
+ */
+rt_inline void rt_slist_init(rt_slist_t *l)
+{
+ l->next = RT_NULL;
+}
+
+rt_inline void rt_slist_append(rt_slist_t *l, rt_slist_t *n)
+{
+ struct rt_slist_node *node;
+
+ node = l;
+ while (node->next) node = node->next;
+
+ /* append the node to the tail */
+ node->next = n;
+ n->next = RT_NULL;
+}
+
+rt_inline void rt_slist_insert(rt_slist_t *l, rt_slist_t *n)
+{
+ n->next = l->next;
+ l->next = n;
+}
+
+rt_inline unsigned int rt_slist_len(const rt_slist_t *l)
+{
+ unsigned int len = 0;
+ const rt_slist_t *list = l->next;
+ while (list != RT_NULL)
+ {
+ list = list->next;
+ len ++;
+ }
+
+ return len;
+}
+
+rt_inline rt_slist_t *rt_slist_remove(rt_slist_t *l, rt_slist_t *n)
+{
+ /* remove slist head */
+ struct rt_slist_node *node = l;
+ while (node->next && node->next != n) node = node->next;
+
+ /* remove node */
+ if (node->next != (rt_slist_t *)0) node->next = node->next->next;
+
+ return l;
+}
+
+rt_inline rt_slist_t *rt_slist_first(rt_slist_t *l)
+{
+ return l->next;
+}
+
+rt_inline rt_slist_t *rt_slist_tail(rt_slist_t *l)
+{
+ while (l->next) l = l->next;
+
+ return l;
+}
+
+rt_inline rt_slist_t *rt_slist_next(rt_slist_t *n)
+{
+ return n->next;
+}
+
+rt_inline int rt_slist_isempty(rt_slist_t *l)
+{
+ return l->next == RT_NULL;
+}
+
+/**
+ * @brief get the struct for this single list node
+ * @param node the entry point
+ * @param type the type of structure
+ * @param member the name of list in structure
+ */
+#define rt_slist_entry(node, type, member) \
+ rt_container_of(node, type, member)
+
+/**
+ * rt_slist_for_each - iterate over a single list
+ * @pos: the rt_slist_t * to use as a loop cursor.
+ * @head: the head for your single list.
+ */
+#define rt_slist_for_each(pos, head) \
+ for (pos = (head)->next; pos != RT_NULL; pos = pos->next)
+
+/**
+ * rt_slist_for_each_entry - iterate over single list of given type
+ * @pos: the type * to use as a loop cursor.
+ * @head: the head for your single list.
+ * @member: the name of the list_struct within the struct.
+ */
+#define rt_slist_for_each_entry(pos, head, member) \
+ for (pos = rt_slist_entry((head)->next, typeof(*pos), member); \
+ &pos->member != (RT_NULL); \
+ pos = rt_slist_entry(pos->member.next, typeof(*pos), member))
+
+/**
+ * rt_slist_first_entry - get the first element from a slist
+ * @ptr: the slist head to take the element from.
+ * @type: the type of the struct this is embedded in.
+ * @member: the name of the slist_struct within the struct.
+ *
+ * Note, that slist is expected to be not empty.
+ */
+#define rt_slist_first_entry(ptr, type, member) \
+ rt_slist_entry((ptr)->next, type, member)
+
+/**
+ * rt_slist_tail_entry - get the tail element from a slist
+ * @ptr: the slist head to take the element from.
+ * @type: the type of the struct this is embedded in.
+ * @member: the name of the slist_struct within the struct.
+ *
+ * Note, that slist is expected to be not empty.
+ */
+#define rt_slist_tail_entry(ptr, type, member) \
+ rt_slist_entry(rt_slist_tail(ptr), type, member)
+
+/**@}*/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/User/system/rt-thread/include/rtthread.h b/User/system/rt-thread/include/rtthread.h
new file mode 100644
index 0000000..c55720b
--- /dev/null
+++ b/User/system/rt-thread/include/rtthread.h
@@ -0,0 +1,656 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2006-03-18 Bernard the first version
+ * 2006-04-26 Bernard add semaphore APIs
+ * 2006-08-10 Bernard add version information
+ * 2007-01-28 Bernard rename RT_OBJECT_Class_Static to RT_Object_Class_Static
+ * 2007-03-03 Bernard clean up the definitions to rtdef.h
+ * 2010-04-11 yi.qiu add module feature
+ * 2013-06-24 Bernard add rt_kprintf re-define when not use RT_USING_CONSOLE.
+ * 2016-08-09 ArdaFu add new thread and interrupt hook.
+ * 2018-11-22 Jesven add all cpu's lock and ipi handler
+ * 2021-02-28 Meco Man add RT_KSERVICE_USING_STDLIB
+ * 2021-11-14 Meco Man add rtlegacy.h for compatibility
+ * 2022-06-04 Meco Man remove strnlen
+ */
+
+#ifndef __RT_THREAD_H__
+#define __RT_THREAD_H__
+
+#include
+#include
+#include
+#include
+#include
+#ifdef RT_USING_LEGACY
+#include
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @addtogroup KernelObject
+ */
+
+/**@{*/
+
+/*
+ * kernel object interface
+ */
+struct rt_object_information *
+rt_object_get_information(enum rt_object_class_type type);
+int rt_object_get_length(enum rt_object_class_type type);
+int rt_object_get_pointers(enum rt_object_class_type type, rt_object_t *pointers, int maxlen);
+
+void rt_object_init(struct rt_object *object,
+ enum rt_object_class_type type,
+ const char *name);
+void rt_object_detach(rt_object_t object);
+#ifdef RT_USING_HEAP
+rt_object_t rt_object_allocate(enum rt_object_class_type type,
+ const char *name);
+void rt_object_delete(rt_object_t object);
+#endif
+rt_bool_t rt_object_is_systemobject(rt_object_t object);
+rt_uint8_t rt_object_get_type(rt_object_t object);
+rt_object_t rt_object_find(const char *name, rt_uint8_t type);
+
+#ifdef RT_USING_HOOK
+void rt_object_attach_sethook(void (*hook)(struct rt_object *object));
+void rt_object_detach_sethook(void (*hook)(struct rt_object *object));
+void rt_object_trytake_sethook(void (*hook)(struct rt_object *object));
+void rt_object_take_sethook(void (*hook)(struct rt_object *object));
+void rt_object_put_sethook(void (*hook)(struct rt_object *object));
+#endif
+
+/**@}*/
+
+/**
+ * @addtogroup Clock
+ */
+
+/**@{*/
+
+/*
+ * clock & timer interface
+ */
+rt_tick_t rt_tick_get(void);
+void rt_tick_set(rt_tick_t tick);
+void rt_tick_increase(void);
+rt_tick_t rt_tick_from_millisecond(rt_int32_t ms);
+rt_tick_t rt_tick_get_millisecond(void);
+#ifdef RT_USING_HOOK
+void rt_tick_sethook(void (*hook)(void));
+#endif
+
+void rt_system_timer_init(void);
+void rt_system_timer_thread_init(void);
+
+void rt_timer_init(rt_timer_t timer,
+ const char *name,
+ void (*timeout)(void *parameter),
+ void *parameter,
+ rt_tick_t time,
+ rt_uint8_t flag);
+rt_err_t rt_timer_detach(rt_timer_t timer);
+#ifdef RT_USING_HEAP
+rt_timer_t rt_timer_create(const char *name,
+ void (*timeout)(void *parameter),
+ void *parameter,
+ rt_tick_t time,
+ rt_uint8_t flag);
+rt_err_t rt_timer_delete(rt_timer_t timer);
+#endif
+rt_err_t rt_timer_start(rt_timer_t timer);
+rt_err_t rt_timer_stop(rt_timer_t timer);
+rt_err_t rt_timer_control(rt_timer_t timer, int cmd, void *arg);
+
+rt_tick_t rt_timer_next_timeout_tick(void);
+void rt_timer_check(void);
+
+#ifdef RT_USING_HOOK
+void rt_timer_enter_sethook(void (*hook)(struct rt_timer *timer));
+void rt_timer_exit_sethook(void (*hook)(struct rt_timer *timer));
+#endif
+
+/**@}*/
+
+/**
+ * @addtogroup Thread
+ */
+
+/**@{*/
+
+/*
+ * thread interface
+ */
+rt_err_t rt_thread_init(struct rt_thread *thread,
+ const char *name,
+ void (*entry)(void *parameter),
+ void *parameter,
+ void *stack_start,
+ rt_uint32_t stack_size,
+ rt_uint8_t priority,
+ rt_uint32_t tick);
+rt_err_t rt_thread_detach(rt_thread_t thread);
+#ifdef RT_USING_HEAP
+rt_thread_t rt_thread_create(const char *name,
+ void (*entry)(void *parameter),
+ void *parameter,
+ rt_uint32_t stack_size,
+ rt_uint8_t priority,
+ rt_uint32_t tick);
+rt_err_t rt_thread_delete(rt_thread_t thread);
+#endif
+rt_thread_t rt_thread_self(void);
+rt_thread_t rt_thread_find(char *name);
+rt_err_t rt_thread_startup(rt_thread_t thread);
+rt_err_t rt_thread_yield(void);
+rt_err_t rt_thread_delay(rt_tick_t tick);
+rt_err_t rt_thread_delay_until(rt_tick_t *tick, rt_tick_t inc_tick);
+rt_err_t rt_thread_mdelay(rt_int32_t ms);
+rt_err_t rt_thread_control(rt_thread_t thread, int cmd, void *arg);
+rt_err_t rt_thread_suspend(rt_thread_t thread);
+rt_err_t rt_thread_resume(rt_thread_t thread);
+
+#ifdef RT_USING_SIGNALS
+void rt_thread_alloc_sig(rt_thread_t tid);
+void rt_thread_free_sig(rt_thread_t tid);
+int rt_thread_kill(rt_thread_t tid, int sig);
+#endif
+
+#ifdef RT_USING_HOOK
+void rt_thread_suspend_sethook(void (*hook)(rt_thread_t thread));
+void rt_thread_resume_sethook (void (*hook)(rt_thread_t thread));
+void rt_thread_inited_sethook (void (*hook)(rt_thread_t thread));
+#endif
+
+/*
+ * idle thread interface
+ */
+void rt_thread_idle_init(void);
+#if defined(RT_USING_HOOK) || defined(RT_USING_IDLE_HOOK)
+rt_err_t rt_thread_idle_sethook(void (*hook)(void));
+rt_err_t rt_thread_idle_delhook(void (*hook)(void));
+#endif
+rt_thread_t rt_thread_idle_gethandler(void);
+
+/*
+ * schedule service
+ */
+void rt_system_scheduler_init(void);
+void rt_system_scheduler_start(void);
+
+void rt_schedule(void);
+void rt_schedule_insert_thread(struct rt_thread *thread);
+void rt_schedule_remove_thread(struct rt_thread *thread);
+
+void rt_enter_critical(void);
+void rt_exit_critical(void);
+rt_uint16_t rt_critical_level(void);
+
+#ifdef RT_USING_HOOK
+void rt_scheduler_sethook(void (*hook)(rt_thread_t from, rt_thread_t to));
+void rt_scheduler_switch_sethook(void (*hook)(struct rt_thread *tid));
+#endif
+
+#ifdef RT_USING_SMP
+void rt_scheduler_ipi_handler(int vector, void *param);
+#endif
+
+/**@}*/
+
+/**
+ * @addtogroup Signals
+ * @{
+ */
+#ifdef RT_USING_SIGNALS
+void rt_signal_mask(int signo);
+void rt_signal_unmask(int signo);
+rt_sighandler_t rt_signal_install(int signo, rt_sighandler_t handler);
+int rt_signal_wait(const rt_sigset_t *set, rt_siginfo_t *si, rt_int32_t timeout);
+
+int rt_system_signal_init(void);
+#endif
+/*@}*/
+
+/**
+ * @addtogroup MM
+ */
+
+/**@{*/
+
+/*
+ * memory management interface
+ */
+#ifdef RT_USING_MEMPOOL
+/*
+ * memory pool interface
+ */
+rt_err_t rt_mp_init(struct rt_mempool *mp,
+ const char *name,
+ void *start,
+ rt_size_t size,
+ rt_size_t block_size);
+rt_err_t rt_mp_detach(struct rt_mempool *mp);
+#ifdef RT_USING_HEAP
+rt_mp_t rt_mp_create(const char *name,
+ rt_size_t block_count,
+ rt_size_t block_size);
+rt_err_t rt_mp_delete(rt_mp_t mp);
+#endif
+
+void *rt_mp_alloc(rt_mp_t mp, rt_int32_t time);
+void rt_mp_free(void *block);
+
+#ifdef RT_USING_HOOK
+void rt_mp_alloc_sethook(void (*hook)(struct rt_mempool *mp, void *block));
+void rt_mp_free_sethook(void (*hook)(struct rt_mempool *mp, void *block));
+#endif
+
+#endif
+
+#ifdef RT_USING_HEAP
+/*
+ * heap memory interface
+ */
+void rt_system_heap_init(void *begin_addr, void *end_addr);
+
+void *rt_malloc(rt_size_t nbytes);
+void rt_free(void *ptr);
+void *rt_realloc(void *ptr, rt_size_t nbytes);
+void *rt_calloc(rt_size_t count, rt_size_t size);
+void *rt_malloc_align(rt_size_t size, rt_size_t align);
+void rt_free_align(void *ptr);
+
+void rt_memory_info(rt_size_t *total,
+ rt_size_t *used,
+ rt_size_t *max_used);
+
+#if defined(RT_USING_SLAB) && defined(RT_USING_SLAB_AS_HEAP)
+void *rt_page_alloc(rt_size_t npages);
+void rt_page_free(void *addr, rt_size_t npages);
+#endif
+
+#ifdef RT_USING_HOOK
+void rt_malloc_sethook(void (*hook)(void *ptr, rt_size_t size));
+void rt_free_sethook(void (*hook)(void *ptr));
+#endif
+
+#endif
+
+#ifdef RT_USING_SMALL_MEM
+/**
+ * small memory object interface
+ */
+rt_smem_t rt_smem_init(const char *name,
+ void *begin_addr,
+ rt_size_t size);
+rt_err_t rt_smem_detach(rt_smem_t m);
+void *rt_smem_alloc(rt_smem_t m, rt_size_t size);
+void *rt_smem_realloc(rt_smem_t m, void *rmem, rt_size_t newsize);
+void rt_smem_free(void *rmem);
+#endif
+
+#ifdef RT_USING_MEMHEAP
+/**
+ * memory heap object interface
+ */
+rt_err_t rt_memheap_init(struct rt_memheap *memheap,
+ const char *name,
+ void *start_addr,
+ rt_size_t size);
+rt_err_t rt_memheap_detach(struct rt_memheap *heap);
+void *rt_memheap_alloc(struct rt_memheap *heap, rt_size_t size);
+void *rt_memheap_realloc(struct rt_memheap *heap, void *ptr, rt_size_t newsize);
+void rt_memheap_free(void *ptr);
+void rt_memheap_info(struct rt_memheap *heap,
+ rt_size_t *total,
+ rt_size_t *used,
+ rt_size_t *max_used);
+#endif
+
+#ifdef RT_USING_SLAB
+/**
+ * slab object interface
+ */
+rt_slab_t rt_slab_init(const char *name, void *begin_addr, rt_size_t size);
+rt_err_t rt_slab_detach(rt_slab_t m);
+void *rt_slab_page_alloc(rt_slab_t m, rt_size_t npages);
+void rt_slab_page_free(rt_slab_t m, void *addr, rt_size_t npages);
+void *rt_slab_alloc(rt_slab_t m, rt_size_t size);
+void *rt_slab_realloc(rt_slab_t m, void *ptr, rt_size_t size);
+void rt_slab_free(rt_slab_t m, void *ptr);
+#endif
+
+/**@}*/
+
+/**
+ * @addtogroup IPC
+ */
+
+/**@{*/
+
+#ifdef RT_USING_SEMAPHORE
+/*
+ * semaphore interface
+ */
+rt_err_t rt_sem_init(rt_sem_t sem,
+ const char *name,
+ rt_uint32_t value,
+ rt_uint8_t flag);
+rt_err_t rt_sem_detach(rt_sem_t sem);
+#ifdef RT_USING_HEAP
+rt_sem_t rt_sem_create(const char *name, rt_uint32_t value, rt_uint8_t flag);
+rt_err_t rt_sem_delete(rt_sem_t sem);
+#endif
+
+rt_err_t rt_sem_take(rt_sem_t sem, rt_int32_t timeout);
+rt_err_t rt_sem_trytake(rt_sem_t sem);
+rt_err_t rt_sem_release(rt_sem_t sem);
+rt_err_t rt_sem_control(rt_sem_t sem, int cmd, void *arg);
+#endif
+
+#ifdef RT_USING_MUTEX
+/*
+ * mutex interface
+ */
+rt_err_t rt_mutex_init(rt_mutex_t mutex, const char *name, rt_uint8_t flag);
+rt_err_t rt_mutex_detach(rt_mutex_t mutex);
+#ifdef RT_USING_HEAP
+rt_mutex_t rt_mutex_create(const char *name, rt_uint8_t flag);
+rt_err_t rt_mutex_delete(rt_mutex_t mutex);
+#endif
+
+rt_err_t rt_mutex_take(rt_mutex_t mutex, rt_int32_t timeout);
+rt_err_t rt_mutex_trytake(rt_mutex_t mutex);
+rt_err_t rt_mutex_release(rt_mutex_t mutex);
+rt_err_t rt_mutex_control(rt_mutex_t mutex, int cmd, void *arg);
+#endif
+
+#ifdef RT_USING_EVENT
+/*
+ * event interface
+ */
+rt_err_t rt_event_init(rt_event_t event, const char *name, rt_uint8_t flag);
+rt_err_t rt_event_detach(rt_event_t event);
+#ifdef RT_USING_HEAP
+rt_event_t rt_event_create(const char *name, rt_uint8_t flag);
+rt_err_t rt_event_delete(rt_event_t event);
+#endif
+
+rt_err_t rt_event_send(rt_event_t event, rt_uint32_t set);
+rt_err_t rt_event_recv(rt_event_t event,
+ rt_uint32_t set,
+ rt_uint8_t opt,
+ rt_int32_t timeout,
+ rt_uint32_t *recved);
+rt_err_t rt_event_control(rt_event_t event, int cmd, void *arg);
+#endif
+
+#ifdef RT_USING_MAILBOX
+/*
+ * mailbox interface
+ */
+rt_err_t rt_mb_init(rt_mailbox_t mb,
+ const char *name,
+ void *msgpool,
+ rt_size_t size,
+ rt_uint8_t flag);
+rt_err_t rt_mb_detach(rt_mailbox_t mb);
+#ifdef RT_USING_HEAP
+rt_mailbox_t rt_mb_create(const char *name, rt_size_t size, rt_uint8_t flag);
+rt_err_t rt_mb_delete(rt_mailbox_t mb);
+#endif
+
+rt_err_t rt_mb_send(rt_mailbox_t mb, rt_ubase_t value);
+rt_err_t rt_mb_send_wait(rt_mailbox_t mb,
+ rt_ubase_t value,
+ rt_int32_t timeout);
+rt_err_t rt_mb_urgent(rt_mailbox_t mb, rt_ubase_t value);
+rt_err_t rt_mb_recv(rt_mailbox_t mb, rt_ubase_t *value, rt_int32_t timeout);
+rt_err_t rt_mb_control(rt_mailbox_t mb, int cmd, void *arg);
+#endif
+
+#ifdef RT_USING_MESSAGEQUEUE
+/*
+ * message queue interface
+ */
+rt_err_t rt_mq_init(rt_mq_t mq,
+ const char *name,
+ void *msgpool,
+ rt_size_t msg_size,
+ rt_size_t pool_size,
+ rt_uint8_t flag);
+rt_err_t rt_mq_detach(rt_mq_t mq);
+#ifdef RT_USING_HEAP
+rt_mq_t rt_mq_create(const char *name,
+ rt_size_t msg_size,
+ rt_size_t max_msgs,
+ rt_uint8_t flag);
+rt_err_t rt_mq_delete(rt_mq_t mq);
+#endif
+
+rt_err_t rt_mq_send(rt_mq_t mq, const void *buffer, rt_size_t size);
+rt_err_t rt_mq_send_wait(rt_mq_t mq,
+ const void *buffer,
+ rt_size_t size,
+ rt_int32_t timeout);
+rt_err_t rt_mq_urgent(rt_mq_t mq, const void *buffer, rt_size_t size);
+rt_err_t rt_mq_recv(rt_mq_t mq,
+ void *buffer,
+ rt_size_t size,
+ rt_int32_t timeout);
+rt_err_t rt_mq_control(rt_mq_t mq, int cmd, void *arg);
+#endif
+
+/* defunct */
+void rt_thread_defunct_enqueue(rt_thread_t thread);
+rt_thread_t rt_thread_defunct_dequeue(void);
+
+/*
+ * spinlock
+ */
+#ifdef RT_USING_SMP
+struct rt_spinlock;
+
+void rt_spin_lock_init(struct rt_spinlock *lock);
+void rt_spin_lock(struct rt_spinlock *lock);
+void rt_spin_unlock(struct rt_spinlock *lock);
+rt_base_t rt_spin_lock_irqsave(struct rt_spinlock *lock);
+void rt_spin_unlock_irqrestore(struct rt_spinlock *lock, rt_base_t level);
+
+#else
+#define rt_spin_lock_init(lock) /* nothing */
+#define rt_spin_lock(lock) rt_enter_critical()
+#define rt_spin_unlock(lock) rt_exit_critical()
+#define rt_spin_lock_irqsave(lock) rt_hw_interrupt_disable()
+#define rt_spin_unlock_irqrestore(lock, level) rt_hw_interrupt_enable(level)
+
+#endif
+
+/**@}*/
+
+#ifdef RT_USING_DEVICE
+/**
+ * @addtogroup Device
+ */
+
+/**@{*/
+
+/*
+ * device (I/O) system interface
+ */
+rt_device_t rt_device_find(const char *name);
+
+rt_err_t rt_device_register(rt_device_t dev,
+ const char *name,
+ rt_uint16_t flags);
+rt_err_t rt_device_unregister(rt_device_t dev);
+
+#ifdef RT_USING_HEAP
+rt_device_t rt_device_create(int type, int attach_size);
+void rt_device_destroy(rt_device_t device);
+#endif
+
+rt_err_t
+rt_device_set_rx_indicate(rt_device_t dev,
+ rt_err_t (*rx_ind)(rt_device_t dev, rt_size_t size));
+rt_err_t
+rt_device_set_tx_complete(rt_device_t dev,
+ rt_err_t (*tx_done)(rt_device_t dev, void *buffer));
+
+rt_err_t rt_device_init (rt_device_t dev);
+rt_err_t rt_device_open (rt_device_t dev, rt_uint16_t oflag);
+rt_err_t rt_device_close(rt_device_t dev);
+rt_size_t rt_device_read (rt_device_t dev,
+ rt_off_t pos,
+ void *buffer,
+ rt_size_t size);
+rt_size_t rt_device_write(rt_device_t dev,
+ rt_off_t pos,
+ const void *buffer,
+ rt_size_t size);
+rt_err_t rt_device_control(rt_device_t dev, int cmd, void *arg);
+
+/**@}*/
+#endif
+
+/*
+ * interrupt service
+ */
+
+/*
+ * rt_interrupt_enter and rt_interrupt_leave only can be called by BSP
+ */
+void rt_interrupt_enter(void);
+void rt_interrupt_leave(void);
+
+#ifdef RT_USING_SMP
+
+/*
+ * smp cpus lock service
+ */
+
+rt_base_t rt_cpus_lock(void);
+void rt_cpus_unlock(rt_base_t level);
+
+struct rt_cpu *rt_cpu_self(void);
+struct rt_cpu *rt_cpu_index(int index);
+
+#endif
+
+/*
+ * the number of nested interrupts.
+ */
+rt_uint8_t rt_interrupt_get_nest(void);
+
+#ifdef RT_USING_HOOK
+void rt_interrupt_enter_sethook(void (*hook)(void));
+void rt_interrupt_leave_sethook(void (*hook)(void));
+#endif
+
+#ifdef RT_USING_COMPONENTS_INIT
+void rt_components_init(void);
+void rt_components_board_init(void);
+#endif
+
+/**
+ * @addtogroup KernelService
+ */
+
+/**@{*/
+
+/*
+ * general kernel service
+ */
+#ifndef RT_USING_CONSOLE
+#define rt_kprintf(...)
+#define rt_kputs(str)
+#else
+int rt_kprintf(const char *fmt, ...);
+void rt_kputs(const char *str);
+#endif
+
+int rt_vsprintf(char *dest, const char *format, va_list arg_ptr);
+int rt_vsnprintf(char *buf, rt_size_t size, const char *fmt, va_list args);
+int rt_sprintf(char *buf, const char *format, ...);
+int rt_snprintf(char *buf, rt_size_t size, const char *format, ...);
+
+#if defined(RT_USING_DEVICE) && defined(RT_USING_CONSOLE)
+rt_device_t rt_console_set_device(const char *name);
+rt_device_t rt_console_get_device(void);
+#endif
+
+rt_err_t rt_get_errno(void);
+void rt_set_errno(rt_err_t no);
+int *_rt_errno(void);
+const char *rt_strerror(rt_err_t error);
+#if !defined(RT_USING_NEWLIB) && !defined(_WIN32)
+#ifndef errno
+#define errno *_rt_errno()
+#endif
+#endif
+
+int __rt_ffs(int value);
+
+#ifndef RT_KSERVICE_USING_STDLIB_MEMORY
+void *rt_memset(void *src, int c, rt_ubase_t n);
+void *rt_memcpy(void *dest, const void *src, rt_ubase_t n);
+void *rt_memmove(void *dest, const void *src, rt_size_t n);
+rt_int32_t rt_memcmp(const void *cs, const void *ct, rt_size_t count);
+#endif /* RT_KSERVICE_USING_STDLIB_MEMORY */
+char *rt_strdup(const char *s);
+rt_size_t rt_strnlen(const char *s, rt_ubase_t maxlen);
+#ifndef RT_KSERVICE_USING_STDLIB
+char *rt_strstr(const char *str1, const char *str2);
+rt_int32_t rt_strcasecmp(const char *a, const char *b);
+char *rt_strcpy(char *dst, const char *src);
+char *rt_strncpy(char *dest, const char *src, rt_size_t n);
+rt_int32_t rt_strncmp(const char *cs, const char *ct, rt_size_t count);
+rt_int32_t rt_strcmp(const char *cs, const char *ct);
+rt_size_t rt_strlen(const char *src);
+#else
+#include
+#ifdef RT_KSERVICE_USING_STDLIB_MEMORY
+#define rt_memset(s, c, count) memset(s, c, count)
+#define rt_memcpy(dst, src, count) memcpy(dst, src, count)
+#define rt_memmove(dest, src, n) memmove(dest, src, n)
+#define rt_memcmp(cs, ct, count) memcmp(cs, ct, count)
+#endif /* RT_KSERVICE_USING_STDLIB_MEMORY */
+#define rt_strstr(str1, str2) strstr(str1, str2)
+#define rt_strcasecmp(a, b) strcasecmp(a, b)
+#define rt_strcpy(dest, src) strcpy(dest, src)
+#define rt_strncpy(dest, src, n) strncpy(dest, src, n)
+#define rt_strncmp(cs, ct, count) strncmp(cs, ct, count)
+#define rt_strcmp(cs, ct) strcmp(cs, ct)
+#define rt_strlen(src) strlen(src)
+#endif /*RT_KSERVICE_USING_STDLIB*/
+
+void rt_show_version(void);
+
+#ifdef RT_DEBUG
+extern void (*rt_assert_hook)(const char *ex, const char *func, rt_size_t line);
+void rt_assert_set_hook(void (*hook)(const char *ex, const char *func, rt_size_t line));
+
+void rt_assert_handler(const char *ex, const char *func, rt_size_t line);
+#endif /* RT_DEBUG */
+
+#ifdef RT_USING_FINSH
+#include
+#endif
+
+/**@}*/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/User/system/rt-thread/libcpu/cortex-m4/context_gcc.S b/User/system/rt-thread/libcpu/cortex-m4/context_gcc.S
new file mode 100644
index 0000000..5088e40
--- /dev/null
+++ b/User/system/rt-thread/libcpu/cortex-m4/context_gcc.S
@@ -0,0 +1,253 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2009-10-11 Bernard first version
+ * 2012-01-01 aozima support context switch load/store FPU register.
+ * 2013-06-18 aozima add restore MSP feature.
+ * 2013-06-23 aozima support lazy stack optimized.
+ * 2018-07-24 aozima enhancement hard fault exception handler.
+ */
+
+/**
+ * @addtogroup cortex-m4
+ */
+/*@{*/
+
+.cpu cortex-m4
+.syntax unified
+.thumb
+.text
+
+.equ SCB_VTOR, 0xE000ED08 /* Vector Table Offset Register */
+.equ NVIC_INT_CTRL, 0xE000ED04 /* interrupt control state register */
+.equ NVIC_SYSPRI2, 0xE000ED20 /* system priority register (2) */
+.equ NVIC_PENDSV_PRI, 0xFFFF0000 /* PendSV and SysTick priority value (lowest) */
+.equ NVIC_PENDSVSET, 0x10000000 /* value to trigger PendSV exception */
+
+/*
+ * rt_base_t rt_hw_interrupt_disable();
+ */
+.global rt_hw_interrupt_disable
+.type rt_hw_interrupt_disable, %function
+rt_hw_interrupt_disable:
+ MRS r0, PRIMASK
+ CPSID I
+ BX LR
+
+/*
+ * void rt_hw_interrupt_enable(rt_base_t level);
+ */
+.global rt_hw_interrupt_enable
+.type rt_hw_interrupt_enable, %function
+rt_hw_interrupt_enable:
+ MSR PRIMASK, r0
+ BX LR
+
+/*
+ * void rt_hw_context_switch(rt_uint32 from, rt_uint32 to);
+ * r0 --> from
+ * r1 --> to
+ */
+.global rt_hw_context_switch_interrupt
+.type rt_hw_context_switch_interrupt, %function
+.global rt_hw_context_switch
+.type rt_hw_context_switch, %function
+
+rt_hw_context_switch_interrupt:
+rt_hw_context_switch:
+ /* set rt_thread_switch_interrupt_flag to 1 */
+ LDR r2, =rt_thread_switch_interrupt_flag
+ LDR r3, [r2]
+ CMP r3, #1
+ BEQ _reswitch
+ MOV r3, #1
+ STR r3, [r2]
+
+ LDR r2, =rt_interrupt_from_thread /* set rt_interrupt_from_thread */
+ STR r0, [r2]
+
+_reswitch:
+ LDR r2, =rt_interrupt_to_thread /* set rt_interrupt_to_thread */
+ STR r1, [r2]
+
+ LDR r0, =NVIC_INT_CTRL /* trigger the PendSV exception (causes context switch) */
+ LDR r1, =NVIC_PENDSVSET
+ STR r1, [r0]
+ BX LR
+
+/* r0 --> switch from thread stack
+ * r1 --> switch to thread stack
+ * psr, pc, lr, r12, r3, r2, r1, r0 are pushed into [from] stack
+ */
+.global PendSV_Handler
+.type PendSV_Handler, %function
+PendSV_Handler:
+ /* disable interrupt to protect context switch */
+ MRS r2, PRIMASK
+ CPSID I
+
+ /* get rt_thread_switch_interrupt_flag */
+ LDR r0, =rt_thread_switch_interrupt_flag
+ LDR r1, [r0]
+ CBZ r1, pendsv_exit /* pendsv already handled */
+
+ /* clear rt_thread_switch_interrupt_flag to 0 */
+ MOV r1, #0x00
+ STR r1, [r0]
+
+ LDR r0, =rt_interrupt_from_thread
+ LDR r1, [r0]
+ CBZ r1, switch_to_thread /* skip register save at the first time */
+
+ MRS r1, psp /* get from thread stack pointer */
+
+#if defined (__VFP_FP__) && !defined(__SOFTFP__)
+ TST lr, #0x10 /* if(!EXC_RETURN[4]) */
+ IT EQ
+ VSTMDBEQ r1!, {d8 - d15} /* push FPU register s16~s31 */
+#endif
+
+ STMFD r1!, {r4 - r11} /* push r4 - r11 register */
+
+#if defined (__VFP_FP__) && !defined(__SOFTFP__)
+ MOV r4, #0x00 /* flag = 0 */
+
+ TST lr, #0x10 /* if(!EXC_RETURN[4]) */
+ IT EQ
+ MOVEQ r4, #0x01 /* flag = 1 */
+
+ STMFD r1!, {r4} /* push flag */
+#endif
+
+ LDR r0, [r0]
+ STR r1, [r0] /* update from thread stack pointer */
+
+switch_to_thread:
+ LDR r1, =rt_interrupt_to_thread
+ LDR r1, [r1]
+ LDR r1, [r1] /* load thread stack pointer */
+
+#if defined (__VFP_FP__) && !defined(__SOFTFP__)
+ LDMFD r1!, {r3} /* pop flag */
+#endif
+
+ LDMFD r1!, {r4 - r11} /* pop r4 - r11 register */
+
+#if defined (__VFP_FP__) && !defined(__SOFTFP__)
+ CMP r3, #0 /* if(flag_r3 != 0) */
+ IT NE
+ VLDMIANE r1!, {d8 - d15} /* pop FPU register s16~s31 */
+#endif
+
+ MSR psp, r1 /* update stack pointer */
+
+#if defined (__VFP_FP__) && !defined(__SOFTFP__)
+ ORR lr, lr, #0x10 /* lr |= (1 << 4), clean FPCA. */
+ CMP r3, #0 /* if(flag_r3 != 0) */
+ IT NE
+ BICNE lr, lr, #0x10 /* lr &= ~(1 << 4), set FPCA. */
+#endif
+
+pendsv_exit:
+ /* restore interrupt */
+ MSR PRIMASK, r2
+
+ ORR lr, lr, #0x04
+ BX lr
+
+/*
+ * void rt_hw_context_switch_to(rt_uint32 to);
+ * r0 --> to
+ */
+.global rt_hw_context_switch_to
+.type rt_hw_context_switch_to, %function
+rt_hw_context_switch_to:
+ LDR r1, =rt_interrupt_to_thread
+ STR r0, [r1]
+
+#if defined (__VFP_FP__) && !defined(__SOFTFP__)
+ /* CLEAR CONTROL.FPCA */
+ MRS r2, CONTROL /* read */
+ BIC r2, #0x04 /* modify */
+ MSR CONTROL, r2 /* write-back */
+#endif
+
+ /* set from thread to 0 */
+ LDR r1, =rt_interrupt_from_thread
+ MOV r0, #0x0
+ STR r0, [r1]
+
+ /* set interrupt flag to 1 */
+ LDR r1, =rt_thread_switch_interrupt_flag
+ MOV r0, #1
+ STR r0, [r1]
+
+ /* set the PendSV and SysTick exception priority */
+ LDR r0, =NVIC_SYSPRI2
+ LDR r1, =NVIC_PENDSV_PRI
+ LDR.W r2, [r0,#0x00] /* read */
+ ORR r1,r1,r2 /* modify */
+ STR r1, [r0] /* write-back */
+
+ LDR r0, =NVIC_INT_CTRL /* trigger the PendSV exception (causes context switch) */
+ LDR r1, =NVIC_PENDSVSET
+ STR r1, [r0]
+
+ /* restore MSP */
+ LDR r0, =SCB_VTOR
+ LDR r0, [r0]
+ LDR r0, [r0]
+ NOP
+ MSR msp, r0
+
+ /* enable interrupts at processor level */
+ CPSIE F
+ CPSIE I
+
+ /* ensure PendSV exception taken place before subsequent operation */
+ DSB
+ ISB
+
+ /* never reach here! */
+
+/* compatible with old version */
+.global rt_hw_interrupt_thread_switch
+.type rt_hw_interrupt_thread_switch, %function
+rt_hw_interrupt_thread_switch:
+ BX lr
+ NOP
+
+.global HardFault_Handler
+.type HardFault_Handler, %function
+HardFault_Handler:
+ /* get current context */
+ MRS r0, msp /* get fault context from handler. */
+ TST lr, #0x04 /* if(!EXC_RETURN[2]) */
+ BEQ _get_sp_done
+ MRS r0, psp /* get fault context from thread. */
+_get_sp_done:
+
+ STMFD r0!, {r4 - r11} /* push r4 - r11 register */
+#if defined (__VFP_FP__) && !defined(__SOFTFP__)
+ STMFD r0!, {lr} /* push dummy for flag */
+#endif
+ STMFD r0!, {lr} /* push exec_return register */
+
+ TST lr, #0x04 /* if(!EXC_RETURN[2]) */
+ BEQ _update_msp
+ MSR psp, r0 /* update stack pointer to PSP. */
+ B _update_done
+_update_msp:
+ MSR msp, r0 /* update stack pointer to MSP. */
+_update_done:
+
+ PUSH {LR}
+ BL rt_hw_hard_fault_exception
+ POP {LR}
+
+ ORR lr, lr, #0x04
+ BX lr
diff --git a/User/system/rt-thread/libcpu/cortex-m4/context_iar.S b/User/system/rt-thread/libcpu/cortex-m4/context_iar.S
new file mode 100644
index 0000000..30be2b7
--- /dev/null
+++ b/User/system/rt-thread/libcpu/cortex-m4/context_iar.S
@@ -0,0 +1,257 @@
+;/*
+; * Copyright (c) 2006-2018, RT-Thread Development Team
+; *
+; * SPDX-License-Identifier: Apache-2.0
+; *
+; * Change Logs:
+; * Date Author Notes
+; * 2009-01-17 Bernard first version
+; * 2009-09-27 Bernard add protect when contex switch occurs
+; * 2012-01-01 aozima support context switch load/store FPU register.
+; * 2013-06-18 aozima add restore MSP feature.
+; * 2013-06-23 aozima support lazy stack optimized.
+; * 2018-07-24 aozima enhancement hard fault exception handler.
+; */
+
+;/**
+; * @addtogroup cortex-m4
+; */
+;/*@{*/
+
+SCB_VTOR EQU 0xE000ED08 ; Vector Table Offset Register
+NVIC_INT_CTRL EQU 0xE000ED04 ; interrupt control state register
+NVIC_SYSPRI2 EQU 0xE000ED20 ; system priority register (2)
+NVIC_PENDSV_PRI EQU 0xFFFF0000 ; PendSV and SysTick priority value (lowest)
+NVIC_PENDSVSET EQU 0x10000000 ; value to trigger PendSV exception
+
+ SECTION .text:CODE(2)
+ THUMB
+ REQUIRE8
+ PRESERVE8
+
+ IMPORT rt_thread_switch_interrupt_flag
+ IMPORT rt_interrupt_from_thread
+ IMPORT rt_interrupt_to_thread
+
+;/*
+; * rt_base_t rt_hw_interrupt_disable();
+; */
+ EXPORT rt_hw_interrupt_disable
+rt_hw_interrupt_disable:
+ MRS r0, PRIMASK
+ CPSID I
+ BX LR
+
+;/*
+; * void rt_hw_interrupt_enable(rt_base_t level);
+; */
+ EXPORT rt_hw_interrupt_enable
+rt_hw_interrupt_enable:
+ MSR PRIMASK, r0
+ BX LR
+
+;/*
+; * void rt_hw_context_switch(rt_uint32 from, rt_uint32 to);
+; * r0 --> from
+; * r1 --> to
+; */
+ EXPORT rt_hw_context_switch_interrupt
+ EXPORT rt_hw_context_switch
+rt_hw_context_switch_interrupt:
+rt_hw_context_switch:
+ ; set rt_thread_switch_interrupt_flag to 1
+ LDR r2, =rt_thread_switch_interrupt_flag
+ LDR r3, [r2]
+ CMP r3, #1
+ BEQ _reswitch
+ MOV r3, #1
+ STR r3, [r2]
+
+ LDR r2, =rt_interrupt_from_thread ; set rt_interrupt_from_thread
+ STR r0, [r2]
+
+_reswitch
+ LDR r2, =rt_interrupt_to_thread ; set rt_interrupt_to_thread
+ STR r1, [r2]
+
+ LDR r0, =NVIC_INT_CTRL ; trigger the PendSV exception (causes context switch)
+ LDR r1, =NVIC_PENDSVSET
+ STR r1, [r0]
+ BX LR
+
+; r0 --> switch from thread stack
+; r1 --> switch to thread stack
+; psr, pc, lr, r12, r3, r2, r1, r0 are pushed into [from] stack
+ EXPORT PendSV_Handler
+PendSV_Handler:
+
+ ; disable interrupt to protect context switch
+ MRS r2, PRIMASK
+ CPSID I
+
+ ; get rt_thread_switch_interrupt_flag
+ LDR r0, =rt_thread_switch_interrupt_flag
+ LDR r1, [r0]
+ CBZ r1, pendsv_exit ; pendsv already handled
+
+ ; clear rt_thread_switch_interrupt_flag to 0
+ MOV r1, #0x00
+ STR r1, [r0]
+
+ LDR r0, =rt_interrupt_from_thread
+ LDR r1, [r0]
+ CBZ r1, switch_to_thread ; skip register save at the first time
+
+ MRS r1, psp ; get from thread stack pointer
+
+#if defined ( __ARMVFP__ )
+ TST lr, #0x10 ; if(!EXC_RETURN[4])
+ BNE skip_push_fpu
+ VSTMDB r1!, {d8 - d15} ; push FPU register s16~s31
+skip_push_fpu
+#endif
+
+ STMFD r1!, {r4 - r11} ; push r4 - r11 register
+
+#if defined ( __ARMVFP__ )
+ MOV r4, #0x00 ; flag = 0
+ TST lr, #0x10 ; if(!EXC_RETURN[4])
+ BNE push_flag
+ MOV r4, #0x01 ; flag = 1
+push_flag
+ ;STMFD r1!, {r4} ; push flag
+ SUB r1, r1, #0x04
+ STR r4, [r1]
+#endif
+
+ LDR r0, [r0]
+ STR r1, [r0] ; update from thread stack pointer
+
+switch_to_thread
+ LDR r1, =rt_interrupt_to_thread
+ LDR r1, [r1]
+ LDR r1, [r1] ; load thread stack pointer
+
+#if defined ( __ARMVFP__ )
+ LDMFD r1!, {r3} ; pop flag
+#endif
+
+ LDMFD r1!, {r4 - r11} ; pop r4 - r11 register
+
+#if defined ( __ARMVFP__ )
+ CBZ r3, skip_pop_fpu
+ VLDMIA r1!, {d8 - d15} ; pop FPU register s16~s31
+skip_pop_fpu
+#endif
+
+ MSR psp, r1 ; update stack pointer
+
+#if defined ( __ARMVFP__ )
+ ORR lr, lr, #0x10 ; lr |= (1 << 4), clean FPCA.
+ CBZ r3, return_without_fpu ; if(flag_r3 != 0)
+ BIC lr, lr, #0x10 ; lr &= ~(1 << 4), set FPCA.
+return_without_fpu
+#endif
+
+pendsv_exit
+ ; restore interrupt
+ MSR PRIMASK, r2
+
+ ORR lr, lr, #0x04
+ BX lr
+
+;/*
+; * void rt_hw_context_switch_to(rt_uint32 to);
+; * r0 --> to
+; */
+ EXPORT rt_hw_context_switch_to
+rt_hw_context_switch_to:
+ LDR r1, =rt_interrupt_to_thread
+ STR r0, [r1]
+
+#if defined ( __ARMVFP__ )
+ ; CLEAR CONTROL.FPCA
+ MRS r2, CONTROL ; read
+ BIC r2, r2, #0x04 ; modify
+ MSR CONTROL, r2 ; write-back
+#endif
+
+ ; set from thread to 0
+ LDR r1, =rt_interrupt_from_thread
+ MOV r0, #0x0
+ STR r0, [r1]
+
+ ; set interrupt flag to 1
+ LDR r1, =rt_thread_switch_interrupt_flag
+ MOV r0, #1
+ STR r0, [r1]
+
+ ; set the PendSV and SysTick exception priority
+ LDR r0, =NVIC_SYSPRI2
+ LDR r1, =NVIC_PENDSV_PRI
+ LDR.W r2, [r0,#0x00] ; read
+ ORR r1,r1,r2 ; modify
+ STR r1, [r0] ; write-back
+
+ LDR r0, =NVIC_INT_CTRL ; trigger the PendSV exception (causes context switch)
+ LDR r1, =NVIC_PENDSVSET
+ STR r1, [r0]
+
+ ; restore MSP
+ LDR r0, =SCB_VTOR
+ LDR r0, [r0]
+ LDR r0, [r0]
+ NOP
+ MSR msp, r0
+
+ ; enable interrupts at processor level
+ CPSIE F
+ CPSIE I
+
+ ; ensure PendSV exception taken place before subsequent operation
+ DSB
+ ISB
+
+ ; never reach here!
+
+; compatible with old version
+ EXPORT rt_hw_interrupt_thread_switch
+rt_hw_interrupt_thread_switch:
+ BX lr
+
+ IMPORT rt_hw_hard_fault_exception
+ EXPORT HardFault_Handler
+HardFault_Handler:
+
+ ; get current context
+ MRS r0, msp ; get fault context from handler.
+ TST lr, #0x04 ; if(!EXC_RETURN[2])
+ BEQ _get_sp_done
+ MRS r0, psp ; get fault context from thread.
+_get_sp_done
+
+ STMFD r0!, {r4 - r11} ; push r4 - r11 register
+ ;STMFD r0!, {lr} ; push exec_return register
+#if defined ( __ARMVFP__ )
+ SUB r0, r0, #0x04 ; push dummy for flag
+ STR lr, [r0]
+#endif
+ SUB r0, r0, #0x04
+ STR lr, [r0]
+
+ TST lr, #0x04 ; if(!EXC_RETURN[2])
+ BEQ _update_msp
+ MSR psp, r0 ; update stack pointer to PSP.
+ B _update_done
+_update_msp
+ MSR msp, r0 ; update stack pointer to MSP.
+_update_done
+
+ PUSH {lr}
+ BL rt_hw_hard_fault_exception
+ POP {lr}
+
+ ORR lr, lr, #0x04
+ BX lr
+
+ END
diff --git a/User/system/rt-thread/libcpu/cortex-m4/context_rvds.S b/User/system/rt-thread/libcpu/cortex-m4/context_rvds.S
new file mode 100644
index 0000000..018e425
--- /dev/null
+++ b/User/system/rt-thread/libcpu/cortex-m4/context_rvds.S
@@ -0,0 +1,255 @@
+;/*
+;* Copyright (c) 2006-2018, RT-Thread Development Team
+;*
+;* SPDX-License-Identifier: Apache-2.0
+;*
+; * Change Logs:
+; * Date Author Notes
+; * 2009-01-17 Bernard first version.
+; * 2012-01-01 aozima support context switch load/store FPU register.
+; * 2013-06-18 aozima add restore MSP feature.
+; * 2013-06-23 aozima support lazy stack optimized.
+; * 2018-07-24 aozima enhancement hard fault exception handler.
+; */
+
+;/**
+; * @addtogroup cortex-m4
+; */
+;/*@{*/
+
+SCB_VTOR EQU 0xE000ED08 ; Vector Table Offset Register
+NVIC_INT_CTRL EQU 0xE000ED04 ; interrupt control state register
+NVIC_SYSPRI2 EQU 0xE000ED20 ; system priority register (2)
+NVIC_PENDSV_PRI EQU 0xFFFF0000 ; PendSV and SysTick priority value (lowest)
+NVIC_PENDSVSET EQU 0x10000000 ; value to trigger PendSV exception
+
+ AREA |.text|, CODE, READONLY, ALIGN=2
+ THUMB
+ REQUIRE8
+ PRESERVE8
+
+ IMPORT rt_thread_switch_interrupt_flag
+ IMPORT rt_interrupt_from_thread
+ IMPORT rt_interrupt_to_thread
+
+;/*
+; * rt_base_t rt_hw_interrupt_disable();
+; */
+rt_hw_interrupt_disable PROC
+ EXPORT rt_hw_interrupt_disable
+ MRS r0, PRIMASK
+ CPSID I
+ BX LR
+ ENDP
+
+;/*
+; * void rt_hw_interrupt_enable(rt_base_t level);
+; */
+rt_hw_interrupt_enable PROC
+ EXPORT rt_hw_interrupt_enable
+ MSR PRIMASK, r0
+ BX LR
+ ENDP
+
+;/*
+; * void rt_hw_context_switch(rt_uint32 from, rt_uint32 to);
+; * r0 --> from
+; * r1 --> to
+; */
+rt_hw_context_switch_interrupt
+ EXPORT rt_hw_context_switch_interrupt
+rt_hw_context_switch PROC
+ EXPORT rt_hw_context_switch
+
+ ; set rt_thread_switch_interrupt_flag to 1
+ LDR r2, =rt_thread_switch_interrupt_flag
+ LDR r3, [r2]
+ CMP r3, #1
+ BEQ _reswitch
+ MOV r3, #1
+ STR r3, [r2]
+
+ LDR r2, =rt_interrupt_from_thread ; set rt_interrupt_from_thread
+ STR r0, [r2]
+
+_reswitch
+ LDR r2, =rt_interrupt_to_thread ; set rt_interrupt_to_thread
+ STR r1, [r2]
+
+ LDR r0, =NVIC_INT_CTRL ; trigger the PendSV exception (causes context switch)
+ LDR r1, =NVIC_PENDSVSET
+ STR r1, [r0]
+ BX LR
+ ENDP
+
+; r0 --> switch from thread stack
+; r1 --> switch to thread stack
+; psr, pc, lr, r12, r3, r2, r1, r0 are pushed into [from] stack
+PendSV_Handler PROC
+ EXPORT PendSV_Handler
+
+ ; disable interrupt to protect context switch
+ MRS r2, PRIMASK
+ CPSID I
+
+ ; get rt_thread_switch_interrupt_flag
+ LDR r0, =rt_thread_switch_interrupt_flag
+ LDR r1, [r0]
+ CBZ r1, pendsv_exit ; pendsv already handled
+
+ ; clear rt_thread_switch_interrupt_flag to 0
+ MOV r1, #0x00
+ STR r1, [r0]
+
+ LDR r0, =rt_interrupt_from_thread
+ LDR r1, [r0]
+ CBZ r1, switch_to_thread ; skip register save at the first time
+
+ MRS r1, psp ; get from thread stack pointer
+
+ IF {FPU} != "SoftVFP"
+ TST lr, #0x10 ; if(!EXC_RETURN[4])
+ VSTMFDEQ r1!, {d8 - d15} ; push FPU register s16~s31
+ ENDIF
+
+ STMFD r1!, {r4 - r11} ; push r4 - r11 register
+
+ IF {FPU} != "SoftVFP"
+ MOV r4, #0x00 ; flag = 0
+
+ TST lr, #0x10 ; if(!EXC_RETURN[4])
+ MOVEQ r4, #0x01 ; flag = 1
+
+ STMFD r1!, {r4} ; push flag
+ ENDIF
+
+ LDR r0, [r0]
+ STR r1, [r0] ; update from thread stack pointer
+
+switch_to_thread
+ LDR r1, =rt_interrupt_to_thread
+ LDR r1, [r1]
+ LDR r1, [r1] ; load thread stack pointer
+
+ IF {FPU} != "SoftVFP"
+ LDMFD r1!, {r3} ; pop flag
+ ENDIF
+
+ LDMFD r1!, {r4 - r11} ; pop r4 - r11 register
+
+ IF {FPU} != "SoftVFP"
+ CMP r3, #0 ; if(flag_r3 != 0)
+ VLDMFDNE r1!, {d8 - d15} ; pop FPU register s16~s31
+ ENDIF
+
+ MSR psp, r1 ; update stack pointer
+
+ IF {FPU} != "SoftVFP"
+ ORR lr, lr, #0x10 ; lr |= (1 << 4), clean FPCA.
+ CMP r3, #0 ; if(flag_r3 != 0)
+ BICNE lr, lr, #0x10 ; lr &= ~(1 << 4), set FPCA.
+ ENDIF
+
+pendsv_exit
+ ; restore interrupt
+ MSR PRIMASK, r2
+
+ ORR lr, lr, #0x04
+ BX lr
+ ENDP
+
+;/*
+; * void rt_hw_context_switch_to(rt_uint32 to);
+; * r0 --> to
+; * this fucntion is used to perform the first thread switch
+; */
+rt_hw_context_switch_to PROC
+ EXPORT rt_hw_context_switch_to
+ ; set to thread
+ LDR r1, =rt_interrupt_to_thread
+ STR r0, [r1]
+
+ IF {FPU} != "SoftVFP"
+ ; CLEAR CONTROL.FPCA
+ MRS r2, CONTROL ; read
+ BIC r2, #0x04 ; modify
+ MSR CONTROL, r2 ; write-back
+ ENDIF
+
+ ; set from thread to 0
+ LDR r1, =rt_interrupt_from_thread
+ MOV r0, #0x0
+ STR r0, [r1]
+
+ ; set interrupt flag to 1
+ LDR r1, =rt_thread_switch_interrupt_flag
+ MOV r0, #1
+ STR r0, [r1]
+
+ ; set the PendSV and SysTick exception priority
+ LDR r0, =NVIC_SYSPRI2
+ LDR r1, =NVIC_PENDSV_PRI
+ LDR.W r2, [r0,#0x00] ; read
+ ORR r1,r1,r2 ; modify
+ STR r1, [r0] ; write-back
+
+ ; trigger the PendSV exception (causes context switch)
+ LDR r0, =NVIC_INT_CTRL
+ LDR r1, =NVIC_PENDSVSET
+ STR r1, [r0]
+
+ ; restore MSP
+ LDR r0, =SCB_VTOR
+ LDR r0, [r0]
+ LDR r0, [r0]
+ MSR msp, r0
+
+ ; enable interrupts at processor level
+ CPSIE F
+ CPSIE I
+
+ ; ensure PendSV exception taken place before subsequent operation
+ DSB
+ ISB
+
+ ; never reach here!
+ ENDP
+
+; compatible with old version
+rt_hw_interrupt_thread_switch PROC
+ EXPORT rt_hw_interrupt_thread_switch
+ BX lr
+ ENDP
+
+ IMPORT rt_hw_hard_fault_exception
+ EXPORT HardFault_Handler
+HardFault_Handler PROC
+
+ ; get current context
+ TST lr, #0x04 ; if(!EXC_RETURN[2])
+ ITE EQ
+ MRSEQ r0, msp ; [2]=0 ==> Z=1, get fault context from handler.
+ MRSNE r0, psp ; [2]=1 ==> Z=0, get fault context from thread.
+
+ STMFD r0!, {r4 - r11} ; push r4 - r11 register
+ IF {FPU} != "SoftVFP"
+ STMFD r0!, {lr} ; push dummy for flag
+ ENDIF
+ STMFD r0!, {lr} ; push exec_return register
+
+ TST lr, #0x04 ; if(!EXC_RETURN[2])
+ ITE EQ
+ MSREQ msp, r0 ; [2]=0 ==> Z=1, update stack pointer to MSP.
+ MSRNE psp, r0 ; [2]=1 ==> Z=0, update stack pointer to PSP.
+
+ PUSH {lr}
+ BL rt_hw_hard_fault_exception
+ POP {lr}
+
+ ORR lr, lr, #0x04
+ BX lr
+ ENDP
+
+ ALIGN 4
+
+ END
diff --git a/User/system/rt-thread/libcpu/cortex-m4/cpuport.c b/User/system/rt-thread/libcpu/cortex-m4/cpuport.c
new file mode 100644
index 0000000..717b4ba
--- /dev/null
+++ b/User/system/rt-thread/libcpu/cortex-m4/cpuport.c
@@ -0,0 +1,509 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2011-10-21 Bernard the first version.
+ * 2011-10-27 aozima update for cortex-M4 FPU.
+ * 2011-12-31 aozima fixed stack align issues.
+ * 2012-01-01 aozima support context switch load/store FPU register.
+ * 2012-12-11 lgnq fixed the coding style.
+ * 2012-12-23 aozima stack addr align to 8byte.
+ * 2012-12-29 Bernard Add exception hook.
+ * 2013-06-23 aozima support lazy stack optimized.
+ * 2018-07-24 aozima enhancement hard fault exception handler.
+ * 2019-07-03 yangjie add __rt_ffs() for armclang.
+ * 2022-06-12 jonas fixed __rt_ffs() for armclang.
+ */
+
+#include
+
+#if /* ARMCC */ ( (defined ( __CC_ARM ) && defined ( __TARGET_FPU_VFP )) \
+ /* Clang */ || (defined ( __clang__ ) && defined ( __VFP_FP__ ) && !defined(__SOFTFP__)) \
+ /* IAR */ || (defined ( __ICCARM__ ) && defined ( __ARMVFP__ )) \
+ /* GNU */ || (defined ( __GNUC__ ) && defined ( __VFP_FP__ ) && !defined(__SOFTFP__)) )
+#define USE_FPU 1
+#else
+#define USE_FPU 0
+#endif
+
+/* exception and interrupt handler table */
+rt_uint32_t rt_interrupt_from_thread;
+rt_uint32_t rt_interrupt_to_thread;
+rt_uint32_t rt_thread_switch_interrupt_flag;
+/* exception hook */
+static rt_err_t (*rt_exception_hook)(void *context) = RT_NULL;
+
+struct exception_stack_frame
+{
+ rt_uint32_t r0;
+ rt_uint32_t r1;
+ rt_uint32_t r2;
+ rt_uint32_t r3;
+ rt_uint32_t r12;
+ rt_uint32_t lr;
+ rt_uint32_t pc;
+ rt_uint32_t psr;
+};
+
+struct stack_frame
+{
+#if USE_FPU
+ rt_uint32_t flag;
+#endif /* USE_FPU */
+
+ /* r4 ~ r11 register */
+ rt_uint32_t r4;
+ rt_uint32_t r5;
+ rt_uint32_t r6;
+ rt_uint32_t r7;
+ rt_uint32_t r8;
+ rt_uint32_t r9;
+ rt_uint32_t r10;
+ rt_uint32_t r11;
+
+ struct exception_stack_frame exception_stack_frame;
+};
+
+struct exception_stack_frame_fpu
+{
+ rt_uint32_t r0;
+ rt_uint32_t r1;
+ rt_uint32_t r2;
+ rt_uint32_t r3;
+ rt_uint32_t r12;
+ rt_uint32_t lr;
+ rt_uint32_t pc;
+ rt_uint32_t psr;
+
+#if USE_FPU
+ /* FPU register */
+ rt_uint32_t S0;
+ rt_uint32_t S1;
+ rt_uint32_t S2;
+ rt_uint32_t S3;
+ rt_uint32_t S4;
+ rt_uint32_t S5;
+ rt_uint32_t S6;
+ rt_uint32_t S7;
+ rt_uint32_t S8;
+ rt_uint32_t S9;
+ rt_uint32_t S10;
+ rt_uint32_t S11;
+ rt_uint32_t S12;
+ rt_uint32_t S13;
+ rt_uint32_t S14;
+ rt_uint32_t S15;
+ rt_uint32_t FPSCR;
+ rt_uint32_t NO_NAME;
+#endif
+};
+
+struct stack_frame_fpu
+{
+ rt_uint32_t flag;
+
+ /* r4 ~ r11 register */
+ rt_uint32_t r4;
+ rt_uint32_t r5;
+ rt_uint32_t r6;
+ rt_uint32_t r7;
+ rt_uint32_t r8;
+ rt_uint32_t r9;
+ rt_uint32_t r10;
+ rt_uint32_t r11;
+
+#if USE_FPU
+ /* FPU register s16 ~ s31 */
+ rt_uint32_t s16;
+ rt_uint32_t s17;
+ rt_uint32_t s18;
+ rt_uint32_t s19;
+ rt_uint32_t s20;
+ rt_uint32_t s21;
+ rt_uint32_t s22;
+ rt_uint32_t s23;
+ rt_uint32_t s24;
+ rt_uint32_t s25;
+ rt_uint32_t s26;
+ rt_uint32_t s27;
+ rt_uint32_t s28;
+ rt_uint32_t s29;
+ rt_uint32_t s30;
+ rt_uint32_t s31;
+#endif
+
+ struct exception_stack_frame_fpu exception_stack_frame;
+};
+
+rt_uint8_t *rt_hw_stack_init(void *tentry,
+ void *parameter,
+ rt_uint8_t *stack_addr,
+ void *texit)
+{
+ struct stack_frame *stack_frame;
+ rt_uint8_t *stk;
+ unsigned long i;
+
+ stk = stack_addr + sizeof(rt_uint32_t);
+ stk = (rt_uint8_t *)RT_ALIGN_DOWN((rt_uint32_t)stk, 8);
+ stk -= sizeof(struct stack_frame);
+
+ stack_frame = (struct stack_frame *)stk;
+
+ /* init all register */
+ for (i = 0; i < sizeof(struct stack_frame) / sizeof(rt_uint32_t); i ++)
+ {
+ ((rt_uint32_t *)stack_frame)[i] = 0xdeadbeef;
+ }
+
+ stack_frame->exception_stack_frame.r0 = (unsigned long)parameter; /* r0 : argument */
+ stack_frame->exception_stack_frame.r1 = 0; /* r1 */
+ stack_frame->exception_stack_frame.r2 = 0; /* r2 */
+ stack_frame->exception_stack_frame.r3 = 0; /* r3 */
+ stack_frame->exception_stack_frame.r12 = 0; /* r12 */
+ stack_frame->exception_stack_frame.lr = (unsigned long)texit; /* lr */
+ stack_frame->exception_stack_frame.pc = (unsigned long)tentry; /* entry point, pc */
+ stack_frame->exception_stack_frame.psr = 0x01000000L; /* PSR */
+
+#if USE_FPU
+ stack_frame->flag = 0;
+#endif /* USE_FPU */
+
+ /* return task's current stack address */
+ return stk;
+}
+
+/**
+ * This function set the hook, which is invoked on fault exception handling.
+ *
+ * @param exception_handle the exception handling hook function.
+ */
+void rt_hw_exception_install(rt_err_t (*exception_handle)(void *context))
+{
+ rt_exception_hook = exception_handle;
+}
+
+#define SCB_CFSR (*(volatile const unsigned *)0xE000ED28) /* Configurable Fault Status Register */
+#define SCB_HFSR (*(volatile const unsigned *)0xE000ED2C) /* HardFault Status Register */
+#define SCB_MMAR (*(volatile const unsigned *)0xE000ED34) /* MemManage Fault Address register */
+#define SCB_BFAR (*(volatile const unsigned *)0xE000ED38) /* Bus Fault Address Register */
+#define SCB_AIRCR (*(volatile unsigned long *)0xE000ED0C) /* Reset control Address Register */
+#define SCB_RESET_VALUE 0x05FA0004 /* Reset value, write to SCB_AIRCR can reset cpu */
+
+#define SCB_CFSR_MFSR (*(volatile const unsigned char*)0xE000ED28) /* Memory-management Fault Status Register */
+#define SCB_CFSR_BFSR (*(volatile const unsigned char*)0xE000ED29) /* Bus Fault Status Register */
+#define SCB_CFSR_UFSR (*(volatile const unsigned short*)0xE000ED2A) /* Usage Fault Status Register */
+
+#ifdef RT_USING_FINSH
+static void usage_fault_track(void)
+{
+ rt_kprintf("usage fault:\n");
+ rt_kprintf("SCB_CFSR_UFSR:0x%02X ", SCB_CFSR_UFSR);
+
+ if(SCB_CFSR_UFSR & (1<<0))
+ {
+ /* [0]:UNDEFINSTR */
+ rt_kprintf("UNDEFINSTR ");
+ }
+
+ if(SCB_CFSR_UFSR & (1<<1))
+ {
+ /* [1]:INVSTATE */
+ rt_kprintf("INVSTATE ");
+ }
+
+ if(SCB_CFSR_UFSR & (1<<2))
+ {
+ /* [2]:INVPC */
+ rt_kprintf("INVPC ");
+ }
+
+ if(SCB_CFSR_UFSR & (1<<3))
+ {
+ /* [3]:NOCP */
+ rt_kprintf("NOCP ");
+ }
+
+ if(SCB_CFSR_UFSR & (1<<8))
+ {
+ /* [8]:UNALIGNED */
+ rt_kprintf("UNALIGNED ");
+ }
+
+ if(SCB_CFSR_UFSR & (1<<9))
+ {
+ /* [9]:DIVBYZERO */
+ rt_kprintf("DIVBYZERO ");
+ }
+
+ rt_kprintf("\n");
+}
+
+static void bus_fault_track(void)
+{
+ rt_kprintf("bus fault:\n");
+ rt_kprintf("SCB_CFSR_BFSR:0x%02X ", SCB_CFSR_BFSR);
+
+ if(SCB_CFSR_BFSR & (1<<0))
+ {
+ /* [0]:IBUSERR */
+ rt_kprintf("IBUSERR ");
+ }
+
+ if(SCB_CFSR_BFSR & (1<<1))
+ {
+ /* [1]:PRECISERR */
+ rt_kprintf("PRECISERR ");
+ }
+
+ if(SCB_CFSR_BFSR & (1<<2))
+ {
+ /* [2]:IMPRECISERR */
+ rt_kprintf("IMPRECISERR ");
+ }
+
+ if(SCB_CFSR_BFSR & (1<<3))
+ {
+ /* [3]:UNSTKERR */
+ rt_kprintf("UNSTKERR ");
+ }
+
+ if(SCB_CFSR_BFSR & (1<<4))
+ {
+ /* [4]:STKERR */
+ rt_kprintf("STKERR ");
+ }
+
+ if(SCB_CFSR_BFSR & (1<<7))
+ {
+ rt_kprintf("SCB->BFAR:%08X\n", SCB_BFAR);
+ }
+ else
+ {
+ rt_kprintf("\n");
+ }
+}
+
+static void mem_manage_fault_track(void)
+{
+ rt_kprintf("mem manage fault:\n");
+ rt_kprintf("SCB_CFSR_MFSR:0x%02X ", SCB_CFSR_MFSR);
+
+ if(SCB_CFSR_MFSR & (1<<0))
+ {
+ /* [0]:IACCVIOL */
+ rt_kprintf("IACCVIOL ");
+ }
+
+ if(SCB_CFSR_MFSR & (1<<1))
+ {
+ /* [1]:DACCVIOL */
+ rt_kprintf("DACCVIOL ");
+ }
+
+ if(SCB_CFSR_MFSR & (1<<3))
+ {
+ /* [3]:MUNSTKERR */
+ rt_kprintf("MUNSTKERR ");
+ }
+
+ if(SCB_CFSR_MFSR & (1<<4))
+ {
+ /* [4]:MSTKERR */
+ rt_kprintf("MSTKERR ");
+ }
+
+ if(SCB_CFSR_MFSR & (1<<7))
+ {
+ /* [7]:MMARVALID */
+ rt_kprintf("SCB->MMAR:%08X\n", SCB_MMAR);
+ }
+ else
+ {
+ rt_kprintf("\n");
+ }
+}
+
+static void hard_fault_track(void)
+{
+ if(SCB_HFSR & (1UL<<1))
+ {
+ /* [1]:VECTBL, Indicates hard fault is caused by failed vector fetch. */
+ rt_kprintf("failed vector fetch\n");
+ }
+
+ if(SCB_HFSR & (1UL<<30))
+ {
+ /* [30]:FORCED, Indicates hard fault is taken because of bus fault,
+ memory management fault, or usage fault. */
+ if(SCB_CFSR_BFSR)
+ {
+ bus_fault_track();
+ }
+
+ if(SCB_CFSR_MFSR)
+ {
+ mem_manage_fault_track();
+ }
+
+ if(SCB_CFSR_UFSR)
+ {
+ usage_fault_track();
+ }
+ }
+
+ if(SCB_HFSR & (1UL<<31))
+ {
+ /* [31]:DEBUGEVT, Indicates hard fault is triggered by debug event. */
+ rt_kprintf("debug event\n");
+ }
+}
+#endif /* RT_USING_FINSH */
+
+struct exception_info
+{
+ rt_uint32_t exc_return;
+ struct stack_frame stack_frame;
+};
+
+void rt_hw_hard_fault_exception(struct exception_info *exception_info)
+{
+#if defined(RT_USING_FINSH) && defined(MSH_USING_BUILT_IN_COMMANDS)
+ extern long list_thread(void);
+#endif
+ struct exception_stack_frame *exception_stack = &exception_info->stack_frame.exception_stack_frame;
+ struct stack_frame *context = &exception_info->stack_frame;
+
+ if (rt_exception_hook != RT_NULL)
+ {
+ rt_err_t result;
+
+ result = rt_exception_hook(exception_stack);
+ if (result == RT_EOK) return;
+ }
+
+ rt_kprintf("psr: 0x%08x\n", context->exception_stack_frame.psr);
+
+ rt_kprintf("r00: 0x%08x\n", context->exception_stack_frame.r0);
+ rt_kprintf("r01: 0x%08x\n", context->exception_stack_frame.r1);
+ rt_kprintf("r02: 0x%08x\n", context->exception_stack_frame.r2);
+ rt_kprintf("r03: 0x%08x\n", context->exception_stack_frame.r3);
+ rt_kprintf("r04: 0x%08x\n", context->r4);
+ rt_kprintf("r05: 0x%08x\n", context->r5);
+ rt_kprintf("r06: 0x%08x\n", context->r6);
+ rt_kprintf("r07: 0x%08x\n", context->r7);
+ rt_kprintf("r08: 0x%08x\n", context->r8);
+ rt_kprintf("r09: 0x%08x\n", context->r9);
+ rt_kprintf("r10: 0x%08x\n", context->r10);
+ rt_kprintf("r11: 0x%08x\n", context->r11);
+ rt_kprintf("r12: 0x%08x\n", context->exception_stack_frame.r12);
+ rt_kprintf(" lr: 0x%08x\n", context->exception_stack_frame.lr);
+ rt_kprintf(" pc: 0x%08x\n", context->exception_stack_frame.pc);
+
+ if (exception_info->exc_return & (1 << 2))
+ {
+ rt_kprintf("hard fault on thread: %s\r\n\r\n", rt_thread_self()->name);
+
+#if defined(RT_USING_FINSH) && defined(MSH_USING_BUILT_IN_COMMANDS)
+ list_thread();
+#endif
+ }
+ else
+ {
+ rt_kprintf("hard fault on handler\r\n\r\n");
+ }
+
+ if ( (exception_info->exc_return & 0x10) == 0)
+ {
+ rt_kprintf("FPU active!\r\n");
+ }
+
+#ifdef RT_USING_FINSH
+ hard_fault_track();
+#endif /* RT_USING_FINSH */
+
+ while (1);
+}
+
+/**
+ * shutdown CPU
+ */
+RT_WEAK void rt_hw_cpu_shutdown(void)
+{
+ rt_kprintf("shutdown...\n");
+
+ RT_ASSERT(0);
+}
+
+/**
+ * reset CPU
+ */
+RT_WEAK void rt_hw_cpu_reset(void)
+{
+ SCB_AIRCR = SCB_RESET_VALUE;
+}
+
+#ifdef RT_USING_CPU_FFS
+/**
+ * This function finds the first bit set (beginning with the least significant bit)
+ * in value and return the index of that bit.
+ *
+ * Bits are numbered starting at 1 (the least significant bit). A return value of
+ * zero from any of these functions means that the argument was zero.
+ *
+ * @return return the index of the first bit set. If value is 0, then this function
+ * shall return 0.
+ */
+#if defined(__CC_ARM)
+__asm int __rt_ffs(int value)
+{
+ CMP r0, #0x00
+ BEQ exit
+
+ RBIT r0, r0
+ CLZ r0, r0
+ ADDS r0, r0, #0x01
+
+exit
+ BX lr
+}
+#elif defined(__clang__)
+int __rt_ffs(int value)
+{
+ __asm volatile(
+ "CMP %1, #0x00 \n"
+ "BEQ 1f \n"
+
+ "RBIT %1, %1 \n"
+ "CLZ %0, %1 \n"
+ "ADDS %0, %0, #0x01 \n"
+
+ "1: \n"
+
+ : "=r"(value)
+ : "r"(value)
+ );
+ return value;
+}
+#elif defined(__IAR_SYSTEMS_ICC__)
+int __rt_ffs(int value)
+{
+ if (value == 0) return value;
+
+ asm("RBIT %0, %1" : "=r"(value) : "r"(value));
+ asm("CLZ %0, %1" : "=r"(value) : "r"(value));
+ asm("ADDS %0, %1, #0x01" : "=r"(value) : "r"(value));
+
+ return value;
+}
+#elif defined(__GNUC__)
+int __rt_ffs(int value)
+{
+ return __builtin_ffs(value);
+}
+#endif
+
+#endif
diff --git a/User/system/rt-thread/src/clock.c b/User/system/rt-thread/src/clock.c
new file mode 100644
index 0000000..0e88bf4
--- /dev/null
+++ b/User/system/rt-thread/src/clock.c
@@ -0,0 +1,179 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2006-03-12 Bernard first version
+ * 2006-05-27 Bernard add support for same priority thread schedule
+ * 2006-08-10 Bernard remove the last rt_schedule in rt_tick_increase
+ * 2010-03-08 Bernard remove rt_passed_second
+ * 2010-05-20 Bernard fix the tick exceeds the maximum limits
+ * 2010-07-13 Bernard fix rt_tick_from_millisecond issue found by kuronca
+ * 2011-06-26 Bernard add rt_tick_set function.
+ * 2018-11-22 Jesven add per cpu tick
+ * 2020-12-29 Meco Man implement rt_tick_get_millisecond()
+ * 2021-06-01 Meco Man add critical section projection for rt_tick_increase()
+ */
+
+#include
+#include
+
+#ifdef RT_USING_SMP
+#define rt_tick rt_cpu_index(0)->tick
+#else
+static volatile rt_tick_t rt_tick = 0;
+#endif /* RT_USING_SMP */
+
+#ifndef __on_rt_tick_hook
+ #define __on_rt_tick_hook() __ON_HOOK_ARGS(rt_tick_hook, ())
+#endif
+
+#if defined(RT_USING_HOOK) && defined(RT_HOOK_USING_FUNC_PTR)
+static void (*rt_tick_hook)(void);
+
+/**
+ * @addtogroup Hook
+ */
+
+/**@{*/
+
+/**
+ * This function will set a hook function, which will be invoked when tick increase
+ *
+ *
+ * @param hook the hook function
+ */
+void rt_tick_sethook(void (*hook)(void))
+{
+ rt_tick_hook = hook;
+}
+/**@}*/
+#endif /* RT_USING_HOOK */
+
+/**
+ * @addtogroup Clock
+ */
+
+/**@{*/
+
+/**
+ * @brief This function will return current tick from operating system startup.
+ *
+ * @return Return current tick.
+ */
+rt_tick_t rt_tick_get(void)
+{
+ /* return the global tick */
+ return rt_tick;
+}
+RTM_EXPORT(rt_tick_get);
+
+/**
+ * @brief This function will set current tick.
+ *
+ * @param tick is the value that you will set.
+ */
+void rt_tick_set(rt_tick_t tick)
+{
+ rt_base_t level;
+
+ level = rt_hw_interrupt_disable();
+ rt_tick = tick;
+ rt_hw_interrupt_enable(level);
+}
+
+/**
+ * @brief This function will notify kernel there is one tick passed.
+ * Normally, this function is invoked by clock ISR.
+ */
+void rt_tick_increase(void)
+{
+ struct rt_thread *thread;
+ rt_base_t level;
+
+ RT_OBJECT_HOOK_CALL(rt_tick_hook, ());
+
+ level = rt_hw_interrupt_disable();
+
+ /* increase the global tick */
+#ifdef RT_USING_SMP
+ rt_cpu_self()->tick ++;
+#else
+ ++ rt_tick;
+#endif /* RT_USING_SMP */
+
+ /* check time slice */
+ thread = rt_thread_self();
+
+ -- thread->remaining_tick;
+ if (thread->remaining_tick == 0)
+ {
+ /* change to initialized tick */
+ thread->remaining_tick = thread->init_tick;
+ thread->stat |= RT_THREAD_STAT_YIELD;
+
+ rt_hw_interrupt_enable(level);
+ rt_schedule();
+ }
+ else
+ {
+ rt_hw_interrupt_enable(level);
+ }
+
+ /* check timer */
+ rt_timer_check();
+}
+
+/**
+ * @brief This function will calculate the tick from millisecond.
+ *
+ * @param ms is the specified millisecond.
+ * - Negative Number wait forever
+ * - Zero not wait
+ * - Max 0x7fffffff
+ *
+ * @return Return the calculated tick.
+ */
+rt_tick_t rt_tick_from_millisecond(rt_int32_t ms)
+{
+ rt_tick_t tick;
+
+ if (ms < 0)
+ {
+ tick = (rt_tick_t)RT_WAITING_FOREVER;
+ }
+ else
+ {
+ tick = RT_TICK_PER_SECOND * (ms / 1000);
+ tick += (RT_TICK_PER_SECOND * (ms % 1000) + 999) / 1000;
+ }
+
+ /* return the calculated tick */
+ return tick;
+}
+RTM_EXPORT(rt_tick_from_millisecond);
+
+/**
+ * @brief This function will return the passed millisecond from boot.
+ *
+ * @note if the value of RT_TICK_PER_SECOND is lower than 1000 or
+ * is not an integral multiple of 1000, this function will not
+ * provide the correct 1ms-based tick.
+ *
+ * @return Return passed millisecond from boot.
+ */
+RT_WEAK rt_tick_t rt_tick_get_millisecond(void)
+{
+#if 1000 % RT_TICK_PER_SECOND == 0u
+ return rt_tick_get() * (1000u / RT_TICK_PER_SECOND);
+#else
+ #warning "rt-thread cannot provide a correct 1ms-based tick any longer,\
+ please redefine this function in another file by using a high-precision hard-timer."
+ return 0;
+#endif /* 1000 % RT_TICK_PER_SECOND == 0u */
+}
+
+/**@}*/
+
diff --git a/User/system/rt-thread/src/components.c b/User/system/rt-thread/src/components.c
new file mode 100644
index 0000000..9433b74
--- /dev/null
+++ b/User/system/rt-thread/src/components.c
@@ -0,0 +1,275 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2012-09-20 Bernard Change the name to components.c
+ * And all components related header files.
+ * 2012-12-23 Bernard fix the pthread initialization issue.
+ * 2013-06-23 Bernard Add the init_call for components initialization.
+ * 2013-07-05 Bernard Remove initialization feature for MS VC++ compiler
+ * 2015-02-06 Bernard Remove the MS VC++ support and move to the kernel
+ * 2015-05-04 Bernard Rename it to components.c because compiling issue
+ * in some IDEs.
+ * 2015-07-29 Arda.Fu Add support to use RT_USING_USER_MAIN with IAR
+ * 2018-11-22 Jesven Add secondary cpu boot up
+ */
+
+#include
+#include
+
+#ifdef RT_USING_USER_MAIN
+#ifndef RT_MAIN_THREAD_STACK_SIZE
+#define RT_MAIN_THREAD_STACK_SIZE 2048
+#endif /* RT_MAIN_THREAD_STACK_SIZE */
+#ifndef RT_MAIN_THREAD_PRIORITY
+#define RT_MAIN_THREAD_PRIORITY (RT_THREAD_PRIORITY_MAX / 3)
+#endif /* RT_MAIN_THREAD_PRIORITY */
+#endif /* RT_USING_USER_MAIN */
+
+#ifdef RT_USING_COMPONENTS_INIT
+/*
+ * Components Initialization will initialize some driver and components as following
+ * order:
+ * rti_start --> 0
+ * BOARD_EXPORT --> 1
+ * rti_board_end --> 1.end
+ *
+ * DEVICE_EXPORT --> 2
+ * COMPONENT_EXPORT --> 3
+ * FS_EXPORT --> 4
+ * ENV_EXPORT --> 5
+ * APP_EXPORT --> 6
+ *
+ * rti_end --> 6.end
+ *
+ * These automatically initialization, the driver or component initial function must
+ * be defined with:
+ * INIT_BOARD_EXPORT(fn);
+ * INIT_DEVICE_EXPORT(fn);
+ * ...
+ * INIT_APP_EXPORT(fn);
+ * etc.
+ */
+static int rti_start(void)
+{
+ return 0;
+}
+INIT_EXPORT(rti_start, "0");
+
+static int rti_board_start(void)
+{
+ return 0;
+}
+INIT_EXPORT(rti_board_start, "0.end");
+
+static int rti_board_end(void)
+{
+ return 0;
+}
+INIT_EXPORT(rti_board_end, "1.end");
+
+static int rti_end(void)
+{
+ return 0;
+}
+INIT_EXPORT(rti_end, "6.end");
+
+/**
+ * @brief Onboard components initialization. In this function, the board-level
+ * initialization function will be called to complete the initialization
+ * of the on-board peripherals.
+ */
+void rt_components_board_init(void)
+{
+#if RT_DEBUG_INIT
+ int result;
+ const struct rt_init_desc *desc;
+ for (desc = &__rt_init_desc_rti_board_start; desc < &__rt_init_desc_rti_board_end; desc ++)
+ {
+ rt_kprintf("initialize %s", desc->fn_name);
+ result = desc->fn();
+ rt_kprintf(":%d done\n", result);
+ }
+#else
+ volatile const init_fn_t *fn_ptr;
+
+ for (fn_ptr = &__rt_init_rti_board_start; fn_ptr < &__rt_init_rti_board_end; fn_ptr++)
+ {
+ (*fn_ptr)();
+ }
+#endif /* RT_DEBUG_INIT */
+}
+
+/**
+ * @brief RT-Thread Components Initialization.
+ */
+void rt_components_init(void)
+{
+#if RT_DEBUG_INIT
+ int result;
+ const struct rt_init_desc *desc;
+
+ rt_kprintf("do components initialization.\n");
+ for (desc = &__rt_init_desc_rti_board_end; desc < &__rt_init_desc_rti_end; desc ++)
+ {
+ rt_kprintf("initialize %s", desc->fn_name);
+ result = desc->fn();
+ rt_kprintf(":%d done\n", result);
+ }
+#else
+ volatile const init_fn_t *fn_ptr;
+
+ for (fn_ptr = &__rt_init_rti_board_end; fn_ptr < &__rt_init_rti_end; fn_ptr ++)
+ {
+ (*fn_ptr)();
+ }
+#endif /* RT_DEBUG_INIT */
+}
+#endif /* RT_USING_COMPONENTS_INIT */
+
+#ifdef RT_USING_USER_MAIN
+
+void rt_application_init(void);
+void rt_hw_board_init(void);
+int rtthread_startup(void);
+
+#ifdef __ARMCC_VERSION
+extern int $Super$$main(void);
+/* re-define main function */
+int $Sub$$main(void)
+{
+ rtthread_startup();
+ return 0;
+}
+#elif defined(__ICCARM__)
+extern int main(void);
+/* __low_level_init will auto called by IAR cstartup */
+extern void __iar_data_init3(void);
+int __low_level_init(void)
+{
+ // call IAR table copy function.
+ __iar_data_init3();
+ rtthread_startup();
+ return 0;
+}
+#elif defined(__GNUC__)
+/* Add -eentry to arm-none-eabi-gcc argument */
+int entry(void)
+{
+ rtthread_startup();
+ return 0;
+}
+#endif
+
+#ifndef RT_USING_HEAP
+/* if there is not enable heap, we should use static thread and stack. */
+ALIGN(8)
+static rt_uint8_t main_stack[RT_MAIN_THREAD_STACK_SIZE];
+struct rt_thread main_thread;
+#endif /* RT_USING_HEAP */
+
+/**
+ * @brief The system main thread. In this thread will call the rt_components_init()
+ * for initialization of RT-Thread Components and call the user's programming
+ * entry main().
+ */
+void main_thread_entry(void *parameter)
+{
+ extern int main(void);
+
+#ifdef RT_USING_COMPONENTS_INIT
+ /* RT-Thread components initialization */
+ rt_components_init();
+#endif /* RT_USING_COMPONENTS_INIT */
+
+#ifdef RT_USING_SMP
+ rt_hw_secondary_cpu_up();
+#endif /* RT_USING_SMP */
+ /* invoke system main function */
+#ifdef __ARMCC_VERSION
+ {
+ extern int $Super$$main(void);
+ $Super$$main(); /* for ARMCC. */
+ }
+#elif defined(__ICCARM__) || defined(__GNUC__) || defined(__TASKING__)
+ main();
+#endif
+}
+
+/**
+ * @brief This function will create and start the main thread, but this thread
+ * will not run until the scheduler starts.
+ */
+void rt_application_init(void)
+{
+ rt_thread_t tid;
+
+#ifdef RT_USING_HEAP
+ tid = rt_thread_create("main", main_thread_entry, RT_NULL,
+ RT_MAIN_THREAD_STACK_SIZE, RT_MAIN_THREAD_PRIORITY, 20);
+ RT_ASSERT(tid != RT_NULL);
+#else
+ rt_err_t result;
+
+ tid = &main_thread;
+ result = rt_thread_init(tid, "main", main_thread_entry, RT_NULL,
+ main_stack, sizeof(main_stack), RT_MAIN_THREAD_PRIORITY, 20);
+ RT_ASSERT(result == RT_EOK);
+
+ /* if not define RT_USING_HEAP, using to eliminate the warning */
+ (void)result;
+#endif /* RT_USING_HEAP */
+
+ rt_thread_startup(tid);
+}
+
+/**
+ * @brief This function will call all levels of initialization functions to complete
+ * the initialization of the system, and finally start the scheduler.
+ */
+int rtthread_startup(void)
+{
+ rt_hw_interrupt_disable();
+
+ /* board level initialization
+ * NOTE: please initialize heap inside board initialization.
+ */
+ rt_hw_board_init();
+
+ /* show RT-Thread version */
+ rt_show_version();
+
+ /* timer system initialization */
+ rt_system_timer_init();
+
+ /* scheduler system initialization */
+ rt_system_scheduler_init();
+
+#ifdef RT_USING_SIGNALS
+ /* signal system initialization */
+ rt_system_signal_init();
+#endif /* RT_USING_SIGNALS */
+
+ /* create init_thread */
+ rt_application_init();
+
+ /* timer thread initialization */
+ rt_system_timer_thread_init();
+
+ /* idle thread initialization */
+ rt_thread_idle_init();
+
+#ifdef RT_USING_SMP
+ rt_hw_spin_lock(&_cpus_lock);
+#endif /* RT_USING_SMP */
+
+ /* start scheduler */
+ rt_system_scheduler_start();
+
+ /* never reach here */
+ return 0;
+}
+#endif /* RT_USING_USER_MAIN */
diff --git a/User/system/rt-thread/src/cpu.c b/User/system/rt-thread/src/cpu.c
new file mode 100644
index 0000000..2371ec2
--- /dev/null
+++ b/User/system/rt-thread/src/cpu.c
@@ -0,0 +1,234 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2018-10-30 Bernard The first version
+ */
+#include
+#include
+
+#ifdef RT_USING_SMP
+static struct rt_cpu _cpus[RT_CPUS_NR];
+rt_hw_spinlock_t _cpus_lock;
+
+/*
+ * disable scheduler
+ */
+static void _cpu_preempt_disable(void)
+{
+ rt_base_t level;
+ struct rt_thread *current_thread;
+
+ /* disable interrupt */
+ level = rt_hw_local_irq_disable();
+
+ current_thread = rt_thread_self();
+ if (!current_thread)
+ {
+ rt_hw_local_irq_enable(level);
+ return;
+ }
+
+ /* lock scheduler for local cpu */
+ current_thread->scheduler_lock_nest ++;
+
+ /* enable interrupt */
+ rt_hw_local_irq_enable(level);
+}
+
+/*
+ * enable scheduler
+ */
+static void _cpu_preempt_enable(void)
+{
+ rt_base_t level;
+ struct rt_thread *current_thread;
+
+ /* disable interrupt */
+ level = rt_hw_local_irq_disable();
+
+ current_thread = rt_thread_self();
+ if (!current_thread)
+ {
+ rt_hw_local_irq_enable(level);
+ return;
+ }
+
+ /* unlock scheduler for local cpu */
+ current_thread->scheduler_lock_nest --;
+
+ rt_schedule();
+ /* enable interrupt */
+ rt_hw_local_irq_enable(level);
+}
+
+/**
+ * @brief Initialize a static spinlock object.
+ *
+ * @param lock is a pointer to the spinlock to initialize.
+ */
+void rt_spin_lock_init(struct rt_spinlock *lock)
+{
+ rt_hw_spin_lock_init(&lock->lock);
+}
+RTM_EXPORT(rt_spin_lock_init)
+
+/**
+ * @brief This function will lock the spinlock.
+ *
+ * @note If the spinlock is locked, the current CPU will keep polling the spinlock state
+ * until the spinlock is unlocked.
+ *
+ * @param lock is a pointer to the spinlock.
+ */
+void rt_spin_lock(struct rt_spinlock *lock)
+{
+ _cpu_preempt_disable();
+ rt_hw_spin_lock(&lock->lock);
+}
+RTM_EXPORT(rt_spin_lock)
+
+/**
+ * @brief This function will unlock the spinlock.
+ *
+ * @param lock is a pointer to the spinlock.
+ */
+void rt_spin_unlock(struct rt_spinlock *lock)
+{
+ rt_hw_spin_unlock(&lock->lock);
+ _cpu_preempt_enable();
+}
+RTM_EXPORT(rt_spin_unlock)
+
+/**
+ * @brief This function will disable the local interrupt and then lock the spinlock.
+ *
+ * @note If the spinlock is locked, the current CPU will keep polling the spinlock state
+ * until the spinlock is unlocked.
+ *
+ * @param lock is a pointer to the spinlock.
+ *
+ * @return Return current cpu interrupt status.
+ */
+rt_base_t rt_spin_lock_irqsave(struct rt_spinlock *lock)
+{
+ unsigned long level;
+
+ _cpu_preempt_disable();
+
+ level = rt_hw_local_irq_disable();
+ rt_hw_spin_lock(&lock->lock);
+
+ return level;
+}
+RTM_EXPORT(rt_spin_lock_irqsave)
+
+/**
+ * @brief This function will unlock the spinlock and then restore current cpu interrupt status.
+ *
+ * @param lock is a pointer to the spinlock.
+ *
+ * @param level is interrupt status returned by rt_spin_lock_irqsave().
+ */
+void rt_spin_unlock_irqrestore(struct rt_spinlock *lock, rt_base_t level)
+{
+ rt_hw_spin_unlock(&lock->lock);
+ rt_hw_local_irq_enable(level);
+
+ _cpu_preempt_enable();
+}
+RTM_EXPORT(rt_spin_unlock_irqrestore)
+
+/**
+ * @brief This fucntion will return current cpu object.
+ *
+ * @return Return a pointer to the current cpu object.
+ */
+struct rt_cpu *rt_cpu_self(void)
+{
+ return &_cpus[rt_hw_cpu_id()];
+}
+
+/**
+ * @brief This fucntion will return the cpu object corresponding to index.
+ *
+ * @return Return a pointer to the cpu object corresponding to index.
+ */
+struct rt_cpu *rt_cpu_index(int index)
+{
+ return &_cpus[index];
+}
+
+/**
+ * @brief This function will lock all cpus's scheduler and disable local irq.
+ *
+ * @return Return current cpu interrupt status.
+ */
+rt_base_t rt_cpus_lock(void)
+{
+ rt_base_t level;
+ struct rt_cpu* pcpu;
+
+ level = rt_hw_local_irq_disable();
+
+ pcpu = rt_cpu_self();
+ if (pcpu->current_thread != RT_NULL)
+ {
+ register rt_ubase_t lock_nest = pcpu->current_thread->cpus_lock_nest;
+
+ pcpu->current_thread->cpus_lock_nest++;
+ if (lock_nest == 0)
+ {
+ pcpu->current_thread->scheduler_lock_nest++;
+ rt_hw_spin_lock(&_cpus_lock);
+ }
+ }
+
+ return level;
+}
+RTM_EXPORT(rt_cpus_lock);
+
+/**
+ * @brief This function will restore all cpus's scheduler and restore local irq.
+ *
+ * @param level is interrupt status returned by rt_cpus_lock().
+ */
+void rt_cpus_unlock(rt_base_t level)
+{
+ struct rt_cpu* pcpu = rt_cpu_self();
+
+ if (pcpu->current_thread != RT_NULL)
+ {
+ pcpu->current_thread->cpus_lock_nest--;
+
+ if (pcpu->current_thread->cpus_lock_nest == 0)
+ {
+ pcpu->current_thread->scheduler_lock_nest--;
+ rt_hw_spin_unlock(&_cpus_lock);
+ }
+ }
+ rt_hw_local_irq_enable(level);
+}
+RTM_EXPORT(rt_cpus_unlock);
+
+/**
+ * This function is invoked by scheduler.
+ * It will restore the lock state to whatever the thread's counter expects.
+ * If target thread not locked the cpus then unlock the cpus lock.
+ */
+void rt_cpus_lock_status_restore(struct rt_thread *thread)
+{
+ struct rt_cpu* pcpu = rt_cpu_self();
+
+ pcpu->current_thread = thread;
+ if (!thread->cpus_lock_nest)
+ {
+ rt_hw_spin_unlock(&_cpus_lock);
+ }
+}
+RTM_EXPORT(rt_cpus_lock_status_restore);
+
+#endif /* RT_USING_SMP */
diff --git a/User/system/rt-thread/src/device.c b/User/system/rt-thread/src/device.c
new file mode 100644
index 0000000..1079e2c
--- /dev/null
+++ b/User/system/rt-thread/src/device.c
@@ -0,0 +1,460 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2007-01-21 Bernard the first version
+ * 2010-05-04 Bernard add rt_device_init implementation
+ * 2012-10-20 Bernard add device check in register function,
+ * provided by Rob
+ * 2012-12-25 Bernard return RT_EOK if the device interface not exist.
+ * 2013-07-09 Grissiom add ref_count support
+ * 2016-04-02 Bernard fix the open_flag initialization issue.
+ * 2021-03-19 Meco Man remove rt_device_init_all()
+ */
+
+#include
+#ifdef RT_USING_POSIX_DEVIO
+#include /* for wqueue_init */
+#endif /* RT_USING_POSIX_DEVIO */
+
+#ifdef RT_USING_DEVICE
+
+#ifdef RT_USING_DEVICE_OPS
+#define device_init (dev->ops->init)
+#define device_open (dev->ops->open)
+#define device_close (dev->ops->close)
+#define device_read (dev->ops->read)
+#define device_write (dev->ops->write)
+#define device_control (dev->ops->control)
+#else
+#define device_init (dev->init)
+#define device_open (dev->open)
+#define device_close (dev->close)
+#define device_read (dev->read)
+#define device_write (dev->write)
+#define device_control (dev->control)
+#endif /* RT_USING_DEVICE_OPS */
+
+/**
+ * @brief This function registers a device driver with a specified name.
+ *
+ * @param dev is the pointer of device driver structure.
+ *
+ * @param name is the device driver's name.
+ *
+ * @param flags is the capabilities flag of device.
+ *
+ * @return the error code, RT_EOK on initialization successfully.
+ */
+rt_err_t rt_device_register(rt_device_t dev,
+ const char *name,
+ rt_uint16_t flags)
+{
+ if (dev == RT_NULL)
+ return -RT_ERROR;
+
+ if (rt_device_find(name) != RT_NULL)
+ return -RT_ERROR;
+
+ rt_object_init(&(dev->parent), RT_Object_Class_Device, name);
+ dev->flag = flags;
+ dev->ref_count = 0;
+ dev->open_flag = 0;
+
+#ifdef RT_USING_POSIX_DEVIO
+ dev->fops = RT_NULL;
+ rt_wqueue_init(&(dev->wait_queue));
+#endif /* RT_USING_POSIX_DEVIO */
+
+ return RT_EOK;
+}
+RTM_EXPORT(rt_device_register);
+
+/**
+ * @brief This function removes a previously registered device driver.
+ *
+ * @param dev is the pointer of device driver structure.
+ *
+ * @return the error code, RT_EOK on successfully.
+ */
+rt_err_t rt_device_unregister(rt_device_t dev)
+{
+ /* parameter check */
+ RT_ASSERT(dev != RT_NULL);
+ RT_ASSERT(rt_object_get_type(&dev->parent) == RT_Object_Class_Device);
+ RT_ASSERT(rt_object_is_systemobject(&dev->parent));
+
+ rt_object_detach(&(dev->parent));
+
+ return RT_EOK;
+}
+RTM_EXPORT(rt_device_unregister);
+
+/**
+ * @brief This function finds a device driver by specified name.
+ *
+ * @param name is the device driver's name.
+ *
+ * @return the registered device driver on successful, or RT_NULL on failure.
+ */
+rt_device_t rt_device_find(const char *name)
+{
+ return (rt_device_t)rt_object_find(name, RT_Object_Class_Device);
+}
+RTM_EXPORT(rt_device_find);
+
+#ifdef RT_USING_HEAP
+/**
+ * @brief This function creates a device object with user data size.
+ *
+ * @param type is the type of the device object.
+ *
+ * @param attach_size is the size of user data.
+ *
+ * @return the allocated device object, or RT_NULL when failed.
+ */
+rt_device_t rt_device_create(int type, int attach_size)
+{
+ int size;
+ rt_device_t device;
+
+ size = RT_ALIGN(sizeof(struct rt_device), RT_ALIGN_SIZE);
+ attach_size = RT_ALIGN(attach_size, RT_ALIGN_SIZE);
+ /* use the total size */
+ size += attach_size;
+
+ device = (rt_device_t)rt_malloc(size);
+ if (device)
+ {
+ rt_memset(device, 0x0, sizeof(struct rt_device));
+ device->type = (enum rt_device_class_type)type;
+ }
+
+ return device;
+}
+RTM_EXPORT(rt_device_create);
+
+/**
+ * @brief This function destroy the specific device object.
+ *
+ * @param dev is a specific device object.
+ */
+void rt_device_destroy(rt_device_t dev)
+{
+ /* parameter check */
+ RT_ASSERT(dev != RT_NULL);
+ RT_ASSERT(rt_object_get_type(&dev->parent) == RT_Object_Class_Device);
+ RT_ASSERT(rt_object_is_systemobject(&dev->parent) == RT_FALSE);
+
+ rt_object_detach(&(dev->parent));
+
+ /* release this device object */
+ rt_free(dev);
+}
+RTM_EXPORT(rt_device_destroy);
+#endif /* RT_USING_HEAP */
+
+/**
+ * @brief This function will initialize the specified device.
+ *
+ * @param dev is the pointer of device driver structure.
+ *
+ * @return the result, RT_EOK on successfully.
+ */
+rt_err_t rt_device_init(rt_device_t dev)
+{
+ rt_err_t result = RT_EOK;
+
+ RT_ASSERT(dev != RT_NULL);
+
+ /* get device_init handler */
+ if (device_init != RT_NULL)
+ {
+ if (!(dev->flag & RT_DEVICE_FLAG_ACTIVATED))
+ {
+ result = device_init(dev);
+ if (result != RT_EOK)
+ {
+ RT_DEBUG_LOG(RT_DEBUG_DEVICE, ("To initialize device:%s failed. The error code is %d\n",
+ dev->parent.name, result));
+ }
+ else
+ {
+ dev->flag |= RT_DEVICE_FLAG_ACTIVATED;
+ }
+ }
+ }
+
+ return result;
+}
+
+/**
+ * @brief This function will open a device.
+ *
+ * @param dev is the pointer of device driver structure.
+ *
+ * @param oflag is the flags for device open.
+ *
+ * @return the result, RT_EOK on successfully.
+ */
+rt_err_t rt_device_open(rt_device_t dev, rt_uint16_t oflag)
+{
+ rt_err_t result = RT_EOK;
+
+ /* parameter check */
+ RT_ASSERT(dev != RT_NULL);
+ RT_ASSERT(rt_object_get_type(&dev->parent) == RT_Object_Class_Device);
+
+ /* if device is not initialized, initialize it. */
+ if (!(dev->flag & RT_DEVICE_FLAG_ACTIVATED))
+ {
+ if (device_init != RT_NULL)
+ {
+ result = device_init(dev);
+ if (result != RT_EOK)
+ {
+ RT_DEBUG_LOG(RT_DEBUG_DEVICE, ("To initialize device:%s failed. The error code is %d\n",
+ dev->parent.name, result));
+
+ return result;
+ }
+ }
+
+ dev->flag |= RT_DEVICE_FLAG_ACTIVATED;
+ }
+
+ /* device is a stand alone device and opened */
+ if ((dev->flag & RT_DEVICE_FLAG_STANDALONE) &&
+ (dev->open_flag & RT_DEVICE_OFLAG_OPEN))
+ {
+ return -RT_EBUSY;
+ }
+
+ /* call device_open interface */
+ if (device_open != RT_NULL)
+ {
+ result = device_open(dev, oflag);
+ }
+ else
+ {
+ /* set open flag */
+ dev->open_flag = (oflag & RT_DEVICE_OFLAG_MASK);
+ }
+
+ /* set open flag */
+ if (result == RT_EOK || result == -RT_ENOSYS)
+ {
+ dev->open_flag |= RT_DEVICE_OFLAG_OPEN;
+
+ dev->ref_count++;
+ /* don't let bad things happen silently. If you are bitten by this assert,
+ * please set the ref_count to a bigger type. */
+ RT_ASSERT(dev->ref_count != 0);
+ }
+
+ return result;
+}
+RTM_EXPORT(rt_device_open);
+
+/**
+ * @brief This function will close a device.
+ *
+ * @param dev is the pointer of device driver structure.
+ *
+ * @return the result, RT_EOK on successfully.
+ */
+rt_err_t rt_device_close(rt_device_t dev)
+{
+ rt_err_t result = RT_EOK;
+
+ /* parameter check */
+ RT_ASSERT(dev != RT_NULL);
+ RT_ASSERT(rt_object_get_type(&dev->parent) == RT_Object_Class_Device);
+
+ if (dev->ref_count == 0)
+ return -RT_ERROR;
+
+ dev->ref_count--;
+
+ if (dev->ref_count != 0)
+ return RT_EOK;
+
+ /* call device_close interface */
+ if (device_close != RT_NULL)
+ {
+ result = device_close(dev);
+ }
+
+ /* set open flag */
+ if (result == RT_EOK || result == -RT_ENOSYS)
+ dev->open_flag = RT_DEVICE_OFLAG_CLOSE;
+
+ return result;
+}
+RTM_EXPORT(rt_device_close);
+
+/**
+ * @brief This function will read some data from a device.
+ *
+ * @param dev is the pointer of device driver structure.
+ *
+ * @param pos is the position when reading.
+ *
+ * @param buffer is a data buffer to save the read data.
+ *
+ * @param size is the size of buffer.
+ *
+ * @return the actually read size on successful, otherwise 0 will be returned.
+ *
+ * @note the unit of size/pos is a block for block device.
+ */
+rt_size_t rt_device_read(rt_device_t dev,
+ rt_off_t pos,
+ void *buffer,
+ rt_size_t size)
+{
+ /* parameter check */
+ RT_ASSERT(dev != RT_NULL);
+ RT_ASSERT(rt_object_get_type(&dev->parent) == RT_Object_Class_Device);
+
+ if (dev->ref_count == 0)
+ {
+ rt_set_errno(-RT_ERROR);
+ return 0;
+ }
+
+ /* call device_read interface */
+ if (device_read != RT_NULL)
+ {
+ return device_read(dev, pos, buffer, size);
+ }
+
+ /* set error code */
+ rt_set_errno(-RT_ENOSYS);
+
+ return 0;
+}
+RTM_EXPORT(rt_device_read);
+
+/**
+ * @brief This function will write some data to a device.
+ *
+ * @param dev is the pointer of device driver structure.
+ *
+ * @param pos is the position when writing.
+ *
+ * @param buffer is the data buffer to be written to device.
+ *
+ * @param size is the size of buffer.
+ *
+ * @return the actually written size on successful, otherwise 0 will be returned.
+ *
+ * @note the unit of size/pos is a block for block device.
+ */
+rt_size_t rt_device_write(rt_device_t dev,
+ rt_off_t pos,
+ const void *buffer,
+ rt_size_t size)
+{
+ /* parameter check */
+ RT_ASSERT(dev != RT_NULL);
+ RT_ASSERT(rt_object_get_type(&dev->parent) == RT_Object_Class_Device);
+
+ if (dev->ref_count == 0)
+ {
+ rt_set_errno(-RT_ERROR);
+ return 0;
+ }
+
+ /* call device_write interface */
+ if (device_write != RT_NULL)
+ {
+ return device_write(dev, pos, buffer, size);
+ }
+
+ /* set error code */
+ rt_set_errno(-RT_ENOSYS);
+
+ return 0;
+}
+RTM_EXPORT(rt_device_write);
+
+/**
+ * @brief This function will perform a variety of control functions on devices.
+ *
+ * @param dev is the pointer of device driver structure.
+ *
+ * @param cmd is the command sent to device.
+ *
+ * @param arg is the argument of command.
+ *
+ * @return the result, -RT_ENOSYS for failed.
+ */
+rt_err_t rt_device_control(rt_device_t dev, int cmd, void *arg)
+{
+ /* parameter check */
+ RT_ASSERT(dev != RT_NULL);
+ RT_ASSERT(rt_object_get_type(&dev->parent) == RT_Object_Class_Device);
+
+ /* call device_write interface */
+ if (device_control != RT_NULL)
+ {
+ return device_control(dev, cmd, arg);
+ }
+
+ return -RT_ENOSYS;
+}
+RTM_EXPORT(rt_device_control);
+
+/**
+ * @brief This function will set the reception indication callback function. This callback function
+ * is invoked when this device receives data.
+ *
+ * @param dev is the pointer of device driver structure.
+ *
+ * @param rx_ind is the indication callback function.
+ *
+ * @return RT_EOK
+ */
+rt_err_t rt_device_set_rx_indicate(rt_device_t dev,
+ rt_err_t (*rx_ind)(rt_device_t dev,
+ rt_size_t size))
+{
+ /* parameter check */
+ RT_ASSERT(dev != RT_NULL);
+ RT_ASSERT(rt_object_get_type(&dev->parent) == RT_Object_Class_Device);
+
+ dev->rx_indicate = rx_ind;
+
+ return RT_EOK;
+}
+RTM_EXPORT(rt_device_set_rx_indicate);
+
+/**
+ * @brief This function will set a callback function. The callback function
+ * will be called when device has written data to physical hardware.
+ *
+ * @param dev is the pointer of device driver structure.
+ *
+ * @param tx_done is the indication callback function.
+ *
+ * @return RT_EOK
+ */
+rt_err_t rt_device_set_tx_complete(rt_device_t dev,
+ rt_err_t (*tx_done)(rt_device_t dev,
+ void *buffer))
+{
+ /* parameter check */
+ RT_ASSERT(dev != RT_NULL);
+ RT_ASSERT(rt_object_get_type(&dev->parent) == RT_Object_Class_Device);
+
+ dev->tx_complete = tx_done;
+
+ return RT_EOK;
+}
+RTM_EXPORT(rt_device_set_tx_complete);
+
+#endif /* RT_USING_DEVICE */
diff --git a/User/system/rt-thread/src/idle.c b/User/system/rt-thread/src/idle.c
new file mode 100644
index 0000000..4b8a002
--- /dev/null
+++ b/User/system/rt-thread/src/idle.c
@@ -0,0 +1,360 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2006-03-23 Bernard the first version
+ * 2010-11-10 Bernard add cleanup callback function in thread exit.
+ * 2012-12-29 Bernard fix compiling warning.
+ * 2013-12-21 Grissiom let rt_thread_idle_excute loop until there is no
+ * dead thread.
+ * 2016-08-09 ArdaFu add method to get the handler of the idle thread.
+ * 2018-02-07 Bernard lock scheduler to protect tid->cleanup.
+ * 2018-07-14 armink add idle hook list
+ * 2018-11-22 Jesven add per cpu idle task
+ * combine the code of primary and secondary cpu
+ * 2021-11-15 THEWON Remove duplicate work between idle and _thread_exit
+ */
+
+#include
+#include
+
+#ifdef RT_USING_MODULE
+#include
+#endif /* RT_USING_MODULE */
+
+#ifdef RT_USING_HOOK
+#ifndef RT_USING_IDLE_HOOK
+#define RT_USING_IDLE_HOOK
+#endif /* RT_USING_IDLE_HOOK */
+#endif /* RT_USING_HOOK */
+
+#ifndef IDLE_THREAD_STACK_SIZE
+#if defined (RT_USING_IDLE_HOOK) || defined(RT_USING_HEAP)
+#define IDLE_THREAD_STACK_SIZE 256
+#else
+#define IDLE_THREAD_STACK_SIZE 128
+#endif /* (RT_USING_IDLE_HOOK) || defined(RT_USING_HEAP) */
+#endif /* IDLE_THREAD_STACK_SIZE */
+
+#ifdef RT_USING_SMP
+#define _CPUS_NR RT_CPUS_NR
+#else
+#define _CPUS_NR 1
+#endif /* RT_USING_SMP */
+
+static rt_list_t _rt_thread_defunct = RT_LIST_OBJECT_INIT(_rt_thread_defunct);
+
+static struct rt_thread idle[_CPUS_NR];
+ALIGN(RT_ALIGN_SIZE)
+static rt_uint8_t rt_thread_stack[_CPUS_NR][IDLE_THREAD_STACK_SIZE];
+
+#ifdef RT_USING_SMP
+#ifndef SYSTEM_THREAD_STACK_SIZE
+#define SYSTEM_THREAD_STACK_SIZE IDLE_THREAD_STACK_SIZE
+#endif
+static struct rt_thread rt_system_thread;
+ALIGN(RT_ALIGN_SIZE)
+static rt_uint8_t rt_system_stack[SYSTEM_THREAD_STACK_SIZE];
+static struct rt_semaphore system_sem;
+#endif
+
+#ifdef RT_USING_IDLE_HOOK
+#ifndef RT_IDLE_HOOK_LIST_SIZE
+#define RT_IDLE_HOOK_LIST_SIZE 4
+#endif /* RT_IDLE_HOOK_LIST_SIZE */
+
+static void (*idle_hook_list[RT_IDLE_HOOK_LIST_SIZE])(void);
+
+/**
+ * @brief This function sets a hook function to idle thread loop. When the system performs
+ * idle loop, this hook function should be invoked.
+ *
+ * @param hook the specified hook function.
+ *
+ * @return RT_EOK: set OK.
+ * -RT_EFULL: hook list is full.
+ *
+ * @note the hook function must be simple and never be blocked or suspend.
+ */
+rt_err_t rt_thread_idle_sethook(void (*hook)(void))
+{
+ rt_size_t i;
+ rt_base_t level;
+ rt_err_t ret = -RT_EFULL;
+
+ /* disable interrupt */
+ level = rt_hw_interrupt_disable();
+
+ for (i = 0; i < RT_IDLE_HOOK_LIST_SIZE; i++)
+ {
+ if (idle_hook_list[i] == RT_NULL)
+ {
+ idle_hook_list[i] = hook;
+ ret = RT_EOK;
+ break;
+ }
+ }
+ /* enable interrupt */
+ rt_hw_interrupt_enable(level);
+
+ return ret;
+}
+
+/**
+ * @brief delete the idle hook on hook list.
+ *
+ * @param hook the specified hook function.
+ *
+ * @return RT_EOK: delete OK.
+ * -RT_ENOSYS: hook was not found.
+ */
+rt_err_t rt_thread_idle_delhook(void (*hook)(void))
+{
+ rt_size_t i;
+ rt_base_t level;
+ rt_err_t ret = -RT_ENOSYS;
+
+ /* disable interrupt */
+ level = rt_hw_interrupt_disable();
+
+ for (i = 0; i < RT_IDLE_HOOK_LIST_SIZE; i++)
+ {
+ if (idle_hook_list[i] == hook)
+ {
+ idle_hook_list[i] = RT_NULL;
+ ret = RT_EOK;
+ break;
+ }
+ }
+ /* enable interrupt */
+ rt_hw_interrupt_enable(level);
+
+ return ret;
+}
+
+#endif /* RT_USING_IDLE_HOOK */
+
+/**
+ * @brief Enqueue a thread to defunct queue.
+ *
+ * @note It must be called between rt_hw_interrupt_disable and rt_hw_interrupt_enable
+ */
+void rt_thread_defunct_enqueue(rt_thread_t thread)
+{
+ rt_list_insert_after(&_rt_thread_defunct, &thread->tlist);
+#ifdef RT_USING_SMP
+ rt_sem_release(&system_sem);
+#endif
+}
+
+/**
+ * @brief Dequeue a thread from defunct queue.
+ */
+rt_thread_t rt_thread_defunct_dequeue(void)
+{
+ rt_base_t level;
+ rt_thread_t thread = RT_NULL;
+ rt_list_t *l = &_rt_thread_defunct;
+
+#ifdef RT_USING_SMP
+ /* disable interrupt */
+ level = rt_hw_interrupt_disable();
+ if (l->next != l)
+ {
+ thread = rt_list_entry(l->next,
+ struct rt_thread,
+ tlist);
+ rt_list_remove(&(thread->tlist));
+ }
+ rt_hw_interrupt_enable(level);
+#else
+ if (l->next != l)
+ {
+ thread = rt_list_entry(l->next,
+ struct rt_thread,
+ tlist);
+ level = rt_hw_interrupt_disable();
+ rt_list_remove(&(thread->tlist));
+ rt_hw_interrupt_enable(level);
+ }
+#endif
+ return thread;
+}
+
+/**
+ * @brief This function will perform system background job when system idle.
+ */
+static void rt_defunct_execute(void)
+{
+ /* Loop until there is no dead thread. So one call to rt_defunct_execute
+ * will do all the cleanups. */
+ while (1)
+ {
+ rt_thread_t thread;
+ rt_bool_t object_is_systemobject;
+ void (*cleanup)(struct rt_thread *tid);
+
+#ifdef RT_USING_MODULE
+ struct rt_dlmodule *module = RT_NULL;
+#endif
+ /* get defunct thread */
+ thread = rt_thread_defunct_dequeue();
+ if (thread == RT_NULL)
+ {
+ break;
+ }
+#ifdef RT_USING_MODULE
+ module = (struct rt_dlmodule*)thread->module_id;
+ if (module)
+ {
+ dlmodule_destroy(module);
+ }
+#endif
+
+#ifdef RT_USING_SIGNALS
+ rt_thread_free_sig(thread);
+#endif
+
+ /* store the point of "thread->cleanup" avoid to lose */
+ cleanup = thread->cleanup;
+
+ /* if it's a system object, not delete it */
+ object_is_systemobject = rt_object_is_systemobject((rt_object_t)thread);
+ if (object_is_systemobject == RT_TRUE)
+ {
+ /* detach this object */
+ rt_object_detach((rt_object_t)thread);
+ }
+
+ /* invoke thread cleanup */
+ if (cleanup != RT_NULL)
+ {
+ cleanup(thread);
+ }
+
+#ifdef RT_USING_HEAP
+ /* if need free, delete it */
+ if (object_is_systemobject == RT_FALSE)
+ {
+ /* release thread's stack */
+ RT_KERNEL_FREE(thread->stack_addr);
+ /* delete thread object */
+ rt_object_delete((rt_object_t)thread);
+ }
+#endif
+ }
+}
+
+static void rt_thread_idle_entry(void *parameter)
+{
+#ifdef RT_USING_SMP
+ if (rt_hw_cpu_id() != 0)
+ {
+ while (1)
+ {
+ rt_hw_secondary_cpu_idle_exec();
+ }
+ }
+#endif /* RT_USING_SMP */
+
+ while (1)
+ {
+#ifdef RT_USING_IDLE_HOOK
+ rt_size_t i;
+ void (*idle_hook)(void);
+
+ for (i = 0; i < RT_IDLE_HOOK_LIST_SIZE; i++)
+ {
+ idle_hook = idle_hook_list[i];
+ if (idle_hook != RT_NULL)
+ {
+ idle_hook();
+ }
+ }
+#endif /* RT_USING_IDLE_HOOK */
+
+#ifndef RT_USING_SMP
+ rt_defunct_execute();
+#endif /* RT_USING_SMP */
+
+#ifdef RT_USING_PM
+ void rt_system_power_manager(void);
+ rt_system_power_manager();
+#endif /* RT_USING_PM */
+ }
+}
+
+#ifdef RT_USING_SMP
+static void rt_thread_system_entry(void *parameter)
+{
+ while (1)
+ {
+ rt_sem_take(&system_sem, RT_WAITING_FOREVER);
+ rt_defunct_execute();
+ }
+}
+#endif
+
+/**
+ * @brief This function will initialize idle thread, then start it.
+ *
+ * @note this function must be invoked when system init.
+ */
+void rt_thread_idle_init(void)
+{
+ rt_ubase_t i;
+ char tidle_name[RT_NAME_MAX];
+
+ for (i = 0; i < _CPUS_NR; i++)
+ {
+ rt_sprintf(tidle_name, "tidle%d", i);
+ rt_thread_init(&idle[i],
+ tidle_name,
+ rt_thread_idle_entry,
+ RT_NULL,
+ &rt_thread_stack[i][0],
+ sizeof(rt_thread_stack[i]),
+ RT_THREAD_PRIORITY_MAX - 1,
+ 32);
+#ifdef RT_USING_SMP
+ rt_thread_control(&idle[i], RT_THREAD_CTRL_BIND_CPU, (void*)i);
+#endif /* RT_USING_SMP */
+ /* startup */
+ rt_thread_startup(&idle[i]);
+ }
+
+#ifdef RT_USING_SMP
+ RT_ASSERT(RT_THREAD_PRIORITY_MAX > 2);
+
+ rt_sem_init(&system_sem, "defunct", 1, RT_IPC_FLAG_FIFO);
+
+ /* create defunct thread */
+ rt_thread_init(&rt_system_thread,
+ "tsystem",
+ rt_thread_system_entry,
+ RT_NULL,
+ rt_system_stack,
+ sizeof(rt_system_stack),
+ RT_THREAD_PRIORITY_MAX - 2,
+ 32);
+ /* startup */
+ rt_thread_startup(&rt_system_thread);
+#endif
+}
+
+/**
+ * @brief This function will get the handler of the idle thread.
+ */
+rt_thread_t rt_thread_idle_gethandler(void)
+{
+#ifdef RT_USING_SMP
+ int id = rt_hw_cpu_id();
+#else
+ int id = 0;
+#endif /* RT_USING_SMP */
+
+ return (rt_thread_t)(&idle[id]);
+}
diff --git a/User/system/rt-thread/src/ipc.c b/User/system/rt-thread/src/ipc.c
new file mode 100644
index 0000000..4a6244a
--- /dev/null
+++ b/User/system/rt-thread/src/ipc.c
@@ -0,0 +1,3288 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2006-03-14 Bernard the first version
+ * 2006-04-25 Bernard implement semaphore
+ * 2006-05-03 Bernard add RT_IPC_DEBUG
+ * modify the type of IPC waiting time to rt_int32_t
+ * 2006-05-10 Bernard fix the semaphore take bug and add IPC object
+ * 2006-05-12 Bernard implement mailbox and message queue
+ * 2006-05-20 Bernard implement mutex
+ * 2006-05-23 Bernard implement fast event
+ * 2006-05-24 Bernard implement event
+ * 2006-06-03 Bernard fix the thread timer init bug
+ * 2006-06-05 Bernard fix the mutex release bug
+ * 2006-06-07 Bernard fix the message queue send bug
+ * 2006-08-04 Bernard add hook support
+ * 2009-05-21 Yi.qiu fix the sem release bug
+ * 2009-07-18 Bernard fix the event clear bug
+ * 2009-09-09 Bernard remove fast event and fix ipc release bug
+ * 2009-10-10 Bernard change semaphore and mutex value to unsigned value
+ * 2009-10-25 Bernard change the mb/mq receive timeout to 0 if the
+ * re-calculated delta tick is a negative number.
+ * 2009-12-16 Bernard fix the rt_ipc_object_suspend issue when IPC flag
+ * is RT_IPC_FLAG_PRIO
+ * 2010-01-20 mbbill remove rt_ipc_object_decrease function.
+ * 2010-04-20 Bernard move memcpy outside interrupt disable in mq
+ * 2010-10-26 yi.qiu add module support in rt_mp_delete and rt_mq_delete
+ * 2010-11-10 Bernard add IPC reset command implementation.
+ * 2011-12-18 Bernard add more parameter checking in message queue
+ * 2013-09-14 Grissiom add an option check in rt_event_recv
+ * 2018-10-02 Bernard add 64bit support for mailbox
+ * 2019-09-16 tyx add send wait support for message queue
+ * 2020-07-29 Meco Man fix thread->event_set/event_info when received an
+ * event without pending
+ * 2020-10-11 Meco Man add value overflow-check code
+ * 2021-01-03 Meco Man implement rt_mb_urgent()
+ * 2021-05-30 Meco Man implement rt_mutex_trytake()
+ * 2022-01-07 Gabriel Moving __on_rt_xxxxx_hook to ipc.c
+ * 2022-01-24 THEWON let rt_mutex_take return thread->error when using signal
+ * 2022-04-08 Stanley Correct descriptions
+ */
+
+#include
+#include
+
+#ifndef __on_rt_object_trytake_hook
+ #define __on_rt_object_trytake_hook(parent) __ON_HOOK_ARGS(rt_object_trytake_hook, (parent))
+#endif
+#ifndef __on_rt_object_take_hook
+ #define __on_rt_object_take_hook(parent) __ON_HOOK_ARGS(rt_object_take_hook, (parent))
+#endif
+#ifndef __on_rt_object_put_hook
+ #define __on_rt_object_put_hook(parent) __ON_HOOK_ARGS(rt_object_put_hook, (parent))
+#endif
+
+#if defined(RT_USING_HOOK) && defined(RT_HOOK_USING_FUNC_PTR)
+extern void (*rt_object_trytake_hook)(struct rt_object *object);
+extern void (*rt_object_take_hook)(struct rt_object *object);
+extern void (*rt_object_put_hook)(struct rt_object *object);
+#endif /* RT_USING_HOOK */
+
+/**
+ * @addtogroup IPC
+ */
+
+/**@{*/
+
+/**
+ * @brief This function will initialize an IPC object, such as semaphore, mutex, messagequeue and mailbox.
+ *
+ * @note Executing this function will complete an initialization of the suspend thread list of the ipc object.
+ *
+ * @param ipc is a pointer to the IPC object.
+ *
+ * @return Return the operation status. When the return value is RT_EOK, the initialization is successful.
+ * When the return value is any other values, it means the initialization failed.
+ *
+ * @warning This function can be called from all IPC initialization and creation.
+ */
+rt_inline rt_err_t _ipc_object_init(struct rt_ipc_object *ipc)
+{
+ /* initialize ipc object */
+ rt_list_init(&(ipc->suspend_thread));
+
+ return RT_EOK;
+}
+
+
+/**
+ * @brief This function will suspend a thread to a IPC object list.
+ *
+ * @param list is a pointer to a suspended thread list of the IPC object.
+ *
+ * @param thread is a pointer to the thread object to be suspended.
+ *
+ * @param flag is a flag for the thread object to be suspended. It determines how the thread is suspended.
+ * The flag can be ONE of the following values:
+ *
+ * RT_IPC_FLAG_PRIO The pending threads will queue in order of priority.
+ *
+ * RT_IPC_FLAG_FIFO The pending threads will queue in the first-in-first-out method
+ * (also known as first-come-first-served (FCFS) scheduling strategy).
+ *
+ * NOTE: RT_IPC_FLAG_FIFO is a non-real-time scheduling mode. It is strongly recommended to use
+ * RT_IPC_FLAG_PRIO to ensure the thread is real-time UNLESS your applications concern about
+ * the first-in-first-out principle, and you clearly understand that all threads involved in
+ * this semaphore will become non-real-time threads.
+ *
+ * @return Return the operation status. When the return value is RT_EOK, the function is successfully executed.
+ * When the return value is any other values, it means the initialization failed.
+ *
+ * @warning This function can ONLY be called in the thread context, you can use RT_DEBUG_IN_THREAD_CONTEXT to
+ * check the context.
+ * In addition, this function is generally called by the following functions:
+ * rt_sem_take(), rt_mutex_take(), rt_event_recv(), rt_mb_send_wait(),
+ * rt_mb_recv(), rt_mq_recv(), rt_mq_send_wait()
+ */
+rt_inline rt_err_t _ipc_list_suspend(rt_list_t *list,
+ struct rt_thread *thread,
+ rt_uint8_t flag)
+{
+ /* suspend thread */
+ rt_thread_suspend(thread);
+
+ switch (flag)
+ {
+ case RT_IPC_FLAG_FIFO:
+ rt_list_insert_before(list, &(thread->tlist));
+ break; /* RT_IPC_FLAG_FIFO */
+
+ case RT_IPC_FLAG_PRIO:
+ {
+ struct rt_list_node *n;
+ struct rt_thread *sthread;
+
+ /* find a suitable position */
+ for (n = list->next; n != list; n = n->next)
+ {
+ sthread = rt_list_entry(n, struct rt_thread, tlist);
+
+ /* find out */
+ if (thread->current_priority < sthread->current_priority)
+ {
+ /* insert this thread before the sthread */
+ rt_list_insert_before(&(sthread->tlist), &(thread->tlist));
+ break;
+ }
+ }
+
+ /*
+ * not found a suitable position,
+ * append to the end of suspend_thread list
+ */
+ if (n == list)
+ rt_list_insert_before(list, &(thread->tlist));
+ }
+ break;/* RT_IPC_FLAG_PRIO */
+
+ default:
+ RT_ASSERT(0);
+ break;
+ }
+
+ return RT_EOK;
+}
+
+
+/**
+ * @brief This function will resume a thread.
+ *
+ * @note This function will resume the first thread in the list of a IPC object.
+ * 1. remove the thread from suspend queue of a IPC object.
+ * 2. put the thread into system ready queue.
+ *
+ * By contrast, the rt_ipc_list_resume_all() function will resume all suspended threads
+ * in the list of a IPC object.
+ *
+ * @param list is a pointer to a suspended thread list of the IPC object.
+ *
+ * @return Return the operation status. When the return value is RT_EOK, the function is successfully executed.
+ * When the return value is any other values, it means this operation failed.
+ *
+ * @warning This function is generally called by the following functions:
+ * rt_sem_release(), rt_mutex_release(), rt_mb_send_wait(), rt_mq_send_wait(),
+ * rt_mb_urgent(), rt_mb_recv(), rt_mq_urgent(), rt_mq_recv(),
+ */
+rt_inline rt_err_t _ipc_list_resume(rt_list_t *list)
+{
+ struct rt_thread *thread;
+
+ /* get thread entry */
+ thread = rt_list_entry(list->next, struct rt_thread, tlist);
+
+ RT_DEBUG_LOG(RT_DEBUG_IPC, ("resume thread:%s\n", thread->name));
+
+ /* resume it */
+ rt_thread_resume(thread);
+
+ return RT_EOK;
+}
+
+
+/**
+ * @brief This function will resume all suspended threads in the IPC object list,
+ * including the suspended list of IPC object, and private list of mailbox etc.
+ *
+ * @note This function will resume all threads in the IPC object list.
+ * By contrast, the rt_ipc_list_resume() function will resume a suspended thread in the list of a IPC object.
+ *
+ * @param list is a pointer to a suspended thread list of the IPC object.
+ *
+ * @return Return the operation status. When the return value is RT_EOK, the function is successfully executed.
+ * When the return value is any other values, it means this operation failed.
+ *
+ */
+rt_inline rt_err_t _ipc_list_resume_all(rt_list_t *list)
+{
+ struct rt_thread *thread;
+ rt_base_t level;
+
+ /* wakeup all suspended threads */
+ while (!rt_list_isempty(list))
+ {
+ /* disable interrupt */
+ level = rt_hw_interrupt_disable();
+
+ /* get next suspended thread */
+ thread = rt_list_entry(list->next, struct rt_thread, tlist);
+ /* set error code to RT_ERROR */
+ thread->error = -RT_ERROR;
+
+ /*
+ * resume thread
+ * In rt_thread_resume function, it will remove current thread from
+ * suspended list
+ */
+ rt_thread_resume(thread);
+
+ /* enable interrupt */
+ rt_hw_interrupt_enable(level);
+ }
+
+ return RT_EOK;
+}
+
+/**@}*/
+
+#ifdef RT_USING_SEMAPHORE
+/**
+ * @addtogroup semaphore
+ */
+
+/**@{*/
+/**
+ * @brief This function will initialize a static semaphore object.
+ *
+ * @note For the static semaphore object, its memory space is allocated by the compiler during compiling,
+ * and shall placed on the read-write data segment or on the uninitialized data segment.
+ * By contrast, the rt_sem_create() function will allocate memory space automatically and initialize
+ * the semaphore.
+ *
+ * @see rt_sem_create()
+ *
+ * @param sem is a pointer to the semaphore to initialize. It is assumed that storage for the semaphore will be
+ * allocated in your application.
+ *
+ * @param name is a pointer to the name you would like to give the semaphore.
+ *
+ * @param value is the initial value for the semaphore.
+ * If used to share resources, you should initialize the value as the number of available resources.
+ * If used to signal the occurrence of an event, you should initialize the value as 0.
+ *
+ * @param flag is the semaphore flag, which determines the queuing way of how multiple threads wait
+ * when the semaphore is not available.
+ * The semaphore flag can be ONE of the following values:
+ *
+ * RT_IPC_FLAG_PRIO The pending threads will queue in order of priority.
+ *
+ * RT_IPC_FLAG_FIFO The pending threads will queue in the first-in-first-out method
+ * (also known as first-come-first-served (FCFS) scheduling strategy).
+ *
+ * NOTE: RT_IPC_FLAG_FIFO is a non-real-time scheduling mode. It is strongly recommended to
+ * use RT_IPC_FLAG_PRIO to ensure the thread is real-time UNLESS your applications concern about
+ * the first-in-first-out principle, and you clearly understand that all threads involved in
+ * this semaphore will become non-real-time threads.
+ *
+ * @return Return the operation status. When the return value is RT_EOK, the initialization is successful.
+ * If the return value is any other values, it represents the initialization failed.
+ *
+ * @warning This function can ONLY be called from threads.
+ */
+rt_err_t rt_sem_init(rt_sem_t sem,
+ const char *name,
+ rt_uint32_t value,
+ rt_uint8_t flag)
+{
+ RT_ASSERT(sem != RT_NULL);
+ RT_ASSERT(value < 0x10000U);
+ RT_ASSERT((flag == RT_IPC_FLAG_FIFO) || (flag == RT_IPC_FLAG_PRIO));
+
+ /* initialize object */
+ rt_object_init(&(sem->parent.parent), RT_Object_Class_Semaphore, name);
+
+ /* initialize ipc object */
+ _ipc_object_init(&(sem->parent));
+
+ /* set initial value */
+ sem->value = (rt_uint16_t)value;
+
+ /* set parent */
+ sem->parent.parent.flag = flag;
+
+ return RT_EOK;
+}
+RTM_EXPORT(rt_sem_init);
+
+
+/**
+ * @brief This function will detach a static semaphore object.
+ *
+ * @note This function is used to detach a static semaphore object which is initialized by rt_sem_init() function.
+ * By contrast, the rt_sem_delete() function will delete a semaphore object.
+ * When the semaphore is successfully detached, it will resume all suspended threads in the semaphore list.
+ *
+ * @see rt_sem_delete()
+ *
+ * @param sem is a pointer to a semaphore object to be detached.
+ *
+ * @return Return the operation status. When the return value is RT_EOK, the initialization is successful.
+ * If the return value is any other values, it means that the semaphore detach failed.
+ *
+ * @warning This function can ONLY detach a static semaphore initialized by the rt_sem_init() function.
+ * If the semaphore is created by the rt_sem_create() function, you MUST NOT USE this function to detach it,
+ * ONLY USE the rt_sem_delete() function to complete the deletion.
+ */
+rt_err_t rt_sem_detach(rt_sem_t sem)
+{
+ /* parameter check */
+ RT_ASSERT(sem != RT_NULL);
+ RT_ASSERT(rt_object_get_type(&sem->parent.parent) == RT_Object_Class_Semaphore);
+ RT_ASSERT(rt_object_is_systemobject(&sem->parent.parent));
+
+ /* wakeup all suspended threads */
+ _ipc_list_resume_all(&(sem->parent.suspend_thread));
+
+ /* detach semaphore object */
+ rt_object_detach(&(sem->parent.parent));
+
+ return RT_EOK;
+}
+RTM_EXPORT(rt_sem_detach);
+
+#ifdef RT_USING_HEAP
+/**
+ * @brief Creating a semaphore object.
+ *
+ * @note For the semaphore object, its memory space is allocated automatically.
+ * By contrast, the rt_sem_init() function will initialize a static semaphore object.
+ *
+ * @see rt_sem_init()
+ *
+ * @param name is a pointer to the name you would like to give the semaphore.
+ *
+ * @param value is the initial value for the semaphore.
+ * If used to share resources, you should initialize the value as the number of available resources.
+ * If used to signal the occurrence of an event, you should initialize the value as 0.
+ *
+ * @param flag is the semaphore flag, which determines the queuing way of how multiple threads wait
+ * when the semaphore is not available.
+ * The semaphore flag can be ONE of the following values:
+ *
+ * RT_IPC_FLAG_PRIO The pending threads will queue in order of priority.
+ *
+ * RT_IPC_FLAG_FIFO The pending threads will queue in the first-in-first-out method
+ * (also known as first-come-first-served (FCFS) scheduling strategy).
+ *
+ * NOTE: RT_IPC_FLAG_FIFO is a non-real-time scheduling mode. It is strongly recommended to
+ * use RT_IPC_FLAG_PRIO to ensure the thread is real-time UNLESS your applications concern about
+ * the first-in-first-out principle, and you clearly understand that all threads involved in
+ * this semaphore will become non-real-time threads.
+ *
+ * @return Return a pointer to the semaphore object. When the return value is RT_NULL, it means the creation failed.
+ *
+ * @warning This function can NOT be called in interrupt context. You can use macor RT_DEBUG_NOT_IN_INTERRUPT to check it.
+ */
+rt_sem_t rt_sem_create(const char *name, rt_uint32_t value, rt_uint8_t flag)
+{
+ rt_sem_t sem;
+
+ RT_ASSERT(value < 0x10000U);
+ RT_ASSERT((flag == RT_IPC_FLAG_FIFO) || (flag == RT_IPC_FLAG_PRIO));
+
+ RT_DEBUG_NOT_IN_INTERRUPT;
+
+ /* allocate object */
+ sem = (rt_sem_t)rt_object_allocate(RT_Object_Class_Semaphore, name);
+ if (sem == RT_NULL)
+ return sem;
+
+ /* initialize ipc object */
+ _ipc_object_init(&(sem->parent));
+
+ /* set initial value */
+ sem->value = value;
+
+ /* set parent */
+ sem->parent.parent.flag = flag;
+
+ return sem;
+}
+RTM_EXPORT(rt_sem_create);
+
+
+/**
+ * @brief This function will delete a semaphore object and release the memory space.
+ *
+ * @note This function is used to delete a semaphore object which is created by the rt_sem_create() function.
+ * By contrast, the rt_sem_detach() function will detach a static semaphore object.
+ * When the semaphore is successfully deleted, it will resume all suspended threads in the semaphore list.
+ *
+ * @see rt_sem_detach()
+ *
+ * @param sem is a pointer to a semaphore object to be deleted.
+ *
+ * @return Return the operation status. When the return value is RT_EOK, the operation is successful.
+ * If the return value is any other values, it means that the semaphore detach failed.
+ *
+ * @warning This function can ONLY delete a semaphore initialized by the rt_sem_create() function.
+ * If the semaphore is initialized by the rt_sem_init() function, you MUST NOT USE this function to delete it,
+ * ONLY USE the rt_sem_detach() function to complete the detachment.
+ */
+rt_err_t rt_sem_delete(rt_sem_t sem)
+{
+ /* parameter check */
+ RT_ASSERT(sem != RT_NULL);
+ RT_ASSERT(rt_object_get_type(&sem->parent.parent) == RT_Object_Class_Semaphore);
+ RT_ASSERT(rt_object_is_systemobject(&sem->parent.parent) == RT_FALSE);
+
+ RT_DEBUG_NOT_IN_INTERRUPT;
+
+ /* wakeup all suspended threads */
+ _ipc_list_resume_all(&(sem->parent.suspend_thread));
+
+ /* delete semaphore object */
+ rt_object_delete(&(sem->parent.parent));
+
+ return RT_EOK;
+}
+RTM_EXPORT(rt_sem_delete);
+#endif /* RT_USING_HEAP */
+
+
+/**
+ * @brief This function will take a semaphore, if the semaphore is unavailable, the thread shall wait for
+ * the semaphore up to a specified time.
+ *
+ * @note When this function is called, the count value of the sem->value will decrease 1 until it is equal to 0.
+ * When the sem->value is 0, it means that the semaphore is unavailable. At this time, it will suspend the
+ * thread preparing to take the semaphore.
+ * On the contrary, the rt_sem_release() function will increase the count value of sem->value by 1 each time.
+ *
+ * @see rt_sem_trytake()
+ *
+ * @param sem is a pointer to a semaphore object.
+ *
+ * @param timeout is a timeout period (unit: an OS tick). If the semaphore is unavailable, the thread will wait for
+ * the semaphore up to the amount of time specified by this parameter.
+ *
+ * NOTE:
+ * If use Macro RT_WAITING_FOREVER to set this parameter, which means that when the
+ * message is unavailable in the queue, the thread will be waiting forever.
+ * If use macro RT_WAITING_NO to set this parameter, which means that this
+ * function is non-blocking and will return immediately.
+ *
+ * @return Return the operation status. ONLY When the return value is RT_EOK, the operation is successful.
+ * If the return value is any other values, it means that the semaphore take failed.
+ *
+ * @warning This function can ONLY be called in the thread context. It MUST NOT BE called in interrupt context.
+ */
+rt_err_t rt_sem_take(rt_sem_t sem, rt_int32_t timeout)
+{
+ rt_base_t level;
+ struct rt_thread *thread;
+
+ /* parameter check */
+ RT_ASSERT(sem != RT_NULL);
+ RT_ASSERT(rt_object_get_type(&sem->parent.parent) == RT_Object_Class_Semaphore);
+
+ RT_OBJECT_HOOK_CALL(rt_object_trytake_hook, (&(sem->parent.parent)));
+
+ /* disable interrupt */
+ level = rt_hw_interrupt_disable();
+
+ RT_DEBUG_LOG(RT_DEBUG_IPC, ("thread %s take sem:%s, which value is: %d\n",
+ rt_thread_self()->name,
+ ((struct rt_object *)sem)->name,
+ sem->value));
+
+ if (sem->value > 0)
+ {
+ /* semaphore is available */
+ sem->value --;
+
+ /* enable interrupt */
+ rt_hw_interrupt_enable(level);
+ }
+ else
+ {
+ /* no waiting, return with timeout */
+ if (timeout == 0)
+ {
+ rt_hw_interrupt_enable(level);
+
+ return -RT_ETIMEOUT;
+ }
+ else
+ {
+ /* current context checking */
+ RT_DEBUG_SCHEDULER_AVAILABLE(RT_TRUE);
+
+ /* semaphore is unavailable, push to suspend list */
+ /* get current thread */
+ thread = rt_thread_self();
+
+ /* reset thread error number */
+ thread->error = RT_EOK;
+
+ RT_DEBUG_LOG(RT_DEBUG_IPC, ("sem take: suspend thread - %s\n",
+ thread->name));
+
+ /* suspend thread */
+ _ipc_list_suspend(&(sem->parent.suspend_thread),
+ thread,
+ sem->parent.parent.flag);
+
+ /* has waiting time, start thread timer */
+ if (timeout > 0)
+ {
+ RT_DEBUG_LOG(RT_DEBUG_IPC, ("set thread:%s to timer list\n",
+ thread->name));
+
+ /* reset the timeout of thread timer and start it */
+ rt_timer_control(&(thread->thread_timer),
+ RT_TIMER_CTRL_SET_TIME,
+ &timeout);
+ rt_timer_start(&(thread->thread_timer));
+ }
+
+ /* enable interrupt */
+ rt_hw_interrupt_enable(level);
+
+ /* do schedule */
+ rt_schedule();
+
+ if (thread->error != RT_EOK)
+ {
+ return thread->error;
+ }
+ }
+ }
+
+ RT_OBJECT_HOOK_CALL(rt_object_take_hook, (&(sem->parent.parent)));
+
+ return RT_EOK;
+}
+RTM_EXPORT(rt_sem_take);
+
+
+/**
+ * @brief This function will try to take a semaphore, if the semaphore is unavailable, the thread returns immediately.
+ *
+ * @note This function is very similar to the rt_sem_take() function, when the semaphore is not available,
+ * the rt_sem_trytake() function will return immediately without waiting for a timeout.
+ * In other words, rt_sem_trytake(sem) has the same effect as rt_sem_take(sem, 0).
+ *
+ * @see rt_sem_take()
+ *
+ * @param sem is a pointer to a semaphore object.
+ *
+ * @return Return the operation status. ONLY When the return value is RT_EOK, the operation is successful.
+ * If the return value is any other values, it means that the semaphore take failed.
+ */
+rt_err_t rt_sem_trytake(rt_sem_t sem)
+{
+ return rt_sem_take(sem, RT_WAITING_NO);
+}
+RTM_EXPORT(rt_sem_trytake);
+
+
+/**
+ * @brief This function will release a semaphore. If there is thread suspended on the semaphore, it will get resumed.
+ *
+ * @note If there are threads suspended on this semaphore, the first thread in the list of this semaphore object
+ * will be resumed, and a thread scheduling (rt_schedule) will be executed.
+ * If no threads are suspended on this semaphore, the count value sem->value of this semaphore will increase by 1.
+ *
+ * @param sem is a pointer to a semaphore object.
+ *
+ * @return Return the operation status. When the return value is RT_EOK, the operation is successful.
+ * If the return value is any other values, it means that the semaphore release failed.
+ */
+rt_err_t rt_sem_release(rt_sem_t sem)
+{
+ rt_base_t level;
+ rt_bool_t need_schedule;
+
+ /* parameter check */
+ RT_ASSERT(sem != RT_NULL);
+ RT_ASSERT(rt_object_get_type(&sem->parent.parent) == RT_Object_Class_Semaphore);
+
+ RT_OBJECT_HOOK_CALL(rt_object_put_hook, (&(sem->parent.parent)));
+
+ need_schedule = RT_FALSE;
+
+ /* disable interrupt */
+ level = rt_hw_interrupt_disable();
+
+ RT_DEBUG_LOG(RT_DEBUG_IPC, ("thread %s releases sem:%s, which value is: %d\n",
+ rt_thread_self()->name,
+ ((struct rt_object *)sem)->name,
+ sem->value));
+
+ if (!rt_list_isempty(&sem->parent.suspend_thread))
+ {
+ /* resume the suspended thread */
+ _ipc_list_resume(&(sem->parent.suspend_thread));
+ need_schedule = RT_TRUE;
+ }
+ else
+ {
+ if(sem->value < RT_SEM_VALUE_MAX)
+ {
+ sem->value ++; /* increase value */
+ }
+ else
+ {
+ rt_hw_interrupt_enable(level); /* enable interrupt */
+ return -RT_EFULL; /* value overflowed */
+ }
+ }
+
+ /* enable interrupt */
+ rt_hw_interrupt_enable(level);
+
+ /* resume a thread, re-schedule */
+ if (need_schedule == RT_TRUE)
+ rt_schedule();
+
+ return RT_EOK;
+}
+RTM_EXPORT(rt_sem_release);
+
+
+/**
+ * @brief This function will set some extra attributions of a semaphore object.
+ *
+ * @note Currently this function only supports the RT_IPC_CMD_RESET command to reset the semaphore.
+ *
+ * @param sem is a pointer to a semaphore object.
+ *
+ * @param cmd is a command word used to configure some attributions of the semaphore.
+ *
+ * @param arg is the argument of the function to execute the command.
+ *
+ * @return Return the operation status. When the return value is RT_EOK, the operation is successful.
+ * If the return value is any other values, it means that this function failed to execute.
+ */
+rt_err_t rt_sem_control(rt_sem_t sem, int cmd, void *arg)
+{
+ rt_base_t level;
+
+ /* parameter check */
+ RT_ASSERT(sem != RT_NULL);
+ RT_ASSERT(rt_object_get_type(&sem->parent.parent) == RT_Object_Class_Semaphore);
+
+ if (cmd == RT_IPC_CMD_RESET)
+ {
+ rt_ubase_t value;
+
+ /* get value */
+ value = (rt_ubase_t)arg;
+ /* disable interrupt */
+ level = rt_hw_interrupt_disable();
+
+ /* resume all waiting thread */
+ _ipc_list_resume_all(&sem->parent.suspend_thread);
+
+ /* set new value */
+ sem->value = (rt_uint16_t)value;
+
+ /* enable interrupt */
+ rt_hw_interrupt_enable(level);
+
+ rt_schedule();
+
+ return RT_EOK;
+ }
+
+ return -RT_ERROR;
+}
+RTM_EXPORT(rt_sem_control);
+
+/**@}*/
+#endif /* RT_USING_SEMAPHORE */
+
+#ifdef RT_USING_MUTEX
+/**
+ * @addtogroup mutex
+ */
+
+/**@{*/
+
+/**
+ * @brief Initialize a static mutex object.
+ *
+ * @note For the static mutex object, its memory space is allocated by the compiler during compiling,
+ * and shall placed on the read-write data segment or on the uninitialized data segment.
+ * By contrast, the rt_mutex_create() function will automatically allocate memory space
+ * and initialize the mutex.
+ *
+ * @see rt_mutex_create()
+ *
+ * @param mutex is a pointer to the mutex to initialize. It is assumed that storage for the mutex will be
+ * allocated in your application.
+ *
+ * @param name is a pointer to the name that given to the mutex.
+ *
+ * @param flag is the mutex flag, which determines the queuing way of how multiple threads wait
+ * when the mutex is not available.
+ * NOTE: This parameter has been obsoleted. It can be RT_IPC_FLAG_PRIO, RT_IPC_FLAG_FIFO or RT_NULL.
+ *
+ * @return Return the operation status. When the return value is RT_EOK, the initialization is successful.
+ * If the return value is any other values, it represents the initialization failed.
+ *
+ * @warning This function can ONLY be called from threads.
+ */
+rt_err_t rt_mutex_init(rt_mutex_t mutex, const char *name, rt_uint8_t flag)
+{
+ /* flag parameter has been obsoleted */
+ RT_UNUSED(flag);
+
+ /* parameter check */
+ RT_ASSERT(mutex != RT_NULL);
+
+ /* initialize object */
+ rt_object_init(&(mutex->parent.parent), RT_Object_Class_Mutex, name);
+
+ /* initialize ipc object */
+ _ipc_object_init(&(mutex->parent));
+
+ mutex->value = 1;
+ mutex->owner = RT_NULL;
+ mutex->original_priority = 0xFF;
+ mutex->hold = 0;
+
+ /* flag can only be RT_IPC_FLAG_PRIO. RT_IPC_FLAG_FIFO cannot solve the unbounded priority inversion problem */
+ mutex->parent.parent.flag = RT_IPC_FLAG_PRIO;
+
+ return RT_EOK;
+}
+RTM_EXPORT(rt_mutex_init);
+
+
+/**
+ * @brief This function will detach a static mutex object.
+ *
+ * @note This function is used to detach a static mutex object which is initialized by rt_mutex_init() function.
+ * By contrast, the rt_mutex_delete() function will delete a mutex object.
+ * When the mutex is successfully detached, it will resume all suspended threads in the mutex list.
+ *
+ * @see rt_mutex_delete()
+ *
+ * @param mutex is a pointer to a mutex object to be detached.
+ *
+ * @return Return the operation status. When the return value is RT_EOK, the initialization is successful.
+ * If the return value is any other values, it means that the mutex detach failed.
+ *
+ * @warning This function can ONLY detach a static mutex initialized by the rt_mutex_init() function.
+ * If the mutex is created by the rt_mutex_create() function, you MUST NOT USE this function to detach it,
+ * ONLY USE the rt_mutex_delete() function to complete the deletion.
+ */
+rt_err_t rt_mutex_detach(rt_mutex_t mutex)
+{
+ /* parameter check */
+ RT_ASSERT(mutex != RT_NULL);
+ RT_ASSERT(rt_object_get_type(&mutex->parent.parent) == RT_Object_Class_Mutex);
+ RT_ASSERT(rt_object_is_systemobject(&mutex->parent.parent));
+
+ /* wakeup all suspended threads */
+ _ipc_list_resume_all(&(mutex->parent.suspend_thread));
+
+ /* detach mutex object */
+ rt_object_detach(&(mutex->parent.parent));
+
+ return RT_EOK;
+}
+RTM_EXPORT(rt_mutex_detach);
+
+#ifdef RT_USING_HEAP
+/**
+ * @brief This function will create a mutex object.
+ *
+ * @note For the mutex object, its memory space is automatically allocated.
+ * By contrast, the rt_mutex_init() function will initialize a static mutex object.
+ *
+ * @see rt_mutex_init()
+ *
+ * @param name is a pointer to the name that given to the mutex.
+ *
+ * @param flag is the mutex flag, which determines the queuing way of how multiple threads wait
+ * when the mutex is not available.
+ * NOTE: This parameter has been obsoleted. It can be RT_IPC_FLAG_PRIO, RT_IPC_FLAG_FIFO or RT_NULL.
+ *
+ * @return Return a pointer to the mutex object. When the return value is RT_NULL, it means the creation failed.
+ *
+ * @warning This function can ONLY be called from threads.
+ */
+rt_mutex_t rt_mutex_create(const char *name, rt_uint8_t flag)
+{
+ struct rt_mutex *mutex;
+
+ /* flag parameter has been obsoleted */
+ RT_UNUSED(flag);
+
+ RT_DEBUG_NOT_IN_INTERRUPT;
+
+ /* allocate object */
+ mutex = (rt_mutex_t)rt_object_allocate(RT_Object_Class_Mutex, name);
+ if (mutex == RT_NULL)
+ return mutex;
+
+ /* initialize ipc object */
+ _ipc_object_init(&(mutex->parent));
+
+ mutex->value = 1;
+ mutex->owner = RT_NULL;
+ mutex->original_priority = 0xFF;
+ mutex->hold = 0;
+
+ /* flag can only be RT_IPC_FLAG_PRIO. RT_IPC_FLAG_FIFO cannot solve the unbounded priority inversion problem */
+ mutex->parent.parent.flag = RT_IPC_FLAG_PRIO;
+
+ return mutex;
+}
+RTM_EXPORT(rt_mutex_create);
+
+
+/**
+ * @brief This function will delete a mutex object and release this memory space.
+ *
+ * @note This function is used to delete a mutex object which is created by the rt_mutex_create() function.
+ * By contrast, the rt_mutex_detach() function will detach a static mutex object.
+ * When the mutex is successfully deleted, it will resume all suspended threads in the mutex list.
+ *
+ * @see rt_mutex_detach()
+ *
+ * @param mutex is a pointer to a mutex object to be deleted.
+ *
+ * @return Return the operation status. When the return value is RT_EOK, the operation is successful.
+ * If the return value is any other values, it means that the mutex detach failed.
+ *
+ * @warning This function can ONLY delete a mutex initialized by the rt_mutex_create() function.
+ * If the mutex is initialized by the rt_mutex_init() function, you MUST NOT USE this function to delete it,
+ * ONLY USE the rt_mutex_detach() function to complete the detachment.
+ */
+rt_err_t rt_mutex_delete(rt_mutex_t mutex)
+{
+ /* parameter check */
+ RT_ASSERT(mutex != RT_NULL);
+ RT_ASSERT(rt_object_get_type(&mutex->parent.parent) == RT_Object_Class_Mutex);
+ RT_ASSERT(rt_object_is_systemobject(&mutex->parent.parent) == RT_FALSE);
+
+ RT_DEBUG_NOT_IN_INTERRUPT;
+
+ /* wakeup all suspended threads */
+ _ipc_list_resume_all(&(mutex->parent.suspend_thread));
+
+ /* delete mutex object */
+ rt_object_delete(&(mutex->parent.parent));
+
+ return RT_EOK;
+}
+RTM_EXPORT(rt_mutex_delete);
+#endif /* RT_USING_HEAP */
+
+
+/**
+ * @brief This function will take a mutex, if the mutex is unavailable, the thread shall wait for
+ * the mutex up to a specified time.
+ *
+ * @note When this function is called, the count value of the mutex->value will decrease 1 until it is equal to 0.
+ * When the mutex->value is 0, it means that the mutex is unavailable. At this time, it will suspend the
+ * thread preparing to take the mutex.
+ * On the contrary, the rt_mutex_release() function will increase the count value of mutex->value by 1 each time.
+ *
+ * @see rt_mutex_trytake()
+ *
+ * @param mutex is a pointer to a mutex object.
+ *
+ * @param timeout is a timeout period (unit: an OS tick). If the mutex is unavailable, the thread will wait for
+ * the mutex up to the amount of time specified by the argument.
+ * NOTE: Generally, we set this parameter to RT_WAITING_FOREVER, which means that when the mutex is unavailable,
+ * the thread will be waitting forever.
+ *
+ * @return Return the operation status. ONLY When the return value is RT_EOK, the operation is successful.
+ * If the return value is any other values, it means that the mutex take failed.
+ *
+ * @warning This function can ONLY be called in the thread context. It MUST NOT BE called in interrupt context.
+ */
+rt_err_t rt_mutex_take(rt_mutex_t mutex, rt_int32_t timeout)
+{
+ rt_base_t level;
+ struct rt_thread *thread;
+
+ /* this function must not be used in interrupt even if time = 0 */
+ /* current context checking */
+ RT_DEBUG_SCHEDULER_AVAILABLE(RT_TRUE);
+
+ /* parameter check */
+ RT_ASSERT(mutex != RT_NULL);
+ RT_ASSERT(rt_object_get_type(&mutex->parent.parent) == RT_Object_Class_Mutex);
+
+ /* get current thread */
+ thread = rt_thread_self();
+
+ /* disable interrupt */
+ level = rt_hw_interrupt_disable();
+
+ RT_OBJECT_HOOK_CALL(rt_object_trytake_hook, (&(mutex->parent.parent)));
+
+ RT_DEBUG_LOG(RT_DEBUG_IPC,
+ ("mutex_take: current thread %s, mutex value: %d, hold: %d\n",
+ thread->name, mutex->value, mutex->hold));
+
+ /* reset thread error */
+ thread->error = RT_EOK;
+
+ if (mutex->owner == thread)
+ {
+ if(mutex->hold < RT_MUTEX_HOLD_MAX)
+ {
+ /* it's the same thread */
+ mutex->hold ++;
+ }
+ else
+ {
+ rt_hw_interrupt_enable(level); /* enable interrupt */
+ return -RT_EFULL; /* value overflowed */
+ }
+ }
+ else
+ {
+ /* The value of mutex is 1 in initial status. Therefore, if the
+ * value is great than 0, it indicates the mutex is avaible.
+ */
+ if (mutex->value > 0)
+ {
+ /* mutex is available */
+ mutex->value --;
+
+ /* set mutex owner and original priority */
+ mutex->owner = thread;
+ mutex->original_priority = thread->current_priority;
+ if(mutex->hold < RT_MUTEX_HOLD_MAX)
+ {
+ mutex->hold ++;
+ }
+ else
+ {
+ rt_hw_interrupt_enable(level); /* enable interrupt */
+ return -RT_EFULL; /* value overflowed */
+ }
+ }
+ else
+ {
+ /* no waiting, return with timeout */
+ if (timeout == 0)
+ {
+ /* set error as timeout */
+ thread->error = -RT_ETIMEOUT;
+
+ /* enable interrupt */
+ rt_hw_interrupt_enable(level);
+
+ return -RT_ETIMEOUT;
+ }
+ else
+ {
+ /* mutex is unavailable, push to suspend list */
+ RT_DEBUG_LOG(RT_DEBUG_IPC, ("mutex_take: suspend thread: %s\n",
+ thread->name));
+
+ /* change the owner thread priority of mutex */
+ if (thread->current_priority < mutex->owner->current_priority)
+ {
+ /* change the owner thread priority */
+ rt_thread_control(mutex->owner,
+ RT_THREAD_CTRL_CHANGE_PRIORITY,
+ &thread->current_priority);
+ }
+
+ /* suspend current thread */
+ _ipc_list_suspend(&(mutex->parent.suspend_thread),
+ thread,
+ mutex->parent.parent.flag);
+
+ /* has waiting time, start thread timer */
+ if (timeout > 0)
+ {
+ RT_DEBUG_LOG(RT_DEBUG_IPC,
+ ("mutex_take: start the timer of thread:%s\n",
+ thread->name));
+
+ /* reset the timeout of thread timer and start it */
+ rt_timer_control(&(thread->thread_timer),
+ RT_TIMER_CTRL_SET_TIME,
+ &timeout);
+ rt_timer_start(&(thread->thread_timer));
+ }
+
+ /* enable interrupt */
+ rt_hw_interrupt_enable(level);
+
+ /* do schedule */
+ rt_schedule();
+
+ if (thread->error != RT_EOK)
+ {
+ /* return error */
+ return thread->error;
+ }
+ else
+ {
+ /* the mutex is taken successfully. */
+ /* disable interrupt */
+ level = rt_hw_interrupt_disable();
+ }
+ }
+ }
+ }
+
+ /* enable interrupt */
+ rt_hw_interrupt_enable(level);
+
+ RT_OBJECT_HOOK_CALL(rt_object_take_hook, (&(mutex->parent.parent)));
+
+ return RT_EOK;
+}
+RTM_EXPORT(rt_mutex_take);
+
+
+/**
+ * @brief This function will try to take a mutex, if the mutex is unavailable, the thread returns immediately.
+ *
+ * @note This function is very similar to the rt_mutex_take() function, when the mutex is not available,
+ * except that rt_mutex_trytake() will return immediately without waiting for a timeout
+ * when the mutex is not available.
+ * In other words, rt_mutex_trytake(mutex) has the same effect as rt_mutex_take(mutex, 0).
+ *
+ * @see rt_mutex_take()
+ *
+ * @param mutex is a pointer to a mutex object.
+ *
+ * @return Return the operation status. ONLY When the return value is RT_EOK, the operation is successful.
+ * If the return value is any other values, it means that the mutex take failed.
+ */
+rt_err_t rt_mutex_trytake(rt_mutex_t mutex)
+{
+ return rt_mutex_take(mutex, RT_WAITING_NO);
+}
+RTM_EXPORT(rt_mutex_trytake);
+
+
+/**
+ * @brief This function will release a mutex. If there is thread suspended on the mutex, the thread will be resumed.
+ *
+ * @note If there are threads suspended on this mutex, the first thread in the list of this mutex object
+ * will be resumed, and a thread scheduling (rt_schedule) will be executed.
+ * If no threads are suspended on this mutex, the count value mutex->value of this mutex will increase by 1.
+ *
+ * @param mutex is a pointer to a mutex object.
+ *
+ * @return Return the operation status. When the return value is RT_EOK, the operation is successful.
+ * If the return value is any other values, it means that the mutex release failed.
+ */
+rt_err_t rt_mutex_release(rt_mutex_t mutex)
+{
+ rt_base_t level;
+ struct rt_thread *thread;
+ rt_bool_t need_schedule;
+
+ /* parameter check */
+ RT_ASSERT(mutex != RT_NULL);
+ RT_ASSERT(rt_object_get_type(&mutex->parent.parent) == RT_Object_Class_Mutex);
+
+ need_schedule = RT_FALSE;
+
+ /* only thread could release mutex because we need test the ownership */
+ RT_DEBUG_IN_THREAD_CONTEXT;
+
+ /* get current thread */
+ thread = rt_thread_self();
+
+ /* disable interrupt */
+ level = rt_hw_interrupt_disable();
+
+ RT_DEBUG_LOG(RT_DEBUG_IPC,
+ ("mutex_release:current thread %s, mutex value: %d, hold: %d\n",
+ thread->name, mutex->value, mutex->hold));
+
+ RT_OBJECT_HOOK_CALL(rt_object_put_hook, (&(mutex->parent.parent)));
+
+ /* mutex only can be released by owner */
+ if (thread != mutex->owner)
+ {
+ thread->error = -RT_ERROR;
+
+ /* enable interrupt */
+ rt_hw_interrupt_enable(level);
+
+ return -RT_ERROR;
+ }
+
+ /* decrease hold */
+ mutex->hold --;
+ /* if no hold */
+ if (mutex->hold == 0)
+ {
+ /* change the owner thread to original priority */
+ if (mutex->original_priority != mutex->owner->current_priority)
+ {
+ rt_thread_control(mutex->owner,
+ RT_THREAD_CTRL_CHANGE_PRIORITY,
+ &(mutex->original_priority));
+ }
+
+ /* wakeup suspended thread */
+ if (!rt_list_isempty(&mutex->parent.suspend_thread))
+ {
+ /* get suspended thread */
+ thread = rt_list_entry(mutex->parent.suspend_thread.next,
+ struct rt_thread,
+ tlist);
+
+ RT_DEBUG_LOG(RT_DEBUG_IPC, ("mutex_release: resume thread: %s\n",
+ thread->name));
+
+ /* set new owner and priority */
+ mutex->owner = thread;
+ mutex->original_priority = thread->current_priority;
+
+ if(mutex->hold < RT_MUTEX_HOLD_MAX)
+ {
+ mutex->hold ++;
+ }
+ else
+ {
+ rt_hw_interrupt_enable(level); /* enable interrupt */
+ return -RT_EFULL; /* value overflowed */
+ }
+
+ /* resume thread */
+ _ipc_list_resume(&(mutex->parent.suspend_thread));
+
+ need_schedule = RT_TRUE;
+ }
+ else
+ {
+ if(mutex->value < RT_MUTEX_VALUE_MAX)
+ {
+ /* increase value */
+ mutex->value ++;
+ }
+ else
+ {
+ rt_hw_interrupt_enable(level); /* enable interrupt */
+ return -RT_EFULL; /* value overflowed */
+ }
+
+ /* clear owner */
+ mutex->owner = RT_NULL;
+ mutex->original_priority = 0xff;
+ }
+ }
+
+ /* enable interrupt */
+ rt_hw_interrupt_enable(level);
+
+ /* perform a schedule */
+ if (need_schedule == RT_TRUE)
+ rt_schedule();
+
+ return RT_EOK;
+}
+RTM_EXPORT(rt_mutex_release);
+
+
+/**
+ * @brief This function will set some extra attributions of a mutex object.
+ *
+ * @note Currently this function does not implement the control function.
+ *
+ * @param mutex is a pointer to a mutex object.
+ *
+ * @param cmd is a command word used to configure some attributions of the mutex.
+ *
+ * @param arg is the argument of the function to execute the command.
+ *
+ * @return Return the operation status. When the return value is RT_EOK, the operation is successful.
+ * If the return value is any other values, it means that this function failed to execute.
+ */
+rt_err_t rt_mutex_control(rt_mutex_t mutex, int cmd, void *arg)
+{
+ /* parameter check */
+ RT_ASSERT(mutex != RT_NULL);
+ RT_ASSERT(rt_object_get_type(&mutex->parent.parent) == RT_Object_Class_Mutex);
+
+ return -RT_ERROR;
+}
+RTM_EXPORT(rt_mutex_control);
+
+/**@}*/
+#endif /* RT_USING_MUTEX */
+
+#ifdef RT_USING_EVENT
+/**
+ * @addtogroup event
+ */
+
+/**@{*/
+
+/**
+ * @brief The function will initialize a static event object.
+ *
+ * @note For the static event object, its memory space is allocated by the compiler during compiling,
+ * and shall placed on the read-write data segment or on the uninitialized data segment.
+ * By contrast, the rt_event_create() function will allocate memory space automatically
+ * and initialize the event.
+ *
+ * @see rt_event_create()
+ *
+ * @param event is a pointer to the event to initialize. It is assumed that storage for the event
+ * will be allocated in your application.
+ *
+ * @param name is a pointer to the name that given to the event.
+ *
+ * @param flag is the event flag, which determines the queuing way of how multiple threads wait
+ * when the event is not available.
+ * The event flag can be ONE of the following values:
+ *
+ * RT_IPC_FLAG_PRIO The pending threads will queue in order of priority.
+ *
+ * RT_IPC_FLAG_FIFO The pending threads will queue in the first-in-first-out method
+ * (also known as first-come-first-served (FCFS) scheduling strategy).
+ *
+ * NOTE: RT_IPC_FLAG_FIFO is a non-real-time scheduling mode. It is strongly recommended to
+ * use RT_IPC_FLAG_PRIO to ensure the thread is real-time UNLESS your applications concern about
+ * the first-in-first-out principle, and you clearly understand that all threads involved in
+ * this event will become non-real-time threads.
+ *
+ * @return Return the operation status. When the return value is RT_EOK, the initialization is successful.
+ * If the return value is any other values, it represents the initialization failed.
+ *
+ * @warning This function can ONLY be called from threads.
+ */
+rt_err_t rt_event_init(rt_event_t event, const char *name, rt_uint8_t flag)
+{
+ /* parameter check */
+ RT_ASSERT(event != RT_NULL);
+ RT_ASSERT((flag == RT_IPC_FLAG_FIFO) || (flag == RT_IPC_FLAG_PRIO));
+
+ /* initialize object */
+ rt_object_init(&(event->parent.parent), RT_Object_Class_Event, name);
+
+ /* set parent flag */
+ event->parent.parent.flag = flag;
+
+ /* initialize ipc object */
+ _ipc_object_init(&(event->parent));
+
+ /* initialize event */
+ event->set = 0;
+
+ return RT_EOK;
+}
+RTM_EXPORT(rt_event_init);
+
+
+/**
+ * @brief This function will detach a static event object.
+ *
+ * @note This function is used to detach a static event object which is initialized by rt_event_init() function.
+ * By contrast, the rt_event_delete() function will delete an event object.
+ * When the event is successfully detached, it will resume all suspended threads in the event list.
+ *
+ * @see rt_event_delete()
+ *
+ * @param event is a pointer to an event object to be detached.
+ *
+ * @return Return the operation status. When the return value is RT_EOK, the initialization is successful.
+ * If the return value is any other values, it means that the event detach failed.
+ *
+ * @warning This function can ONLY detach a static event initialized by the rt_event_init() function.
+ * If the event is created by the rt_event_create() function, you MUST NOT USE this function to detach it,
+ * ONLY USE the rt_event_delete() function to complete the deletion.
+ */
+rt_err_t rt_event_detach(rt_event_t event)
+{
+ /* parameter check */
+ RT_ASSERT(event != RT_NULL);
+ RT_ASSERT(rt_object_get_type(&event->parent.parent) == RT_Object_Class_Event);
+ RT_ASSERT(rt_object_is_systemobject(&event->parent.parent));
+
+ /* resume all suspended thread */
+ _ipc_list_resume_all(&(event->parent.suspend_thread));
+
+ /* detach event object */
+ rt_object_detach(&(event->parent.parent));
+
+ return RT_EOK;
+}
+RTM_EXPORT(rt_event_detach);
+
+#ifdef RT_USING_HEAP
+/**
+ * @brief Creating an event object.
+ *
+ * @note For the event object, its memory space is allocated automatically.
+ * By contrast, the rt_event_init() function will initialize a static event object.
+ *
+ * @see rt_event_init()
+ *
+ * @param name is a pointer to the name that given to the event.
+ *
+ * @param flag is the event flag, which determines the queuing way of how multiple threads wait when the event
+ * is not available.
+ * The event flag can be ONE of the following values:
+ *
+ * RT_IPC_FLAG_PRIO The pending threads will queue in order of priority.
+ *
+ * RT_IPC_FLAG_FIFO The pending threads will queue in the first-in-first-out method
+ * (also known as first-come-first-served (FCFS) scheduling strategy).
+ *
+ * NOTE: RT_IPC_FLAG_FIFO is a non-real-time scheduling mode. It is strongly recommended to
+ * use RT_IPC_FLAG_PRIO to ensure the thread is real-time UNLESS your applications concern about
+ * the first-in-first-out principle, and you clearly understand that all threads involved in
+ * this event will become non-real-time threads.
+ *
+ * @return Return a pointer to the event object. When the return value is RT_NULL, it means the creation failed.
+ *
+ * @warning This function can ONLY be called from threads.
+ */
+rt_event_t rt_event_create(const char *name, rt_uint8_t flag)
+{
+ rt_event_t event;
+
+ RT_ASSERT((flag == RT_IPC_FLAG_FIFO) || (flag == RT_IPC_FLAG_PRIO));
+
+ RT_DEBUG_NOT_IN_INTERRUPT;
+
+ /* allocate object */
+ event = (rt_event_t)rt_object_allocate(RT_Object_Class_Event, name);
+ if (event == RT_NULL)
+ return event;
+
+ /* set parent */
+ event->parent.parent.flag = flag;
+
+ /* initialize ipc object */
+ _ipc_object_init(&(event->parent));
+
+ /* initialize event */
+ event->set = 0;
+
+ return event;
+}
+RTM_EXPORT(rt_event_create);
+
+
+/**
+ * @brief This function will delete an event object and release the memory space.
+ *
+ * @note This function is used to delete an event object which is created by the rt_event_create() function.
+ * By contrast, the rt_event_detach() function will detach a static event object.
+ * When the event is successfully deleted, it will resume all suspended threads in the event list.
+ *
+ * @see rt_event_detach()
+ *
+ * @param event is a pointer to an event object to be deleted.
+ *
+ * @return Return the operation status. When the return value is RT_EOK, the operation is successful.
+ * If the return value is any other values, it means that the event detach failed.
+ *
+ * @warning This function can ONLY delete an event initialized by the rt_event_create() function.
+ * If the event is initialized by the rt_event_init() function, you MUST NOT USE this function to delete it,
+ * ONLY USE the rt_event_detach() function to complete the detachment.
+ */
+rt_err_t rt_event_delete(rt_event_t event)
+{
+ /* parameter check */
+ RT_ASSERT(event != RT_NULL);
+ RT_ASSERT(rt_object_get_type(&event->parent.parent) == RT_Object_Class_Event);
+ RT_ASSERT(rt_object_is_systemobject(&event->parent.parent) == RT_FALSE);
+
+ RT_DEBUG_NOT_IN_INTERRUPT;
+
+ /* resume all suspended thread */
+ _ipc_list_resume_all(&(event->parent.suspend_thread));
+
+ /* delete event object */
+ rt_object_delete(&(event->parent.parent));
+
+ return RT_EOK;
+}
+RTM_EXPORT(rt_event_delete);
+#endif /* RT_USING_HEAP */
+
+
+/**
+ * @brief This function will send an event to the event object.
+ * If there is a thread suspended on the event, the thread will be resumed.
+ *
+ * @note When using this function, you need to use the parameter (set) to specify the event flag of the event object,
+ * then the function will traverse the list of suspended threads waiting on the event object.
+ * If there is a thread suspended on the event, and the thread's event_info and the event flag of
+ * the current event object matches, the thread will be resumed.
+ *
+ * @param event is a pointer to the event object to be sent.
+ *
+ * @param set is a flag that you will set for this event's flag.
+ * You can set an event flag, or you can set multiple flags through OR logic operation.
+ *
+ * @return Return the operation status. When the return value is RT_EOK, the operation is successful.
+ * If the return value is any other values, it means that the event detach failed.
+ */
+rt_err_t rt_event_send(rt_event_t event, rt_uint32_t set)
+{
+ struct rt_list_node *n;
+ struct rt_thread *thread;
+ rt_base_t level;
+ rt_base_t status;
+ rt_bool_t need_schedule;
+
+ /* parameter check */
+ RT_ASSERT(event != RT_NULL);
+ RT_ASSERT(rt_object_get_type(&event->parent.parent) == RT_Object_Class_Event);
+
+ if (set == 0)
+ return -RT_ERROR;
+
+ need_schedule = RT_FALSE;
+
+ /* disable interrupt */
+ level = rt_hw_interrupt_disable();
+
+ /* set event */
+ event->set |= set;
+
+ RT_OBJECT_HOOK_CALL(rt_object_put_hook, (&(event->parent.parent)));
+
+ if (!rt_list_isempty(&event->parent.suspend_thread))
+ {
+ /* search thread list to resume thread */
+ n = event->parent.suspend_thread.next;
+ while (n != &(event->parent.suspend_thread))
+ {
+ /* get thread */
+ thread = rt_list_entry(n, struct rt_thread, tlist);
+
+ status = -RT_ERROR;
+ if (thread->event_info & RT_EVENT_FLAG_AND)
+ {
+ if ((thread->event_set & event->set) == thread->event_set)
+ {
+ /* received an AND event */
+ status = RT_EOK;
+ }
+ }
+ else if (thread->event_info & RT_EVENT_FLAG_OR)
+ {
+ if (thread->event_set & event->set)
+ {
+ /* save the received event set */
+ thread->event_set = thread->event_set & event->set;
+
+ /* received an OR event */
+ status = RT_EOK;
+ }
+ }
+ else
+ {
+ /* enable interrupt */
+ rt_hw_interrupt_enable(level);
+
+ return -RT_EINVAL;
+ }
+
+ /* move node to the next */
+ n = n->next;
+
+ /* condition is satisfied, resume thread */
+ if (status == RT_EOK)
+ {
+ /* clear event */
+ if (thread->event_info & RT_EVENT_FLAG_CLEAR)
+ event->set &= ~thread->event_set;
+
+ /* resume thread, and thread list breaks out */
+ rt_thread_resume(thread);
+
+ /* need do a scheduling */
+ need_schedule = RT_TRUE;
+ }
+ }
+ }
+
+ /* enable interrupt */
+ rt_hw_interrupt_enable(level);
+
+ /* do a schedule */
+ if (need_schedule == RT_TRUE)
+ rt_schedule();
+
+ return RT_EOK;
+}
+RTM_EXPORT(rt_event_send);
+
+
+/**
+ * @brief This function will receive an event from event object. if the event is unavailable, the thread shall wait for
+ * the event up to a specified time.
+ *
+ * @note If there are threads suspended on this semaphore, the first thread in the list of this semaphore object
+ * will be resumed, and a thread scheduling (rt_schedule) will be executed.
+ * If no threads are suspended on this semaphore, the count value sem->value of this semaphore will increase by 1.
+ *
+ * @param event is a pointer to the event object to be received.
+ *
+ * @param set is a flag that you will set for this event's flag.
+ * You can set an event flag, or you can set multiple flags through OR logic operation.
+ *
+ * @param option is the option of this receiving event, it indicates how the receiving event is operated.
+ * The option can be one or more of the following values, When selecting multiple values,use logical OR to operate.
+ * (NOTE: RT_EVENT_FLAG_OR and RT_EVENT_FLAG_AND can only select one):
+ *
+ *
+ * RT_EVENT_FLAG_OR The thread select to use logical OR to receive the event.
+ *
+ * RT_EVENT_FLAG_AND The thread select to use logical OR to receive the event.
+ *
+ * RT_EVENT_FLAG_CLEAR When the thread receives the corresponding event, the function
+ * determines whether to clear the event flag.
+ *
+ * @param timeout is a timeout period (unit: an OS tick).
+ *
+ * @param recved is a pointer to the received event. If you don't care about this value, you can use RT_NULL to set.
+ *
+ * @return Return the operation status. When the return value is RT_EOK, the operation is successful.
+ * If the return value is any other values, it means that the semaphore release failed.
+ */
+rt_err_t rt_event_recv(rt_event_t event,
+ rt_uint32_t set,
+ rt_uint8_t option,
+ rt_int32_t timeout,
+ rt_uint32_t *recved)
+{
+ struct rt_thread *thread;
+ rt_base_t level;
+ rt_base_t status;
+
+ /* parameter check */
+ RT_ASSERT(event != RT_NULL);
+ RT_ASSERT(rt_object_get_type(&event->parent.parent) == RT_Object_Class_Event);
+
+ /* current context checking */
+ RT_DEBUG_SCHEDULER_AVAILABLE(RT_TRUE);
+
+ if (set == 0)
+ return -RT_ERROR;
+
+ /* initialize status */
+ status = -RT_ERROR;
+ /* get current thread */
+ thread = rt_thread_self();
+ /* reset thread error */
+ thread->error = RT_EOK;
+
+ RT_OBJECT_HOOK_CALL(rt_object_trytake_hook, (&(event->parent.parent)));
+
+ /* disable interrupt */
+ level = rt_hw_interrupt_disable();
+
+ /* check event set */
+ if (option & RT_EVENT_FLAG_AND)
+ {
+ if ((event->set & set) == set)
+ status = RT_EOK;
+ }
+ else if (option & RT_EVENT_FLAG_OR)
+ {
+ if (event->set & set)
+ status = RT_EOK;
+ }
+ else
+ {
+ /* either RT_EVENT_FLAG_AND or RT_EVENT_FLAG_OR should be set */
+ RT_ASSERT(0);
+ }
+
+ if (status == RT_EOK)
+ {
+ /* set received event */
+ if (recved)
+ *recved = (event->set & set);
+
+ /* fill thread event info */
+ thread->event_set = (event->set & set);
+ thread->event_info = option;
+
+ /* received event */
+ if (option & RT_EVENT_FLAG_CLEAR)
+ event->set &= ~set;
+ }
+ else if (timeout == 0)
+ {
+ /* no waiting */
+ thread->error = -RT_ETIMEOUT;
+
+ /* enable interrupt */
+ rt_hw_interrupt_enable(level);
+
+ return -RT_ETIMEOUT;
+ }
+ else
+ {
+ /* fill thread event info */
+ thread->event_set = set;
+ thread->event_info = option;
+
+ /* put thread to suspended thread list */
+ _ipc_list_suspend(&(event->parent.suspend_thread),
+ thread,
+ event->parent.parent.flag);
+
+ /* if there is a waiting timeout, active thread timer */
+ if (timeout > 0)
+ {
+ /* reset the timeout of thread timer and start it */
+ rt_timer_control(&(thread->thread_timer),
+ RT_TIMER_CTRL_SET_TIME,
+ &timeout);
+ rt_timer_start(&(thread->thread_timer));
+ }
+
+ /* enable interrupt */
+ rt_hw_interrupt_enable(level);
+
+ /* do a schedule */
+ rt_schedule();
+
+ if (thread->error != RT_EOK)
+ {
+ /* return error */
+ return thread->error;
+ }
+
+ /* received an event, disable interrupt to protect */
+ level = rt_hw_interrupt_disable();
+
+ /* set received event */
+ if (recved)
+ *recved = thread->event_set;
+ }
+
+ /* enable interrupt */
+ rt_hw_interrupt_enable(level);
+
+ RT_OBJECT_HOOK_CALL(rt_object_take_hook, (&(event->parent.parent)));
+
+ return thread->error;
+}
+RTM_EXPORT(rt_event_recv);
+
+
+/**
+ * @brief This function will set some extra attributions of an event object.
+ *
+ * @note Currently this function only supports the RT_IPC_CMD_RESET command to reset the event.
+ *
+ * @param event is a pointer to an event object.
+ *
+ * @param cmd is a command word used to configure some attributions of the event.
+ *
+ * @param arg is the argument of the function to execute the command.
+ *
+ * @return Return the operation status. When the return value is RT_EOK, the operation is successful.
+ * If the return value is any other values, it means that this function failed to execute.
+ */
+rt_err_t rt_event_control(rt_event_t event, int cmd, void *arg)
+{
+ rt_base_t level;
+
+ /* parameter check */
+ RT_ASSERT(event != RT_NULL);
+ RT_ASSERT(rt_object_get_type(&event->parent.parent) == RT_Object_Class_Event);
+
+ if (cmd == RT_IPC_CMD_RESET)
+ {
+ /* disable interrupt */
+ level = rt_hw_interrupt_disable();
+
+ /* resume all waiting thread */
+ _ipc_list_resume_all(&event->parent.suspend_thread);
+
+ /* initialize event set */
+ event->set = 0;
+
+ /* enable interrupt */
+ rt_hw_interrupt_enable(level);
+
+ rt_schedule();
+
+ return RT_EOK;
+ }
+
+ return -RT_ERROR;
+}
+RTM_EXPORT(rt_event_control);
+
+/**@}*/
+#endif /* RT_USING_EVENT */
+
+#ifdef RT_USING_MAILBOX
+/**
+ * @addtogroup mailbox
+ */
+
+/**@{*/
+
+/**
+ * @brief Initialize a static mailbox object.
+ *
+ * @note For the static mailbox object, its memory space is allocated by the compiler during compiling,
+ * and shall placed on the read-write data segment or on the uninitialized data segment.
+ * By contrast, the rt_mb_create() function will allocate memory space automatically and initialize the mailbox.
+ *
+ * @see rt_mb_create()
+ *
+ * @param mb is a pointer to the mailbox to initialize.
+ * It is assumed that storage for the mailbox will be allocated in your application.
+ *
+ * @param name is a pointer to the name that given to the mailbox.
+ *
+ * @param size is the maximum number of mails in the mailbox.
+ * For example, when the mailbox buffer capacity is N, size is N/4.
+ *
+ * @param flag is the mailbox flag, which determines the queuing way of how multiple threads wait
+ * when the mailbox is not available.
+ * The mailbox flag can be ONE of the following values:
+ *
+ * RT_IPC_FLAG_PRIO The pending threads will queue in order of priority.
+ *
+ * RT_IPC_FLAG_FIFO The pending threads will queue in the first-in-first-out method
+ * (also known as first-come-first-served (FCFS) scheduling strategy).
+ *
+ * NOTE: RT_IPC_FLAG_FIFO is a non-real-time scheduling mode. It is strongly recommended to
+ * use RT_IPC_FLAG_PRIO to ensure the thread is real-time UNLESS your applications concern about
+ * the first-in-first-out principle, and you clearly understand that all threads involved in
+ * this mailbox will become non-real-time threads.
+ *
+ * @return Return the operation status. When the return value is RT_EOK, the initialization is successful.
+ * If the return value is any other values, it represents the initialization failed.
+ *
+ * @warning This function can ONLY be called from threads.
+ */
+rt_err_t rt_mb_init(rt_mailbox_t mb,
+ const char *name,
+ void *msgpool,
+ rt_size_t size,
+ rt_uint8_t flag)
+{
+ RT_ASSERT(mb != RT_NULL);
+ RT_ASSERT((flag == RT_IPC_FLAG_FIFO) || (flag == RT_IPC_FLAG_PRIO));
+
+ /* initialize object */
+ rt_object_init(&(mb->parent.parent), RT_Object_Class_MailBox, name);
+
+ /* set parent flag */
+ mb->parent.parent.flag = flag;
+
+ /* initialize ipc object */
+ _ipc_object_init(&(mb->parent));
+
+ /* initialize mailbox */
+ mb->msg_pool = (rt_ubase_t *)msgpool;
+ mb->size = size;
+ mb->entry = 0;
+ mb->in_offset = 0;
+ mb->out_offset = 0;
+
+ /* initialize an additional list of sender suspend thread */
+ rt_list_init(&(mb->suspend_sender_thread));
+
+ return RT_EOK;
+}
+RTM_EXPORT(rt_mb_init);
+
+
+/**
+ * @brief This function will detach a static mailbox object.
+ *
+ * @note This function is used to detach a static mailbox object which is initialized by rt_mb_init() function.
+ * By contrast, the rt_mb_delete() function will delete a mailbox object.
+ * When the mailbox is successfully detached, it will resume all suspended threads in the mailbox list.
+ *
+ * @see rt_mb_delete()
+ *
+ * @param mb is a pointer to a mailbox object to be detached.
+ *
+ * @return Return the operation status. When the return value is RT_EOK, the initialization is successful.
+ * If the return value is any other values, it means that the mailbox detach failed.
+ *
+ * @warning This function can ONLY detach a static mailbox initialized by the rt_mb_init() function.
+ * If the mailbox is created by the rt_mb_create() function, you MUST NOT USE this function to detach it,
+ * ONLY USE the rt_mb_delete() function to complete the deletion.
+ */
+rt_err_t rt_mb_detach(rt_mailbox_t mb)
+{
+ /* parameter check */
+ RT_ASSERT(mb != RT_NULL);
+ RT_ASSERT(rt_object_get_type(&mb->parent.parent) == RT_Object_Class_MailBox);
+ RT_ASSERT(rt_object_is_systemobject(&mb->parent.parent));
+
+ /* resume all suspended thread */
+ _ipc_list_resume_all(&(mb->parent.suspend_thread));
+ /* also resume all mailbox private suspended thread */
+ _ipc_list_resume_all(&(mb->suspend_sender_thread));
+
+ /* detach mailbox object */
+ rt_object_detach(&(mb->parent.parent));
+
+ return RT_EOK;
+}
+RTM_EXPORT(rt_mb_detach);
+
+#ifdef RT_USING_HEAP
+/**
+ * @brief Creating a mailbox object.
+ *
+ * @note For the mailbox object, its memory space is allocated automatically.
+ * By contrast, the rt_mb_init() function will initialize a static mailbox object.
+ *
+ * @see rt_mb_init()
+ *
+ * @param name is a pointer that given to the mailbox.
+ *
+ * @param size is the maximum number of mails in the mailbox.
+ * For example, when mailbox buffer capacity is N, size is N/4.
+ *
+ * @param flag is the mailbox flag, which determines the queuing way of how multiple threads wait
+ * when the mailbox is not available.
+ * The mailbox flag can be ONE of the following values:
+ *
+ * RT_IPC_FLAG_PRIO The pending threads will queue in order of priority.
+ *
+ * RT_IPC_FLAG_FIFO The pending threads will queue in the first-in-first-out method
+ * (also known as first-come-first-served (FCFS) scheduling strategy).
+ *
+ * NOTE: RT_IPC_FLAG_FIFO is a non-real-time scheduling mode. It is strongly recommended to
+ * use RT_IPC_FLAG_PRIO to ensure the thread is real-time UNLESS your applications concern about
+ * the first-in-first-out principle, and you clearly understand that all threads involved in
+ * this mailbox will become non-real-time threads.
+ *
+ * @return Return a pointer to the mailbox object. When the return value is RT_NULL, it means the creation failed.
+ *
+ * @warning This function can ONLY be called from threads.
+ */
+rt_mailbox_t rt_mb_create(const char *name, rt_size_t size, rt_uint8_t flag)
+{
+ rt_mailbox_t mb;
+
+ RT_ASSERT((flag == RT_IPC_FLAG_FIFO) || (flag == RT_IPC_FLAG_PRIO));
+
+ RT_DEBUG_NOT_IN_INTERRUPT;
+
+ /* allocate object */
+ mb = (rt_mailbox_t)rt_object_allocate(RT_Object_Class_MailBox, name);
+ if (mb == RT_NULL)
+ return mb;
+
+ /* set parent */
+ mb->parent.parent.flag = flag;
+
+ /* initialize ipc object */
+ _ipc_object_init(&(mb->parent));
+
+ /* initialize mailbox */
+ mb->size = size;
+ mb->msg_pool = (rt_ubase_t *)RT_KERNEL_MALLOC(mb->size * sizeof(rt_ubase_t));
+ if (mb->msg_pool == RT_NULL)
+ {
+ /* delete mailbox object */
+ rt_object_delete(&(mb->parent.parent));
+
+ return RT_NULL;
+ }
+ mb->entry = 0;
+ mb->in_offset = 0;
+ mb->out_offset = 0;
+
+ /* initialize an additional list of sender suspend thread */
+ rt_list_init(&(mb->suspend_sender_thread));
+
+ return mb;
+}
+RTM_EXPORT(rt_mb_create);
+
+
+/**
+ * @brief This function will delete a mailbox object and release the memory space.
+ *
+ * @note This function is used to delete a mailbox object which is created by the rt_mb_create() function.
+ * By contrast, the rt_mb_detach() function will detach a static mailbox object.
+ * When the mailbox is successfully deleted, it will resume all suspended threads in the mailbox list.
+ *
+ * @see rt_mb_detach()
+ *
+ * @param mb is a pointer to a mailbox object to be deleted.
+ *
+ * @return Return the operation status. When the return value is RT_EOK, the operation is successful.
+ * If the return value is any other values, it means that the mailbox detach failed.
+ *
+ * @warning This function can only delete mailbox created by the rt_mb_create() function.
+ * If the mailbox is initialized by the rt_mb_init() function, you MUST NOT USE this function to delete it,
+ * ONLY USE the rt_mb_detach() function to complete the detachment.
+ */
+rt_err_t rt_mb_delete(rt_mailbox_t mb)
+{
+ /* parameter check */
+ RT_ASSERT(mb != RT_NULL);
+ RT_ASSERT(rt_object_get_type(&mb->parent.parent) == RT_Object_Class_MailBox);
+ RT_ASSERT(rt_object_is_systemobject(&mb->parent.parent) == RT_FALSE);
+
+ RT_DEBUG_NOT_IN_INTERRUPT;
+
+ /* resume all suspended thread */
+ _ipc_list_resume_all(&(mb->parent.suspend_thread));
+
+ /* also resume all mailbox private suspended thread */
+ _ipc_list_resume_all(&(mb->suspend_sender_thread));
+
+ /* free mailbox pool */
+ RT_KERNEL_FREE(mb->msg_pool);
+
+ /* delete mailbox object */
+ rt_object_delete(&(mb->parent.parent));
+
+ return RT_EOK;
+}
+RTM_EXPORT(rt_mb_delete);
+#endif /* RT_USING_HEAP */
+
+
+/**
+ * @brief This function will send an mail to the mailbox object. If there is a thread suspended on the mailbox,
+ * the thread will be resumed.
+ *
+ * @note When using this function to send a mail, if the mailbox if fully used, the current thread will
+ * wait for a timeout. If the set timeout time is reached and there is still no space available,
+ * the sending thread will be resumed and an error code will be returned.
+ * By contrast, the rt_mb_send() function will return an error code immediately without waiting time
+ * when the mailbox if fully used.
+ *
+ * @see rt_mb_send()
+ *
+ * @param mb is a pointer to the mailbox object to be sent.
+ *
+ * @param value is a value to the content of the mail you want to send.
+ *
+ * @param timeout is a timeout period (unit: an OS tick).
+ *
+ * @return Return the operation status. When the return value is RT_EOK, the operation is successful.
+ * If the return value is any other values, it means that the mailbox detach failed.
+ *
+ * @warning This function can be called in interrupt context and thread context.
+ */
+rt_err_t rt_mb_send_wait(rt_mailbox_t mb,
+ rt_ubase_t value,
+ rt_int32_t timeout)
+{
+ struct rt_thread *thread;
+ rt_base_t level;
+ rt_uint32_t tick_delta;
+
+ /* parameter check */
+ RT_ASSERT(mb != RT_NULL);
+ RT_ASSERT(rt_object_get_type(&mb->parent.parent) == RT_Object_Class_MailBox);
+
+ /* current context checking */
+ RT_DEBUG_SCHEDULER_AVAILABLE(timeout != 0);
+
+ /* initialize delta tick */
+ tick_delta = 0;
+ /* get current thread */
+ thread = rt_thread_self();
+
+ RT_OBJECT_HOOK_CALL(rt_object_put_hook, (&(mb->parent.parent)));
+
+ /* disable interrupt */
+ level = rt_hw_interrupt_disable();
+
+ /* for non-blocking call */
+ if (mb->entry == mb->size && timeout == 0)
+ {
+ rt_hw_interrupt_enable(level);
+ return -RT_EFULL;
+ }
+
+ /* mailbox is full */
+ while (mb->entry == mb->size)
+ {
+ /* reset error number in thread */
+ thread->error = RT_EOK;
+
+ /* no waiting, return timeout */
+ if (timeout == 0)
+ {
+ /* enable interrupt */
+ rt_hw_interrupt_enable(level);
+
+ return -RT_EFULL;
+ }
+
+ /* suspend current thread */
+ _ipc_list_suspend(&(mb->suspend_sender_thread),
+ thread,
+ mb->parent.parent.flag);
+
+ /* has waiting time, start thread timer */
+ if (timeout > 0)
+ {
+ /* get the start tick of timer */
+ tick_delta = rt_tick_get();
+
+ RT_DEBUG_LOG(RT_DEBUG_IPC, ("mb_send_wait: start timer of thread:%s\n",
+ thread->name));
+
+ /* reset the timeout of thread timer and start it */
+ rt_timer_control(&(thread->thread_timer),
+ RT_TIMER_CTRL_SET_TIME,
+ &timeout);
+ rt_timer_start(&(thread->thread_timer));
+ }
+
+ /* enable interrupt */
+ rt_hw_interrupt_enable(level);
+
+ /* re-schedule */
+ rt_schedule();
+
+ /* resume from suspend state */
+ if (thread->error != RT_EOK)
+ {
+ /* return error */
+ return thread->error;
+ }
+
+ /* disable interrupt */
+ level = rt_hw_interrupt_disable();
+
+ /* if it's not waiting forever and then re-calculate timeout tick */
+ if (timeout > 0)
+ {
+ tick_delta = rt_tick_get() - tick_delta;
+ timeout -= tick_delta;
+ if (timeout < 0)
+ timeout = 0;
+ }
+ }
+
+ /* set ptr */
+ mb->msg_pool[mb->in_offset] = value;
+ /* increase input offset */
+ ++ mb->in_offset;
+ if (mb->in_offset >= mb->size)
+ mb->in_offset = 0;
+
+ if(mb->entry < RT_MB_ENTRY_MAX)
+ {
+ /* increase message entry */
+ mb->entry ++;
+ }
+ else
+ {
+ rt_hw_interrupt_enable(level); /* enable interrupt */
+ return -RT_EFULL; /* value overflowed */
+ }
+
+ /* resume suspended thread */
+ if (!rt_list_isempty(&mb->parent.suspend_thread))
+ {
+ _ipc_list_resume(&(mb->parent.suspend_thread));
+
+ /* enable interrupt */
+ rt_hw_interrupt_enable(level);
+
+ rt_schedule();
+
+ return RT_EOK;
+ }
+
+ /* enable interrupt */
+ rt_hw_interrupt_enable(level);
+
+ return RT_EOK;
+}
+RTM_EXPORT(rt_mb_send_wait);
+
+
+/**
+ * @brief This function will send an mail to the mailbox object. If there is a thread suspended on the mailbox,
+ * the thread will be resumed.
+ *
+ * @note When using this function to send a mail, if the mailbox is fully used, this function will return an error
+ * code immediately without waiting time.
+ * By contrast, the rt_mb_send_wait() function is set a timeout to wait for the mail to be sent.
+ *
+ * @see rt_mb_send_wait()
+ *
+ * @param mb is a pointer to the mailbox object to be sent.
+ *
+ * @param value is a value to the content of the mail you want to send.
+ *
+ * @return Return the operation status. When the return value is RT_EOK, the operation is successful.
+ * If the return value is any other values, it means that the mailbox detach failed.
+ */
+rt_err_t rt_mb_send(rt_mailbox_t mb, rt_ubase_t value)
+{
+ return rt_mb_send_wait(mb, value, 0);
+}
+RTM_EXPORT(rt_mb_send);
+
+
+/**
+ * @brief This function will send an urgent mail to the mailbox object.
+ *
+ * @note This function is almost the same as the rt_mb_send() function. The only difference is that
+ * when sending an urgent mail, the mail will be placed at the head of the mail queue so that
+ * the recipient can receive the urgent mail first.
+ *
+ * @see rt_mb_send()
+ *
+ * @param mb is a pointer to the mailbox object to be sent.
+ *
+ * @param value is the content of the mail you want to send.
+ *
+ * @return Return the operation status. When the return value is RT_EOK, the operation is successful.
+ * If the return value is any other values, it means that the mailbox detach failed.
+ */
+rt_err_t rt_mb_urgent(rt_mailbox_t mb, rt_ubase_t value)
+{
+ rt_base_t level;
+
+ /* parameter check */
+ RT_ASSERT(mb != RT_NULL);
+ RT_ASSERT(rt_object_get_type(&mb->parent.parent) == RT_Object_Class_MailBox);
+
+ RT_OBJECT_HOOK_CALL(rt_object_put_hook, (&(mb->parent.parent)));
+
+ /* disable interrupt */
+ level = rt_hw_interrupt_disable();
+
+ if (mb->entry == mb->size)
+ {
+ rt_hw_interrupt_enable(level);
+ return -RT_EFULL;
+ }
+
+ /* rewind to the previous position */
+ if (mb->out_offset > 0)
+ {
+ mb->out_offset --;
+ }
+ else
+ {
+ mb->out_offset = mb->size - 1;
+ }
+
+ /* set ptr */
+ mb->msg_pool[mb->out_offset] = value;
+
+ /* increase message entry */
+ mb->entry ++;
+
+ /* resume suspended thread */
+ if (!rt_list_isempty(&mb->parent.suspend_thread))
+ {
+ _ipc_list_resume(&(mb->parent.suspend_thread));
+
+ /* enable interrupt */
+ rt_hw_interrupt_enable(level);
+
+ rt_schedule();
+
+ return RT_EOK;
+ }
+
+ /* enable interrupt */
+ rt_hw_interrupt_enable(level);
+
+ return RT_EOK;
+}
+RTM_EXPORT(rt_mb_urgent);
+
+
+/**
+ * @brief This function will receive a mail from mailbox object, if there is no mail in mailbox object,
+ * the thread shall wait for a specified time.
+ *
+ * @note Only when there is mail in the mailbox, the receiving thread can get the mail immediately and
+ * return RT_EOK, otherwise the receiving thread will be suspended until the set timeout. If the mail
+ * is still not received within the specified time, it will return-RT_ETIMEOUT.
+ *
+ * @param mb is a pointer to the mailbox object to be received.
+ *
+ * @param value is a flag that you will set for this mailbox's flag.
+ * You can set an mailbox flag, or you can set multiple flags through OR logic operations.
+ *
+ * @param timeout is a timeout period (unit: an OS tick). If the mailbox object is not avaliable in the queue,
+ * the thread will wait for the object in the queue up to the amount of time specified by this parameter.
+ *
+ * NOTE:
+ * If use Macro RT_WAITING_FOREVER to set this parameter, which means that when the
+ * mailbox object is unavailable in the queue, the thread will be waiting forever.
+ * If use macro RT_WAITING_NO to set this parameter, which means that this
+ * function is non-blocking and will return immediately.
+ *
+ * @return Return the operation status. When the return value is RT_EOK, the operation is successful.
+ * If the return value is any other values, it means that the mailbox release failed.
+ */
+rt_err_t rt_mb_recv(rt_mailbox_t mb, rt_ubase_t *value, rt_int32_t timeout)
+{
+ struct rt_thread *thread;
+ rt_base_t level;
+ rt_uint32_t tick_delta;
+
+ /* parameter check */
+ RT_ASSERT(mb != RT_NULL);
+ RT_ASSERT(rt_object_get_type(&mb->parent.parent) == RT_Object_Class_MailBox);
+
+ /* current context checking */
+ RT_DEBUG_SCHEDULER_AVAILABLE(timeout != 0);
+
+ /* initialize delta tick */
+ tick_delta = 0;
+ /* get current thread */
+ thread = rt_thread_self();
+
+ RT_OBJECT_HOOK_CALL(rt_object_trytake_hook, (&(mb->parent.parent)));
+
+ /* disable interrupt */
+ level = rt_hw_interrupt_disable();
+
+ /* for non-blocking call */
+ if (mb->entry == 0 && timeout == 0)
+ {
+ rt_hw_interrupt_enable(level);
+
+ return -RT_ETIMEOUT;
+ }
+
+ /* mailbox is empty */
+ while (mb->entry == 0)
+ {
+ /* reset error number in thread */
+ thread->error = RT_EOK;
+
+ /* no waiting, return timeout */
+ if (timeout == 0)
+ {
+ /* enable interrupt */
+ rt_hw_interrupt_enable(level);
+
+ thread->error = -RT_ETIMEOUT;
+
+ return -RT_ETIMEOUT;
+ }
+
+ /* suspend current thread */
+ _ipc_list_suspend(&(mb->parent.suspend_thread),
+ thread,
+ mb->parent.parent.flag);
+
+ /* has waiting time, start thread timer */
+ if (timeout > 0)
+ {
+ /* get the start tick of timer */
+ tick_delta = rt_tick_get();
+
+ RT_DEBUG_LOG(RT_DEBUG_IPC, ("mb_recv: start timer of thread:%s\n",
+ thread->name));
+
+ /* reset the timeout of thread timer and start it */
+ rt_timer_control(&(thread->thread_timer),
+ RT_TIMER_CTRL_SET_TIME,
+ &timeout);
+ rt_timer_start(&(thread->thread_timer));
+ }
+
+ /* enable interrupt */
+ rt_hw_interrupt_enable(level);
+
+ /* re-schedule */
+ rt_schedule();
+
+ /* resume from suspend state */
+ if (thread->error != RT_EOK)
+ {
+ /* return error */
+ return thread->error;
+ }
+
+ /* disable interrupt */
+ level = rt_hw_interrupt_disable();
+
+ /* if it's not waiting forever and then re-calculate timeout tick */
+ if (timeout > 0)
+ {
+ tick_delta = rt_tick_get() - tick_delta;
+ timeout -= tick_delta;
+ if (timeout < 0)
+ timeout = 0;
+ }
+ }
+
+ /* fill ptr */
+ *value = mb->msg_pool[mb->out_offset];
+
+ /* increase output offset */
+ ++ mb->out_offset;
+ if (mb->out_offset >= mb->size)
+ mb->out_offset = 0;
+
+ /* decrease message entry */
+ if(mb->entry > 0)
+ {
+ mb->entry --;
+ }
+
+ /* resume suspended thread */
+ if (!rt_list_isempty(&(mb->suspend_sender_thread)))
+ {
+ _ipc_list_resume(&(mb->suspend_sender_thread));
+
+ /* enable interrupt */
+ rt_hw_interrupt_enable(level);
+
+ RT_OBJECT_HOOK_CALL(rt_object_take_hook, (&(mb->parent.parent)));
+
+ rt_schedule();
+
+ return RT_EOK;
+ }
+
+ /* enable interrupt */
+ rt_hw_interrupt_enable(level);
+
+ RT_OBJECT_HOOK_CALL(rt_object_take_hook, (&(mb->parent.parent)));
+
+ return RT_EOK;
+}
+RTM_EXPORT(rt_mb_recv);
+
+
+/**
+ * @brief This function will set some extra attributions of a mailbox object.
+ *
+ * @note Currently this function only supports the RT_IPC_CMD_RESET command to reset the mailbox.
+ *
+ * @param mb is a pointer to a mailbox object.
+ *
+ * @param cmd is a command used to configure some attributions of the mailbox.
+ *
+ * @param arg is the argument of the function to execute the command.
+ *
+ * @return Return the operation status. When the return value is RT_EOK, the operation is successful.
+ * If the return value is any other values, it means that this function failed to execute.
+ */
+rt_err_t rt_mb_control(rt_mailbox_t mb, int cmd, void *arg)
+{
+ rt_base_t level;
+
+ /* parameter check */
+ RT_ASSERT(mb != RT_NULL);
+ RT_ASSERT(rt_object_get_type(&mb->parent.parent) == RT_Object_Class_MailBox);
+
+ if (cmd == RT_IPC_CMD_RESET)
+ {
+ /* disable interrupt */
+ level = rt_hw_interrupt_disable();
+
+ /* resume all waiting thread */
+ _ipc_list_resume_all(&(mb->parent.suspend_thread));
+ /* also resume all mailbox private suspended thread */
+ _ipc_list_resume_all(&(mb->suspend_sender_thread));
+
+ /* re-init mailbox */
+ mb->entry = 0;
+ mb->in_offset = 0;
+ mb->out_offset = 0;
+
+ /* enable interrupt */
+ rt_hw_interrupt_enable(level);
+
+ rt_schedule();
+
+ return RT_EOK;
+ }
+
+ return -RT_ERROR;
+}
+RTM_EXPORT(rt_mb_control);
+
+/**@}*/
+#endif /* RT_USING_MAILBOX */
+
+#ifdef RT_USING_MESSAGEQUEUE
+/**
+ * @addtogroup messagequeue
+ */
+
+/**@{*/
+
+struct rt_mq_message
+{
+ struct rt_mq_message *next;
+};
+
+
+/**
+ * @brief Initialize a static messagequeue object.
+ *
+ * @note For the static messagequeue object, its memory space is allocated by the compiler during compiling,
+ * and shall placed on the read-write data segment or on the uninitialized data segment.
+ * By contrast, the rt_mq_create() function will allocate memory space automatically
+ * and initialize the messagequeue.
+ *
+ * @see rt_mq_create()
+ *
+ * @param mq is a pointer to the messagequeue to initialize. It is assumed that storage for
+ * the messagequeue will be allocated in your application.
+ *
+ * @param name is a pointer to the name that given to the messagequeue.
+ *
+ * @param msgpool is a pointer to the starting address of the memory space you allocated for
+ * the messagequeue in advance.
+ * In other words, msgpool is a pointer to the messagequeue buffer of the starting address.
+ *
+ * @param msg_size is the maximum length of a message in the messagequeue (Unit: Byte).
+ *
+ * @param pool_size is the size of the memory space allocated for the messagequeue in advance.
+ *
+ * @param flag is the messagequeue flag, which determines the queuing way of how multiple threads wait
+ * when the messagequeue is not available.
+ * The messagequeue flag can be ONE of the following values:
+ *
+ * RT_IPC_FLAG_PRIO The pending threads will queue in order of priority.
+ *
+ * RT_IPC_FLAG_FIFO The pending threads will queue in the first-in-first-out method
+ * (also known as first-come-first-served (FCFS) scheduling strategy).
+ *
+ * NOTE: RT_IPC_FLAG_FIFO is a non-real-time scheduling mode. It is strongly recommended to
+ * use RT_IPC_FLAG_PRIO to ensure the thread is real-time UNLESS your applications concern about
+ * the first-in-first-out principle, and you clearly understand that all threads involved in
+ * this messagequeue will become non-real-time threads.
+ *
+ * @return Return the operation status. When the return value is RT_EOK, the initialization is successful.
+ * If the return value is any other values, it represents the initialization failed.
+ *
+ * @warning This function can ONLY be called from threads.
+ */
+rt_err_t rt_mq_init(rt_mq_t mq,
+ const char *name,
+ void *msgpool,
+ rt_size_t msg_size,
+ rt_size_t pool_size,
+ rt_uint8_t flag)
+{
+ struct rt_mq_message *head;
+ rt_base_t temp;
+
+ /* parameter check */
+ RT_ASSERT(mq != RT_NULL);
+ RT_ASSERT((flag == RT_IPC_FLAG_FIFO) || (flag == RT_IPC_FLAG_PRIO));
+
+ /* initialize object */
+ rt_object_init(&(mq->parent.parent), RT_Object_Class_MessageQueue, name);
+
+ /* set parent flag */
+ mq->parent.parent.flag = flag;
+
+ /* initialize ipc object */
+ _ipc_object_init(&(mq->parent));
+
+ /* set message pool */
+ mq->msg_pool = msgpool;
+
+ /* get correct message size */
+ mq->msg_size = RT_ALIGN(msg_size, RT_ALIGN_SIZE);
+ mq->max_msgs = pool_size / (mq->msg_size + sizeof(struct rt_mq_message));
+
+ /* initialize message list */
+ mq->msg_queue_head = RT_NULL;
+ mq->msg_queue_tail = RT_NULL;
+
+ /* initialize message empty list */
+ mq->msg_queue_free = RT_NULL;
+ for (temp = 0; temp < mq->max_msgs; temp ++)
+ {
+ head = (struct rt_mq_message *)((rt_uint8_t *)mq->msg_pool +
+ temp * (mq->msg_size + sizeof(struct rt_mq_message)));
+ head->next = (struct rt_mq_message *)mq->msg_queue_free;
+ mq->msg_queue_free = head;
+ }
+
+ /* the initial entry is zero */
+ mq->entry = 0;
+
+ /* initialize an additional list of sender suspend thread */
+ rt_list_init(&(mq->suspend_sender_thread));
+
+ return RT_EOK;
+}
+RTM_EXPORT(rt_mq_init);
+
+
+/**
+ * @brief This function will detach a static messagequeue object.
+ *
+ * @note This function is used to detach a static messagequeue object which is initialized by rt_mq_init() function.
+ * By contrast, the rt_mq_delete() function will delete a messagequeue object.
+ * When the messagequeue is successfully detached, it will resume all suspended threads in the messagequeue list.
+ *
+ * @see rt_mq_delete()
+ *
+ * @param mq is a pointer to a messagequeue object to be detached.
+ *
+ * @return Return the operation status. When the return value is RT_EOK, the initialization is successful.
+ * If the return value is any other values, it means that the messagequeue detach failed.
+ *
+ * @warning This function can ONLY detach a static messagequeue initialized by the rt_mq_init() function.
+ * If the messagequeue is created by the rt_mq_create() function, you MUST NOT USE this function to detach it,
+ * and ONLY USE the rt_mq_delete() function to complete the deletion.
+ */
+rt_err_t rt_mq_detach(rt_mq_t mq)
+{
+ /* parameter check */
+ RT_ASSERT(mq != RT_NULL);
+ RT_ASSERT(rt_object_get_type(&mq->parent.parent) == RT_Object_Class_MessageQueue);
+ RT_ASSERT(rt_object_is_systemobject(&mq->parent.parent));
+
+ /* resume all suspended thread */
+ _ipc_list_resume_all(&mq->parent.suspend_thread);
+ /* also resume all message queue private suspended thread */
+ _ipc_list_resume_all(&(mq->suspend_sender_thread));
+
+ /* detach message queue object */
+ rt_object_detach(&(mq->parent.parent));
+
+ return RT_EOK;
+}
+RTM_EXPORT(rt_mq_detach);
+
+#ifdef RT_USING_HEAP
+/**
+ * @brief Creating a messagequeue object.
+ *
+ * @note For the messagequeue object, its memory space is allocated automatically.
+ * By contrast, the rt_mq_init() function will initialize a static messagequeue object.
+ *
+ * @see rt_mq_init()
+ *
+ * @param name is a pointer that given to the messagequeue.
+ *
+ * @param msg_size is the maximum length of a message in the messagequeue (Unit: Byte).
+ *
+ * @param max_msgs is the maximum number of messages in the messagequeue.
+ *
+ * @param flag is the messagequeue flag, which determines the queuing way of how multiple threads wait
+ * when the messagequeue is not available.
+ * The messagequeue flag can be ONE of the following values:
+ *
+ * RT_IPC_FLAG_PRIO The pending threads will queue in order of priority.
+ *
+ * RT_IPC_FLAG_FIFO The pending threads will queue in the first-in-first-out method
+ * (also known as first-come-first-served (FCFS) scheduling strategy).
+ *
+ * NOTE: RT_IPC_FLAG_FIFO is a non-real-time scheduling mode. It is strongly recommended to
+ * use RT_IPC_FLAG_PRIO to ensure the thread is real-time UNLESS your applications concern about
+ * the first-in-first-out principle, and you clearly understand that all threads involved in
+ * this messagequeue will become non-real-time threads.
+ *
+ * @return Return a pointer to the messagequeue object. When the return value is RT_NULL, it means the creation failed.
+ *
+ * @warning This function can NOT be called in interrupt context. You can use macor RT_DEBUG_NOT_IN_INTERRUPT to check it.
+ */
+rt_mq_t rt_mq_create(const char *name,
+ rt_size_t msg_size,
+ rt_size_t max_msgs,
+ rt_uint8_t flag)
+{
+ struct rt_messagequeue *mq;
+ struct rt_mq_message *head;
+ rt_base_t temp;
+
+ RT_ASSERT((flag == RT_IPC_FLAG_FIFO) || (flag == RT_IPC_FLAG_PRIO));
+
+ RT_DEBUG_NOT_IN_INTERRUPT;
+
+ /* allocate object */
+ mq = (rt_mq_t)rt_object_allocate(RT_Object_Class_MessageQueue, name);
+ if (mq == RT_NULL)
+ return mq;
+
+ /* set parent */
+ mq->parent.parent.flag = flag;
+
+ /* initialize ipc object */
+ _ipc_object_init(&(mq->parent));
+
+ /* initialize message queue */
+
+ /* get correct message size */
+ mq->msg_size = RT_ALIGN(msg_size, RT_ALIGN_SIZE);
+ mq->max_msgs = max_msgs;
+
+ /* allocate message pool */
+ mq->msg_pool = RT_KERNEL_MALLOC((mq->msg_size + sizeof(struct rt_mq_message)) * mq->max_msgs);
+ if (mq->msg_pool == RT_NULL)
+ {
+ rt_object_delete(&(mq->parent.parent));
+
+ return RT_NULL;
+ }
+
+ /* initialize message list */
+ mq->msg_queue_head = RT_NULL;
+ mq->msg_queue_tail = RT_NULL;
+
+ /* initialize message empty list */
+ mq->msg_queue_free = RT_NULL;
+ for (temp = 0; temp < mq->max_msgs; temp ++)
+ {
+ head = (struct rt_mq_message *)((rt_uint8_t *)mq->msg_pool +
+ temp * (mq->msg_size + sizeof(struct rt_mq_message)));
+ head->next = (struct rt_mq_message *)mq->msg_queue_free;
+ mq->msg_queue_free = head;
+ }
+
+ /* the initial entry is zero */
+ mq->entry = 0;
+
+ /* initialize an additional list of sender suspend thread */
+ rt_list_init(&(mq->suspend_sender_thread));
+
+ return mq;
+}
+RTM_EXPORT(rt_mq_create);
+
+
+/**
+ * @brief This function will delete a messagequeue object and release the memory.
+ *
+ * @note This function is used to delete a messagequeue object which is created by the rt_mq_create() function.
+ * By contrast, the rt_mq_detach() function will detach a static messagequeue object.
+ * When the messagequeue is successfully deleted, it will resume all suspended threads in the messagequeue list.
+ *
+ * @see rt_mq_detach()
+ *
+ * @param mq is a pointer to a messagequeue object to be deleted.
+ *
+ * @return Return the operation status. When the return value is RT_EOK, the operation is successful.
+ * If the return value is any other values, it means that the messagequeue detach failed.
+ *
+ * @warning This function can ONLY delete a messagequeue initialized by the rt_mq_create() function.
+ * If the messagequeue is initialized by the rt_mq_init() function, you MUST NOT USE this function to delete it,
+ * ONLY USE the rt_mq_detach() function to complete the detachment.
+ * for example,the rt_mq_create() function, it cannot be called in interrupt context.
+ */
+rt_err_t rt_mq_delete(rt_mq_t mq)
+{
+ /* parameter check */
+ RT_ASSERT(mq != RT_NULL);
+ RT_ASSERT(rt_object_get_type(&mq->parent.parent) == RT_Object_Class_MessageQueue);
+ RT_ASSERT(rt_object_is_systemobject(&mq->parent.parent) == RT_FALSE);
+
+ RT_DEBUG_NOT_IN_INTERRUPT;
+
+ /* resume all suspended thread */
+ _ipc_list_resume_all(&(mq->parent.suspend_thread));
+ /* also resume all message queue private suspended thread */
+ _ipc_list_resume_all(&(mq->suspend_sender_thread));
+
+ /* free message queue pool */
+ RT_KERNEL_FREE(mq->msg_pool);
+
+ /* delete message queue object */
+ rt_object_delete(&(mq->parent.parent));
+
+ return RT_EOK;
+}
+RTM_EXPORT(rt_mq_delete);
+#endif /* RT_USING_HEAP */
+
+
+/**
+ * @brief This function will send a message to the messagequeue object. If
+ * there is a thread suspended on the messagequeue, the thread will be
+ * resumed.
+ *
+ * @note When using this function to send a message, if the messagequeue is
+ * fully used, the current thread will wait for a timeout. If reaching
+ * the timeout and there is still no space available, the sending
+ * thread will be resumed and an error code will be returned. By
+ * contrast, the rt_mq_send() function will return an error code
+ * immediately without waiting when the messagequeue if fully used.
+ *
+ * @see rt_mq_send()
+ *
+ * @param mq is a pointer to the messagequeue object to be sent.
+ *
+ * @param buffer is the content of the message.
+ *
+ * @param size is the length of the message(Unit: Byte).
+ *
+ * @param timeout is a timeout period (unit: an OS tick).
+ *
+ * @return Return the operation status. When the return value is RT_EOK, the
+ * operation is successful. If the return value is any other values,
+ * it means that the messagequeue detach failed.
+ *
+ * @warning This function can be called in interrupt context and thread
+ * context.
+ */
+rt_err_t rt_mq_send_wait(rt_mq_t mq,
+ const void *buffer,
+ rt_size_t size,
+ rt_int32_t timeout)
+{
+ rt_base_t level;
+ struct rt_mq_message *msg;
+ rt_uint32_t tick_delta;
+ struct rt_thread *thread;
+
+ /* parameter check */
+ RT_ASSERT(mq != RT_NULL);
+ RT_ASSERT(rt_object_get_type(&mq->parent.parent) == RT_Object_Class_MessageQueue);
+ RT_ASSERT(buffer != RT_NULL);
+ RT_ASSERT(size != 0);
+
+ /* current context checking */
+ RT_DEBUG_SCHEDULER_AVAILABLE(timeout != 0);
+
+ /* greater than one message size */
+ if (size > mq->msg_size)
+ return -RT_ERROR;
+
+ /* initialize delta tick */
+ tick_delta = 0;
+ /* get current thread */
+ thread = rt_thread_self();
+
+ RT_OBJECT_HOOK_CALL(rt_object_put_hook, (&(mq->parent.parent)));
+
+ /* disable interrupt */
+ level = rt_hw_interrupt_disable();
+
+ /* get a free list, there must be an empty item */
+ msg = (struct rt_mq_message *)mq->msg_queue_free;
+ /* for non-blocking call */
+ if (msg == RT_NULL && timeout == 0)
+ {
+ /* enable interrupt */
+ rt_hw_interrupt_enable(level);
+
+ return -RT_EFULL;
+ }
+
+ /* message queue is full */
+ while ((msg = (struct rt_mq_message *)mq->msg_queue_free) == RT_NULL)
+ {
+ /* reset error number in thread */
+ thread->error = RT_EOK;
+
+ /* no waiting, return timeout */
+ if (timeout == 0)
+ {
+ /* enable interrupt */
+ rt_hw_interrupt_enable(level);
+
+ return -RT_EFULL;
+ }
+
+ /* suspend current thread */
+ _ipc_list_suspend(&(mq->suspend_sender_thread),
+ thread,
+ mq->parent.parent.flag);
+
+ /* has waiting time, start thread timer */
+ if (timeout > 0)
+ {
+ /* get the start tick of timer */
+ tick_delta = rt_tick_get();
+
+ RT_DEBUG_LOG(RT_DEBUG_IPC, ("mq_send_wait: start timer of thread:%s\n",
+ thread->name));
+
+ /* reset the timeout of thread timer and start it */
+ rt_timer_control(&(thread->thread_timer),
+ RT_TIMER_CTRL_SET_TIME,
+ &timeout);
+ rt_timer_start(&(thread->thread_timer));
+ }
+
+ /* enable interrupt */
+ rt_hw_interrupt_enable(level);
+
+ /* re-schedule */
+ rt_schedule();
+
+ /* resume from suspend state */
+ if (thread->error != RT_EOK)
+ {
+ /* return error */
+ return thread->error;
+ }
+
+ /* disable interrupt */
+ level = rt_hw_interrupt_disable();
+
+ /* if it's not waiting forever and then re-calculate timeout tick */
+ if (timeout > 0)
+ {
+ tick_delta = rt_tick_get() - tick_delta;
+ timeout -= tick_delta;
+ if (timeout < 0)
+ timeout = 0;
+ }
+ }
+
+ /* move free list pointer */
+ mq->msg_queue_free = msg->next;
+
+ /* enable interrupt */
+ rt_hw_interrupt_enable(level);
+
+ /* the msg is the new tailer of list, the next shall be NULL */
+ msg->next = RT_NULL;
+ /* copy buffer */
+ rt_memcpy(msg + 1, buffer, size);
+
+ /* disable interrupt */
+ level = rt_hw_interrupt_disable();
+ /* link msg to message queue */
+ if (mq->msg_queue_tail != RT_NULL)
+ {
+ /* if the tail exists, */
+ ((struct rt_mq_message *)mq->msg_queue_tail)->next = msg;
+ }
+
+ /* set new tail */
+ mq->msg_queue_tail = msg;
+ /* if the head is empty, set head */
+ if (mq->msg_queue_head == RT_NULL)
+ mq->msg_queue_head = msg;
+
+ if(mq->entry < RT_MQ_ENTRY_MAX)
+ {
+ /* increase message entry */
+ mq->entry ++;
+ }
+ else
+ {
+ rt_hw_interrupt_enable(level); /* enable interrupt */
+ return -RT_EFULL; /* value overflowed */
+ }
+
+ /* resume suspended thread */
+ if (!rt_list_isempty(&mq->parent.suspend_thread))
+ {
+ _ipc_list_resume(&(mq->parent.suspend_thread));
+
+ /* enable interrupt */
+ rt_hw_interrupt_enable(level);
+
+ rt_schedule();
+
+ return RT_EOK;
+ }
+
+ /* enable interrupt */
+ rt_hw_interrupt_enable(level);
+
+ return RT_EOK;
+}
+RTM_EXPORT(rt_mq_send_wait)
+
+
+/**
+ * @brief This function will send a message to the messagequeue object.
+ * If there is a thread suspended on the messagequeue, the thread will be resumed.
+ *
+ * @note When using this function to send a message, if the messagequeue is fully used,
+ * the current thread will wait for a timeout.
+ * By contrast, when the messagequeue is fully used, the rt_mq_send_wait() function will
+ * return an error code immediately without waiting.
+ *
+ * @see rt_mq_send_wait()
+ *
+ * @param mq is a pointer to the messagequeue object to be sent.
+ *
+ * @param buffer is the content of the message.
+ *
+ * @param size is the length of the message(Unit: Byte).
+ *
+ * @return Return the operation status. When the return value is RT_EOK, the operation is successful.
+ * If the return value is any other values, it means that the messagequeue detach failed.
+ *
+ * @warning This function can be called in interrupt context and thread context.
+ */
+rt_err_t rt_mq_send(rt_mq_t mq, const void *buffer, rt_size_t size)
+{
+ return rt_mq_send_wait(mq, buffer, size, 0);
+}
+RTM_EXPORT(rt_mq_send);
+
+
+/**
+ * @brief This function will send an urgent message to the messagequeue object.
+ *
+ * @note This function is almost the same as the rt_mq_send() function. The only difference is that
+ * when sending an urgent message, the message is placed at the head of the messagequeue so that
+ * the recipient can receive the urgent message first.
+ *
+ * @see rt_mq_send()
+ *
+ * @param mq is a pointer to the messagequeue object to be sent.
+ *
+ * @param buffer is the content of the message.
+ *
+ * @param size is the length of the message(Unit: Byte).
+ *
+ * @return Return the operation status. When the return value is RT_EOK, the operation is successful.
+ * If the return value is any other values, it means that the mailbox detach failed.
+ */
+rt_err_t rt_mq_urgent(rt_mq_t mq, const void *buffer, rt_size_t size)
+{
+ rt_base_t level;
+ struct rt_mq_message *msg;
+
+ /* parameter check */
+ RT_ASSERT(mq != RT_NULL);
+ RT_ASSERT(rt_object_get_type(&mq->parent.parent) == RT_Object_Class_MessageQueue);
+ RT_ASSERT(buffer != RT_NULL);
+ RT_ASSERT(size != 0);
+
+ /* greater than one message size */
+ if (size > mq->msg_size)
+ return -RT_ERROR;
+
+ RT_OBJECT_HOOK_CALL(rt_object_put_hook, (&(mq->parent.parent)));
+
+ /* disable interrupt */
+ level = rt_hw_interrupt_disable();
+
+ /* get a free list, there must be an empty item */
+ msg = (struct rt_mq_message *)mq->msg_queue_free;
+ /* message queue is full */
+ if (msg == RT_NULL)
+ {
+ /* enable interrupt */
+ rt_hw_interrupt_enable(level);
+
+ return -RT_EFULL;
+ }
+ /* move free list pointer */
+ mq->msg_queue_free = msg->next;
+
+ /* enable interrupt */
+ rt_hw_interrupt_enable(level);
+
+ /* copy buffer */
+ rt_memcpy(msg + 1, buffer, size);
+
+ /* disable interrupt */
+ level = rt_hw_interrupt_disable();
+
+ /* link msg to the beginning of message queue */
+ msg->next = (struct rt_mq_message *)mq->msg_queue_head;
+ mq->msg_queue_head = msg;
+
+ /* if there is no tail */
+ if (mq->msg_queue_tail == RT_NULL)
+ mq->msg_queue_tail = msg;
+
+ if(mq->entry < RT_MQ_ENTRY_MAX)
+ {
+ /* increase message entry */
+ mq->entry ++;
+ }
+ else
+ {
+ rt_hw_interrupt_enable(level); /* enable interrupt */
+ return -RT_EFULL; /* value overflowed */
+ }
+
+ /* resume suspended thread */
+ if (!rt_list_isempty(&mq->parent.suspend_thread))
+ {
+ _ipc_list_resume(&(mq->parent.suspend_thread));
+
+ /* enable interrupt */
+ rt_hw_interrupt_enable(level);
+
+ rt_schedule();
+
+ return RT_EOK;
+ }
+
+ /* enable interrupt */
+ rt_hw_interrupt_enable(level);
+
+ return RT_EOK;
+}
+RTM_EXPORT(rt_mq_urgent);
+
+
+/**
+ * @brief This function will receive a message from message queue object,
+ * if there is no message in messagequeue object, the thread shall wait for a specified time.
+ *
+ * @note Only when there is mail in the mailbox, the receiving thread can get the mail immediately and return RT_EOK,
+ * otherwise the receiving thread will be suspended until timeout.
+ * If the mail is not received within the specified time, it will return -RT_ETIMEOUT.
+ *
+ * @param mq is a pointer to the messagequeue object to be received.
+ *
+ * @param buffer is the content of the message.
+ *
+ * @param size is the length of the message(Unit: Byte).
+ *
+ * @param timeout is a timeout period (unit: an OS tick). If the message is unavailable, the thread will wait for
+ * the message in the queue up to the amount of time specified by this parameter.
+ *
+ * NOTE:
+ * If use Macro RT_WAITING_FOREVER to set this parameter, which means that when the
+ * message is unavailable in the queue, the thread will be waiting forever.
+ * If use macro RT_WAITING_NO to set this parameter, which means that this
+ * function is non-blocking and will return immediately.
+ *
+ * @return Return the operation status. When the return value is RT_EOK, the operation is successful.
+ * If the return value is any other values, it means that the mailbox release failed.
+ */
+rt_err_t rt_mq_recv(rt_mq_t mq,
+ void *buffer,
+ rt_size_t size,
+ rt_int32_t timeout)
+{
+ struct rt_thread *thread;
+ rt_base_t level;
+ struct rt_mq_message *msg;
+ rt_uint32_t tick_delta;
+
+ /* parameter check */
+ RT_ASSERT(mq != RT_NULL);
+ RT_ASSERT(rt_object_get_type(&mq->parent.parent) == RT_Object_Class_MessageQueue);
+ RT_ASSERT(buffer != RT_NULL);
+ RT_ASSERT(size != 0);
+
+ /* current context checking */
+ RT_DEBUG_SCHEDULER_AVAILABLE(timeout != 0);
+
+ /* initialize delta tick */
+ tick_delta = 0;
+ /* get current thread */
+ thread = rt_thread_self();
+ RT_OBJECT_HOOK_CALL(rt_object_trytake_hook, (&(mq->parent.parent)));
+
+ /* disable interrupt */
+ level = rt_hw_interrupt_disable();
+
+ /* for non-blocking call */
+ if (mq->entry == 0 && timeout == 0)
+ {
+ rt_hw_interrupt_enable(level);
+
+ return -RT_ETIMEOUT;
+ }
+
+ /* message queue is empty */
+ while (mq->entry == 0)
+ {
+ /* reset error number in thread */
+ thread->error = RT_EOK;
+
+ /* no waiting, return timeout */
+ if (timeout == 0)
+ {
+ /* enable interrupt */
+ rt_hw_interrupt_enable(level);
+
+ thread->error = -RT_ETIMEOUT;
+
+ return -RT_ETIMEOUT;
+ }
+
+ /* suspend current thread */
+ _ipc_list_suspend(&(mq->parent.suspend_thread),
+ thread,
+ mq->parent.parent.flag);
+
+ /* has waiting time, start thread timer */
+ if (timeout > 0)
+ {
+ /* get the start tick of timer */
+ tick_delta = rt_tick_get();
+
+ RT_DEBUG_LOG(RT_DEBUG_IPC, ("set thread:%s to timer list\n",
+ thread->name));
+
+ /* reset the timeout of thread timer and start it */
+ rt_timer_control(&(thread->thread_timer),
+ RT_TIMER_CTRL_SET_TIME,
+ &timeout);
+ rt_timer_start(&(thread->thread_timer));
+ }
+
+ /* enable interrupt */
+ rt_hw_interrupt_enable(level);
+
+ /* re-schedule */
+ rt_schedule();
+
+ /* recv message */
+ if (thread->error != RT_EOK)
+ {
+ /* return error */
+ return thread->error;
+ }
+
+ /* disable interrupt */
+ level = rt_hw_interrupt_disable();
+
+ /* if it's not waiting forever and then re-calculate timeout tick */
+ if (timeout > 0)
+ {
+ tick_delta = rt_tick_get() - tick_delta;
+ timeout -= tick_delta;
+ if (timeout < 0)
+ timeout = 0;
+ }
+ }
+
+ /* get message from queue */
+ msg = (struct rt_mq_message *)mq->msg_queue_head;
+
+ /* move message queue head */
+ mq->msg_queue_head = msg->next;
+ /* reach queue tail, set to NULL */
+ if (mq->msg_queue_tail == msg)
+ mq->msg_queue_tail = RT_NULL;
+
+ /* decrease message entry */
+ if(mq->entry > 0)
+ {
+ mq->entry --;
+ }
+
+ /* enable interrupt */
+ rt_hw_interrupt_enable(level);
+
+ /* copy message */
+ rt_memcpy(buffer, msg + 1, size > mq->msg_size ? mq->msg_size : size);
+
+ /* disable interrupt */
+ level = rt_hw_interrupt_disable();
+ /* put message to free list */
+ msg->next = (struct rt_mq_message *)mq->msg_queue_free;
+ mq->msg_queue_free = msg;
+
+ /* resume suspended thread */
+ if (!rt_list_isempty(&(mq->suspend_sender_thread)))
+ {
+ _ipc_list_resume(&(mq->suspend_sender_thread));
+
+ /* enable interrupt */
+ rt_hw_interrupt_enable(level);
+
+ RT_OBJECT_HOOK_CALL(rt_object_take_hook, (&(mq->parent.parent)));
+
+ rt_schedule();
+
+ return RT_EOK;
+ }
+
+ /* enable interrupt */
+ rt_hw_interrupt_enable(level);
+
+ RT_OBJECT_HOOK_CALL(rt_object_take_hook, (&(mq->parent.parent)));
+
+ return RT_EOK;
+}
+RTM_EXPORT(rt_mq_recv);
+
+
+/**
+ * @brief This function will set some extra attributions of a messagequeue object.
+ *
+ * @note Currently this function only supports the RT_IPC_CMD_RESET command to reset the messagequeue.
+ *
+ * @param mq is a pointer to a messagequeue object.
+ *
+ * @param cmd is a command used to configure some attributions of the messagequeue.
+ *
+ * @param arg is the argument of the function to execute the command.
+ *
+ * @return Return the operation status. When the return value is RT_EOK, the operation is successful.
+ * If the return value is any other values, it means that this function failed to execute.
+ */
+rt_err_t rt_mq_control(rt_mq_t mq, int cmd, void *arg)
+{
+ rt_base_t level;
+ struct rt_mq_message *msg;
+
+ /* parameter check */
+ RT_ASSERT(mq != RT_NULL);
+ RT_ASSERT(rt_object_get_type(&mq->parent.parent) == RT_Object_Class_MessageQueue);
+
+ if (cmd == RT_IPC_CMD_RESET)
+ {
+ /* disable interrupt */
+ level = rt_hw_interrupt_disable();
+
+ /* resume all waiting thread */
+ _ipc_list_resume_all(&mq->parent.suspend_thread);
+ /* also resume all message queue private suspended thread */
+ _ipc_list_resume_all(&(mq->suspend_sender_thread));
+
+ /* release all message in the queue */
+ while (mq->msg_queue_head != RT_NULL)
+ {
+ /* get message from queue */
+ msg = (struct rt_mq_message *)mq->msg_queue_head;
+
+ /* move message queue head */
+ mq->msg_queue_head = msg->next;
+ /* reach queue tail, set to NULL */
+ if (mq->msg_queue_tail == msg)
+ mq->msg_queue_tail = RT_NULL;
+
+ /* put message to free list */
+ msg->next = (struct rt_mq_message *)mq->msg_queue_free;
+ mq->msg_queue_free = msg;
+ }
+
+ /* clean entry */
+ mq->entry = 0;
+
+ /* enable interrupt */
+ rt_hw_interrupt_enable(level);
+
+ rt_schedule();
+
+ return RT_EOK;
+ }
+
+ return -RT_ERROR;
+}
+RTM_EXPORT(rt_mq_control);
+
+/**@}*/
+#endif /* RT_USING_MESSAGEQUEUE */
+
+/**@}*/
diff --git a/User/system/rt-thread/src/irq.c b/User/system/rt-thread/src/irq.c
new file mode 100644
index 0000000..c417f25
--- /dev/null
+++ b/User/system/rt-thread/src/irq.c
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2006-02-24 Bernard first version
+ * 2006-05-03 Bernard add IRQ_DEBUG
+ * 2016-08-09 ArdaFu add interrupt enter and leave hook.
+ * 2018-11-22 Jesven rt_interrupt_get_nest function add disable irq
+ * 2021-08-15 Supperthomas fix the comment
+ * 2022-01-07 Gabriel Moving __on_rt_xxxxx_hook to irq.c
+ * 2022-07-04 Yunjie fix RT_DEBUG_LOG
+ */
+
+#include
+#include
+
+#ifndef __on_rt_interrupt_enter_hook
+ #define __on_rt_interrupt_enter_hook() __ON_HOOK_ARGS(rt_interrupt_enter_hook, ())
+#endif
+#ifndef __on_rt_interrupt_leave_hook
+ #define __on_rt_interrupt_leave_hook() __ON_HOOK_ARGS(rt_interrupt_leave_hook, ())
+#endif
+
+#if defined(RT_USING_HOOK) && defined(RT_HOOK_USING_FUNC_PTR)
+
+static void (*rt_interrupt_enter_hook)(void);
+static void (*rt_interrupt_leave_hook)(void);
+
+/**
+ * @ingroup Hook
+ *
+ * @brief This function set a hook function when the system enter a interrupt
+ *
+ * @note The hook function must be simple and never be blocked or suspend.
+ *
+ * @param hook the function point to be called
+ */
+void rt_interrupt_enter_sethook(void (*hook)(void))
+{
+ rt_interrupt_enter_hook = hook;
+}
+
+/**
+ * @ingroup Hook
+ *
+ * @brief This function set a hook function when the system exit a interrupt.
+ *
+ * @note The hook function must be simple and never be blocked or suspend.
+ *
+ * @param hook the function point to be called
+ */
+void rt_interrupt_leave_sethook(void (*hook)(void))
+{
+ rt_interrupt_leave_hook = hook;
+}
+#endif /* RT_USING_HOOK */
+
+/**
+ * @addtogroup Kernel
+ */
+
+/**@{*/
+
+#ifdef RT_USING_SMP
+#define rt_interrupt_nest rt_cpu_self()->irq_nest
+#else
+volatile rt_uint8_t rt_interrupt_nest = 0;
+#endif /* RT_USING_SMP */
+
+
+/**
+ * @brief This function will be invoked by BSP, when enter interrupt service routine
+ *
+ * @note Please don't invoke this routine in application
+ *
+ * @see rt_interrupt_leave
+ */
+void rt_interrupt_enter(void)
+{
+ rt_base_t level;
+
+ level = rt_hw_interrupt_disable();
+ rt_interrupt_nest ++;
+ RT_OBJECT_HOOK_CALL(rt_interrupt_enter_hook,());
+ rt_hw_interrupt_enable(level);
+
+ RT_DEBUG_LOG(RT_DEBUG_IRQ, ("irq has come..., irq current nest:%d\n",
+ (rt_int32_t)rt_interrupt_nest));
+}
+RTM_EXPORT(rt_interrupt_enter);
+
+
+/**
+ * @brief This function will be invoked by BSP, when leave interrupt service routine
+ *
+ * @note Please don't invoke this routine in application
+ *
+ * @see rt_interrupt_enter
+ */
+void rt_interrupt_leave(void)
+{
+ rt_base_t level;
+
+ RT_DEBUG_LOG(RT_DEBUG_IRQ, ("irq is going to leave, irq current nest:%d\n",
+ (rt_int32_t)rt_interrupt_nest));
+
+ level = rt_hw_interrupt_disable();
+ RT_OBJECT_HOOK_CALL(rt_interrupt_leave_hook,());
+ rt_interrupt_nest --;
+ rt_hw_interrupt_enable(level);
+}
+RTM_EXPORT(rt_interrupt_leave);
+
+
+/**
+ * @brief This function will return the nest of interrupt.
+ *
+ * User application can invoke this function to get whether current
+ * context is interrupt context.
+ *
+ * @return the number of nested interrupts.
+ */
+RT_WEAK rt_uint8_t rt_interrupt_get_nest(void)
+{
+ rt_uint8_t ret;
+ rt_base_t level;
+
+ level = rt_hw_interrupt_disable();
+ ret = rt_interrupt_nest;
+ rt_hw_interrupt_enable(level);
+ return ret;
+}
+RTM_EXPORT(rt_interrupt_get_nest);
+
+RTM_EXPORT(rt_hw_interrupt_disable);
+RTM_EXPORT(rt_hw_interrupt_enable);
+
+/**@}*/
+
diff --git a/User/system/rt-thread/src/kservice.c b/User/system/rt-thread/src/kservice.c
new file mode 100644
index 0000000..ef7f38b
--- /dev/null
+++ b/User/system/rt-thread/src/kservice.c
@@ -0,0 +1,1848 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2006-03-16 Bernard the first version
+ * 2006-05-25 Bernard rewrite vsprintf
+ * 2006-08-10 Bernard add rt_show_version
+ * 2010-03-17 Bernard remove rt_strlcpy function
+ * fix gcc compiling issue.
+ * 2010-04-15 Bernard remove weak definition on ICCM16C compiler
+ * 2012-07-18 Arda add the alignment display for signed integer
+ * 2012-11-23 Bernard fix IAR compiler error.
+ * 2012-12-22 Bernard fix rt_kprintf issue, which found by Grissiom.
+ * 2013-06-24 Bernard remove rt_kprintf if RT_USING_CONSOLE is not defined.
+ * 2013-09-24 aozima make sure the device is in STREAM mode when used by rt_kprintf.
+ * 2015-07-06 Bernard Add rt_assert_handler routine.
+ * 2021-02-28 Meco Man add RT_KSERVICE_USING_STDLIB
+ * 2021-12-20 Meco Man implement rt_strcpy()
+ * 2022-01-07 Gabriel add __on_rt_assert_hook
+ * 2022-06-04 Meco Man remove strnlen
+ */
+
+#include
+#include
+
+#ifdef RT_USING_MODULE
+#include
+#endif /* RT_USING_MODULE */
+
+/* use precision */
+#define RT_PRINTF_PRECISION
+
+/**
+ * @addtogroup KernelService
+ */
+
+/**@{*/
+
+/* global errno in RT-Thread */
+static volatile int __rt_errno;
+
+#if defined(RT_USING_DEVICE) && defined(RT_USING_CONSOLE)
+static rt_device_t _console_device = RT_NULL;
+#endif
+
+RT_WEAK void rt_hw_us_delay(rt_uint32_t us)
+{
+ (void) us;
+ RT_DEBUG_LOG(RT_DEBUG_DEVICE, ("rt_hw_us_delay() doesn't support for this board."
+ "Please consider implementing rt_hw_us_delay() in another file.\n"));
+}
+
+static const char* rt_errno_strs[] =
+{
+ "OK",
+ "ERROR",
+ "ETIMOUT",
+ "ERSFULL",
+ "ERSEPTY",
+ "ENOMEM",
+ "ENOSYS",
+ "EBUSY",
+ "EIO",
+ "EINTRPT",
+ "EINVAL",
+ "EUNKNOW"
+};
+
+/**
+ * This function return a pointer to a string that contains the
+ * message of error.
+ *
+ * @param error the errorno code
+ * @return a point to error message string
+ */
+const char *rt_strerror(rt_err_t error)
+{
+ if (error < 0)
+ error = -error;
+
+ return (error > RT_EINVAL + 1) ?
+ rt_errno_strs[RT_EINVAL + 1] :
+ rt_errno_strs[error];
+}
+RTM_EXPORT(rt_strerror);
+
+/**
+ * This function gets the global errno for the current thread.
+ *
+ * @return errno
+ */
+rt_err_t rt_get_errno(void)
+{
+ rt_thread_t tid;
+
+ if (rt_interrupt_get_nest() != 0)
+ {
+ /* it's in interrupt context */
+ return __rt_errno;
+ }
+
+ tid = rt_thread_self();
+ if (tid == RT_NULL)
+ return __rt_errno;
+
+ return tid->error;
+}
+RTM_EXPORT(rt_get_errno);
+
+/**
+ * This function sets the global errno for the current thread.
+ *
+ * @param error is the errno shall be set.
+ */
+void rt_set_errno(rt_err_t error)
+{
+ rt_thread_t tid;
+
+ if (rt_interrupt_get_nest() != 0)
+ {
+ /* it's in interrupt context */
+ __rt_errno = error;
+
+ return;
+ }
+
+ tid = rt_thread_self();
+ if (tid == RT_NULL)
+ {
+ __rt_errno = error;
+
+ return;
+ }
+
+ tid->error = error;
+}
+RTM_EXPORT(rt_set_errno);
+
+/**
+ * This function returns the address of the current thread errno.
+ *
+ * @return The errno address.
+ */
+int *_rt_errno(void)
+{
+ rt_thread_t tid;
+
+ if (rt_interrupt_get_nest() != 0)
+ return (int *)&__rt_errno;
+
+ tid = rt_thread_self();
+ if (tid != RT_NULL)
+ return (int *) & (tid->error);
+
+ return (int *)&__rt_errno;
+}
+RTM_EXPORT(_rt_errno);
+
+#ifndef RT_KSERVICE_USING_STDLIB_MEMORY
+/**
+ * This function will set the content of memory to specified value.
+ *
+ * @param s is the address of source memory, point to the memory block to be filled.
+ *
+ * @param c is the value to be set. The value is passed in int form, but the function
+ * uses the unsigned character form of the value when filling the memory block.
+ *
+ * @param count number of bytes to be set.
+ *
+ * @return The address of source memory.
+ */
+RT_WEAK void *rt_memset(void *s, int c, rt_ubase_t count)
+{
+#ifdef RT_KSERVICE_USING_TINY_SIZE
+ char *xs = (char *)s;
+
+ while (count--)
+ *xs++ = c;
+
+ return s;
+#else
+#define LBLOCKSIZE (sizeof(long))
+#define UNALIGNED(X) ((long)X & (LBLOCKSIZE - 1))
+#define TOO_SMALL(LEN) ((LEN) < LBLOCKSIZE)
+
+ unsigned int i;
+ char *m = (char *)s;
+ unsigned long buffer;
+ unsigned long *aligned_addr;
+ unsigned int d = c & 0xff; /* To avoid sign extension, copy C to an
+ unsigned variable. */
+
+ if (!TOO_SMALL(count) && !UNALIGNED(s))
+ {
+ /* If we get this far, we know that count is large and s is word-aligned. */
+ aligned_addr = (unsigned long *)s;
+
+ /* Store d into each char sized location in buffer so that
+ * we can set large blocks quickly.
+ */
+ if (LBLOCKSIZE == 4)
+ {
+ buffer = (d << 8) | d;
+ buffer |= (buffer << 16);
+ }
+ else
+ {
+ buffer = 0;
+ for (i = 0; i < LBLOCKSIZE; i ++)
+ buffer = (buffer << 8) | d;
+ }
+
+ while (count >= LBLOCKSIZE * 4)
+ {
+ *aligned_addr++ = buffer;
+ *aligned_addr++ = buffer;
+ *aligned_addr++ = buffer;
+ *aligned_addr++ = buffer;
+ count -= 4 * LBLOCKSIZE;
+ }
+
+ while (count >= LBLOCKSIZE)
+ {
+ *aligned_addr++ = buffer;
+ count -= LBLOCKSIZE;
+ }
+
+ /* Pick up the remainder with a bytewise loop. */
+ m = (char *)aligned_addr;
+ }
+
+ while (count--)
+ {
+ *m++ = (char)d;
+ }
+
+ return s;
+
+#undef LBLOCKSIZE
+#undef UNALIGNED
+#undef TOO_SMALL
+#endif /* RT_KSERVICE_USING_TINY_SIZE */
+}
+RTM_EXPORT(rt_memset);
+
+/**
+ * This function will copy memory content from source address to destination address.
+ *
+ * @param dst is the address of destination memory, points to the copied content.
+ *
+ * @param src is the address of source memory, pointing to the data source to be copied.
+ *
+ * @param count is the copied length.
+ *
+ * @return The address of destination memory
+ */
+RT_WEAK void *rt_memcpy(void *dst, const void *src, rt_ubase_t count)
+{
+#ifdef RT_KSERVICE_USING_TINY_SIZE
+ char *tmp = (char *)dst, *s = (char *)src;
+ rt_ubase_t len;
+
+ if (tmp <= s || tmp > (s + count))
+ {
+ while (count--)
+ *tmp ++ = *s ++;
+ }
+ else
+ {
+ for (len = count; len > 0; len --)
+ tmp[len - 1] = s[len - 1];
+ }
+
+ return dst;
+#else
+
+#define UNALIGNED(X, Y) \
+ (((long)X & (sizeof (long) - 1)) | ((long)Y & (sizeof (long) - 1)))
+#define BIGBLOCKSIZE (sizeof (long) << 2)
+#define LITTLEBLOCKSIZE (sizeof (long))
+#define TOO_SMALL(LEN) ((LEN) < BIGBLOCKSIZE)
+
+ char *dst_ptr = (char *)dst;
+ char *src_ptr = (char *)src;
+ long *aligned_dst;
+ long *aligned_src;
+ rt_ubase_t len = count;
+
+ /* If the size is small, or either SRC or DST is unaligned,
+ then punt into the byte copy loop. This should be rare. */
+ if (!TOO_SMALL(len) && !UNALIGNED(src_ptr, dst_ptr))
+ {
+ aligned_dst = (long *)dst_ptr;
+ aligned_src = (long *)src_ptr;
+
+ /* Copy 4X long words at a time if possible. */
+ while (len >= BIGBLOCKSIZE)
+ {
+ *aligned_dst++ = *aligned_src++;
+ *aligned_dst++ = *aligned_src++;
+ *aligned_dst++ = *aligned_src++;
+ *aligned_dst++ = *aligned_src++;
+ len -= BIGBLOCKSIZE;
+ }
+
+ /* Copy one long word at a time if possible. */
+ while (len >= LITTLEBLOCKSIZE)
+ {
+ *aligned_dst++ = *aligned_src++;
+ len -= LITTLEBLOCKSIZE;
+ }
+
+ /* Pick up any residual with a byte copier. */
+ dst_ptr = (char *)aligned_dst;
+ src_ptr = (char *)aligned_src;
+ }
+
+ while (len--)
+ *dst_ptr++ = *src_ptr++;
+
+ return dst;
+#undef UNALIGNED
+#undef BIGBLOCKSIZE
+#undef LITTLEBLOCKSIZE
+#undef TOO_SMALL
+#endif /* RT_KSERVICE_USING_TINY_SIZE */
+}
+RTM_EXPORT(rt_memcpy);
+
+/**
+ * This function will move memory content from source address to destination
+ * address. If the destination memory does not overlap with the source memory,
+ * the function is the same as memcpy().
+ *
+ * @param dest is the address of destination memory, points to the copied content.
+ *
+ * @param src is the address of source memory, point to the data source to be copied.
+ *
+ * @param n is the copied length.
+ *
+ * @return The address of destination memory.
+ */
+void *rt_memmove(void *dest, const void *src, rt_size_t n)
+{
+ char *tmp = (char *)dest, *s = (char *)src;
+
+ if (s < tmp && tmp < s + n)
+ {
+ tmp += n;
+ s += n;
+
+ while (n--)
+ *(--tmp) = *(--s);
+ }
+ else
+ {
+ while (n--)
+ *tmp++ = *s++;
+ }
+
+ return dest;
+}
+RTM_EXPORT(rt_memmove);
+
+/**
+ * This function will compare two areas of memory.
+ *
+ * @param cs is a block of memory.
+ *
+ * @param ct is another block of memory.
+ *
+ * @param count is the size of the area.
+ *
+ * @return Compare the results:
+ * If the result < 0, cs is smaller than ct.
+ * If the result > 0, cs is greater than ct.
+ * If the result = 0, cs is equal to ct.
+ */
+rt_int32_t rt_memcmp(const void *cs, const void *ct, rt_size_t count)
+{
+ const unsigned char *su1, *su2;
+ int res = 0;
+
+ for (su1 = (const unsigned char *)cs, su2 = (const unsigned char *)ct; 0 < count; ++su1, ++su2, count--)
+ if ((res = *su1 - *su2) != 0)
+ break;
+
+ return res;
+}
+RTM_EXPORT(rt_memcmp);
+#endif /* RT_KSERVICE_USING_STDLIB_MEMORY*/
+
+#ifndef RT_KSERVICE_USING_STDLIB
+/**
+ * This function will return the first occurrence of a string, without the
+ * terminator '\0'.
+ *
+ * @param s1 is the source string.
+ *
+ * @param s2 is the find string.
+ *
+ * @return The first occurrence of a s2 in s1, or RT_NULL if no found.
+ */
+char *rt_strstr(const char *s1, const char *s2)
+{
+ int l1, l2;
+
+ l2 = rt_strlen(s2);
+ if (!l2)
+ return (char *)s1;
+ l1 = rt_strlen(s1);
+ while (l1 >= l2)
+ {
+ l1 --;
+ if (!rt_memcmp(s1, s2, l2))
+ return (char *)s1;
+ s1 ++;
+ }
+
+ return RT_NULL;
+}
+RTM_EXPORT(rt_strstr);
+
+/**
+ * This function will compare two strings while ignoring differences in case
+ *
+ * @param a is the string to be compared.
+ *
+ * @param b is the string to be compared.
+ *
+ * @return Compare the results:
+ * If the result < 0, a is smaller than a.
+ * If the result > 0, a is greater than a.
+ * If the result = 0, a is equal to a.
+ */
+rt_int32_t rt_strcasecmp(const char *a, const char *b)
+{
+ int ca, cb;
+
+ do
+ {
+ ca = *a++ & 0xff;
+ cb = *b++ & 0xff;
+ if (ca >= 'A' && ca <= 'Z')
+ ca += 'a' - 'A';
+ if (cb >= 'A' && cb <= 'Z')
+ cb += 'a' - 'A';
+ }
+ while (ca == cb && ca != '\0');
+
+ return ca - cb;
+}
+RTM_EXPORT(rt_strcasecmp);
+
+/**
+ * This function will copy string no more than n bytes.
+ *
+ * @param dst points to the address used to store the copied content.
+ *
+ * @param src is the string to be copied.
+ *
+ * @param n is the maximum copied length.
+ *
+ * @return The address where the copied content is stored.
+ */
+char *rt_strncpy(char *dst, const char *src, rt_size_t n)
+{
+ if (n != 0)
+ {
+ char *d = dst;
+ const char *s = src;
+
+ do
+ {
+ if ((*d++ = *s++) == 0)
+ {
+ /* NUL pad the remaining n-1 bytes */
+ while (--n != 0)
+ *d++ = 0;
+ break;
+ }
+ } while (--n != 0);
+ }
+
+ return (dst);
+}
+RTM_EXPORT(rt_strncpy);
+
+/**
+ * This function will copy string.
+ *
+ * @param dst points to the address used to store the copied content.
+ *
+ * @param src is the string to be copied.
+ *
+ * @return The address where the copied content is stored.
+ */
+char *rt_strcpy(char *dst, const char *src)
+{
+ char *dest = dst;
+
+ while (*src != '\0')
+ {
+ *dst = *src;
+ dst++;
+ src++;
+ }
+
+ *dst = '\0';
+ return dest;
+}
+RTM_EXPORT(rt_strcpy);
+
+/**
+ * This function will compare two strings with specified maximum length.
+ *
+ * @param cs is the string to be compared.
+ *
+ * @param ct is the string to be compared.
+ *
+ * @param count is the maximum compare length.
+ *
+ * @return Compare the results:
+ * If the result < 0, cs is smaller than ct.
+ * If the result > 0, cs is greater than ct.
+ * If the result = 0, cs is equal to ct.
+ */
+rt_int32_t rt_strncmp(const char *cs, const char *ct, rt_size_t count)
+{
+ signed char __res = 0;
+
+ while (count)
+ {
+ if ((__res = *cs - *ct++) != 0 || !*cs++)
+ break;
+ count --;
+ }
+
+ return __res;
+}
+RTM_EXPORT(rt_strncmp);
+
+/**
+ * This function will compare two strings without specified length.
+ *
+ * @param cs is the string to be compared.
+ *
+ * @param ct is the string to be compared.
+ *
+ * @return Compare the results:
+ * If the result < 0, cs is smaller than ct.
+ * If the result > 0, cs is greater than ct.
+ * If the result = 0, cs is equal to ct.
+ */
+rt_int32_t rt_strcmp(const char *cs, const char *ct)
+{
+ while (*cs && *cs == *ct)
+ {
+ cs++;
+ ct++;
+ }
+
+ return (*cs - *ct);
+}
+RTM_EXPORT(rt_strcmp);
+
+/**
+ * This function will return the length of a string, which terminate will
+ * null character.
+ *
+ * @param s is the string
+ *
+ * @return The length of string.
+ */
+rt_size_t rt_strlen(const char *s)
+{
+ const char *sc;
+
+ for (sc = s; *sc != '\0'; ++sc) /* nothing */
+ ;
+
+ return sc - s;
+}
+RTM_EXPORT(rt_strlen);
+
+#endif /* RT_KSERVICE_USING_STDLIB */
+
+/**
+ * The strnlen() function returns the number of characters in the
+ * string pointed to by s, excluding the terminating null byte ('\0'),
+ * but at most maxlen. In doing this, strnlen() looks only at the
+ * first maxlen characters in the string pointed to by s and never
+ * beyond s+maxlen.
+ *
+ * @param s is the string.
+ *
+ * @param maxlen is the max size.
+ *
+ * @return The length of string.
+ */
+rt_size_t rt_strnlen(const char *s, rt_ubase_t maxlen)
+{
+ const char *sc;
+
+ for (sc = s; *sc != '\0' && (rt_ubase_t)(sc - s) < maxlen; ++sc) /* nothing */
+ ;
+
+ return sc - s;
+}
+RTM_EXPORT(rt_strnlen);
+
+#ifdef RT_USING_HEAP
+/**
+ * This function will duplicate a string.
+ *
+ * @param s is the string to be duplicated.
+ *
+ * @return The string address of the copy.
+ */
+char *rt_strdup(const char *s)
+{
+ rt_size_t len = rt_strlen(s) + 1;
+ char *tmp = (char *)rt_malloc(len);
+
+ if (!tmp)
+ return RT_NULL;
+
+ rt_memcpy(tmp, s, len);
+
+ return tmp;
+}
+RTM_EXPORT(rt_strdup);
+#endif /* RT_USING_HEAP */
+
+/**
+ * This function will show the version of rt-thread rtos
+ */
+void rt_show_version(void)
+{
+ rt_kprintf("\n \\ | /\n");
+ rt_kprintf("- RT - Thread Operating System\n");
+ rt_kprintf(" / | \\ %d.%d.%d build %s %s\n",
+ RT_VERSION, RT_SUBVERSION, RT_REVISION, __DATE__, __TIME__);
+ rt_kprintf(" 2006 - 2022 Copyright by RT-Thread team\n");
+}
+RTM_EXPORT(rt_show_version);
+
+/* private function */
+#define _ISDIGIT(c) ((unsigned)((c) - '0') < 10)
+
+/**
+ * This function will duplicate a string.
+ *
+ * @param n is the string to be duplicated.
+ *
+ * @param base is support divide instructions value.
+ *
+ * @return the duplicated string pointer.
+ */
+#ifdef RT_KPRINTF_USING_LONGLONG
+rt_inline int divide(long long *n, int base)
+#else
+rt_inline int divide(long *n, int base)
+#endif /* RT_KPRINTF_USING_LONGLONG */
+{
+ int res;
+
+ /* optimized for processor which does not support divide instructions. */
+ if (base == 10)
+ {
+#ifdef RT_KPRINTF_USING_LONGLONG
+ res = (int)(((unsigned long long)*n) % 10U);
+ *n = (long long)(((unsigned long long)*n) / 10U);
+#else
+ res = (int)(((unsigned long)*n) % 10U);
+ *n = (long)(((unsigned long)*n) / 10U);
+#endif
+ }
+ else
+ {
+#ifdef RT_KPRINTF_USING_LONGLONG
+ res = (int)(((unsigned long long)*n) % 16U);
+ *n = (long long)(((unsigned long long)*n) / 16U);
+#else
+ res = (int)(((unsigned long)*n) % 16U);
+ *n = (long)(((unsigned long)*n) / 16U);
+#endif
+ }
+
+ return res;
+}
+
+rt_inline int skip_atoi(const char **s)
+{
+ int i = 0;
+ while (_ISDIGIT(**s))
+ i = i * 10 + *((*s)++) - '0';
+
+ return i;
+}
+
+#define ZEROPAD (1 << 0) /* pad with zero */
+#define SIGN (1 << 1) /* unsigned/signed long */
+#define PLUS (1 << 2) /* show plus */
+#define SPACE (1 << 3) /* space if plus */
+#define LEFT (1 << 4) /* left justified */
+#define SPECIAL (1 << 5) /* 0x */
+#define LARGE (1 << 6) /* use 'ABCDEF' instead of 'abcdef' */
+
+static char *print_number(char *buf,
+ char *end,
+#ifdef RT_KPRINTF_USING_LONGLONG
+ long long num,
+#else
+ long num,
+#endif /* RT_KPRINTF_USING_LONGLONG */
+ int base,
+ int s,
+#ifdef RT_PRINTF_PRECISION
+ int precision,
+#endif /* RT_PRINTF_PRECISION */
+ int type)
+{
+ char c, sign;
+#ifdef RT_KPRINTF_USING_LONGLONG
+ char tmp[32];
+#else
+ char tmp[16];
+#endif /* RT_KPRINTF_USING_LONGLONG */
+ int precision_bak = precision;
+ const char *digits;
+ static const char small_digits[] = "0123456789abcdef";
+ static const char large_digits[] = "0123456789ABCDEF";
+ int i, size;
+
+ size = s;
+
+ digits = (type & LARGE) ? large_digits : small_digits;
+ if (type & LEFT)
+ type &= ~ZEROPAD;
+
+ c = (type & ZEROPAD) ? '0' : ' ';
+
+ /* get sign */
+ sign = 0;
+ if (type & SIGN)
+ {
+ if (num < 0)
+ {
+ sign = '-';
+ num = -num;
+ }
+ else if (type & PLUS)
+ sign = '+';
+ else if (type & SPACE)
+ sign = ' ';
+ }
+
+#ifdef RT_PRINTF_SPECIAL
+ if (type & SPECIAL)
+ {
+ if (base == 16)
+ size -= 2;
+ else if (base == 8)
+ size--;
+ }
+#endif /* RT_PRINTF_SPECIAL */
+
+ i = 0;
+ if (num == 0)
+ tmp[i++] = '0';
+ else
+ {
+ while (num != 0)
+ tmp[i++] = digits[divide(&num, base)];
+ }
+
+#ifdef RT_PRINTF_PRECISION
+ if (i > precision)
+ precision = i;
+ size -= precision;
+#else
+ size -= i;
+#endif /* RT_PRINTF_PRECISION */
+
+ if (!(type & (ZEROPAD | LEFT)))
+ {
+ if ((sign) && (size > 0))
+ size--;
+
+ while (size-- > 0)
+ {
+ if (buf < end)
+ *buf = ' ';
+ ++ buf;
+ }
+ }
+
+ if (sign)
+ {
+ if (buf < end)
+ {
+ *buf = sign;
+ }
+ -- size;
+ ++ buf;
+ }
+
+#ifdef RT_PRINTF_SPECIAL
+ if (type & SPECIAL)
+ {
+ if (base == 8)
+ {
+ if (buf < end)
+ *buf = '0';
+ ++ buf;
+ }
+ else if (base == 16)
+ {
+ if (buf < end)
+ *buf = '0';
+ ++ buf;
+ if (buf < end)
+ {
+ *buf = type & LARGE ? 'X' : 'x';
+ }
+ ++ buf;
+ }
+ }
+#endif /* RT_PRINTF_SPECIAL */
+
+ /* no align to the left */
+ if (!(type & LEFT))
+ {
+ while (size-- > 0)
+ {
+ if (buf < end)
+ *buf = c;
+ ++ buf;
+ }
+ }
+
+#ifdef RT_PRINTF_PRECISION
+ while (i < precision--)
+ {
+ if (buf < end)
+ *buf = '0';
+ ++ buf;
+ }
+#endif /* RT_PRINTF_PRECISION */
+
+ /* put number in the temporary buffer */
+ while (i-- > 0 && (precision_bak != 0))
+ {
+ if (buf < end)
+ *buf = tmp[i];
+ ++ buf;
+ }
+
+ while (size-- > 0)
+ {
+ if (buf < end)
+ *buf = ' ';
+ ++ buf;
+ }
+
+ return buf;
+}
+
+/**
+ * This function will fill a formatted string to buffer.
+ *
+ * @param buf is the buffer to save formatted string.
+ *
+ * @param size is the size of buffer.
+ *
+ * @param fmt is the format parameters.
+ *
+ * @param args is a list of variable parameters.
+ *
+ * @return The number of characters actually written to buffer.
+ */
+RT_WEAK int rt_vsnprintf(char *buf, rt_size_t size, const char *fmt, va_list args)
+{
+#ifdef RT_KPRINTF_USING_LONGLONG
+ unsigned long long num;
+#else
+ rt_uint32_t num;
+#endif /* RT_KPRINTF_USING_LONGLONG */
+ int i, len;
+ char *str, *end, c;
+ const char *s;
+
+ rt_uint8_t base; /* the base of number */
+ rt_uint8_t flags; /* flags to print number */
+ rt_uint8_t qualifier; /* 'h', 'l', or 'L' for integer fields */
+ rt_int32_t field_width; /* width of output field */
+
+#ifdef RT_PRINTF_PRECISION
+ int precision; /* min. # of digits for integers and max for a string */
+#endif /* RT_PRINTF_PRECISION */
+
+ str = buf;
+ end = buf + size;
+
+ /* Make sure end is always >= buf */
+ if (end < buf)
+ {
+ end = ((char *) - 1);
+ size = end - buf;
+ }
+
+ for (; *fmt ; ++fmt)
+ {
+ if (*fmt != '%')
+ {
+ if (str < end)
+ *str = *fmt;
+ ++ str;
+ continue;
+ }
+
+ /* process flags */
+ flags = 0;
+
+ while (1)
+ {
+ /* skips the first '%' also */
+ ++ fmt;
+ if (*fmt == '-') flags |= LEFT;
+ else if (*fmt == '+') flags |= PLUS;
+ else if (*fmt == ' ') flags |= SPACE;
+ else if (*fmt == '#') flags |= SPECIAL;
+ else if (*fmt == '0') flags |= ZEROPAD;
+ else break;
+ }
+
+ /* get field width */
+ field_width = -1;
+ if (_ISDIGIT(*fmt)) field_width = skip_atoi(&fmt);
+ else if (*fmt == '*')
+ {
+ ++ fmt;
+ /* it's the next argument */
+ field_width = va_arg(args, int);
+ if (field_width < 0)
+ {
+ field_width = -field_width;
+ flags |= LEFT;
+ }
+ }
+
+#ifdef RT_PRINTF_PRECISION
+ /* get the precision */
+ precision = -1;
+ if (*fmt == '.')
+ {
+ ++ fmt;
+ if (_ISDIGIT(*fmt)) precision = skip_atoi(&fmt);
+ else if (*fmt == '*')
+ {
+ ++ fmt;
+ /* it's the next argument */
+ precision = va_arg(args, int);
+ }
+ if (precision < 0) precision = 0;
+ }
+#endif /* RT_PRINTF_PRECISION */
+ /* get the conversion qualifier */
+ qualifier = 0;
+#ifdef RT_KPRINTF_USING_LONGLONG
+ if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L')
+#else
+ if (*fmt == 'h' || *fmt == 'l')
+#endif /* RT_KPRINTF_USING_LONGLONG */
+ {
+ qualifier = *fmt;
+ ++ fmt;
+#ifdef RT_KPRINTF_USING_LONGLONG
+ if (qualifier == 'l' && *fmt == 'l')
+ {
+ qualifier = 'L';
+ ++ fmt;
+ }
+#endif /* RT_KPRINTF_USING_LONGLONG */
+ }
+
+ /* the default base */
+ base = 10;
+
+ switch (*fmt)
+ {
+ case 'c':
+ if (!(flags & LEFT))
+ {
+ while (--field_width > 0)
+ {
+ if (str < end) *str = ' ';
+ ++ str;
+ }
+ }
+
+ /* get character */
+ c = (rt_uint8_t)va_arg(args, int);
+ if (str < end) *str = c;
+ ++ str;
+
+ /* put width */
+ while (--field_width > 0)
+ {
+ if (str < end) *str = ' ';
+ ++ str;
+ }
+ continue;
+
+ case 's':
+ s = va_arg(args, char *);
+ if (!s) s = "(NULL)";
+
+ for (len = 0; (len != field_width) && (s[len] != '\0'); len++);
+#ifdef RT_PRINTF_PRECISION
+ if (precision > 0 && len > precision) len = precision;
+#endif /* RT_PRINTF_PRECISION */
+
+ if (!(flags & LEFT))
+ {
+ while (len < field_width--)
+ {
+ if (str < end) *str = ' ';
+ ++ str;
+ }
+ }
+
+ for (i = 0; i < len; ++i)
+ {
+ if (str < end) *str = *s;
+ ++ str;
+ ++ s;
+ }
+
+ while (len < field_width--)
+ {
+ if (str < end) *str = ' ';
+ ++ str;
+ }
+ continue;
+
+ case 'p':
+ if (field_width == -1)
+ {
+ field_width = sizeof(void *) << 1;
+ flags |= ZEROPAD;
+ }
+#ifdef RT_PRINTF_PRECISION
+ str = print_number(str, end,
+ (long)va_arg(args, void *),
+ 16, field_width, precision, flags);
+#else
+ str = print_number(str, end,
+ (long)va_arg(args, void *),
+ 16, field_width, flags);
+#endif /* RT_PRINTF_PRECISION */
+ continue;
+
+ case '%':
+ if (str < end) *str = '%';
+ ++ str;
+ continue;
+
+ /* integer number formats - set up the flags and "break" */
+ case 'o':
+ base = 8;
+ break;
+
+ case 'X':
+ flags |= LARGE;
+ case 'x':
+ base = 16;
+ break;
+
+ case 'd':
+ case 'i':
+ flags |= SIGN;
+ case 'u':
+ break;
+
+ default:
+ if (str < end) *str = '%';
+ ++ str;
+
+ if (*fmt)
+ {
+ if (str < end) *str = *fmt;
+ ++ str;
+ }
+ else
+ {
+ -- fmt;
+ }
+ continue;
+ }
+
+#ifdef RT_KPRINTF_USING_LONGLONG
+ if (qualifier == 'L') num = va_arg(args, long long);
+ else if (qualifier == 'l')
+#else
+ if (qualifier == 'l')
+#endif /* RT_KPRINTF_USING_LONGLONG */
+ {
+ num = va_arg(args, rt_uint32_t);
+ if (flags & SIGN) num = (rt_int32_t)num;
+ }
+ else if (qualifier == 'h')
+ {
+ num = (rt_uint16_t)va_arg(args, rt_int32_t);
+ if (flags & SIGN) num = (rt_int16_t)num;
+ }
+ else
+ {
+ num = va_arg(args, rt_uint32_t);
+ if (flags & SIGN) num = (rt_int32_t)num;
+ }
+#ifdef RT_PRINTF_PRECISION
+ str = print_number(str, end, num, base, field_width, precision, flags);
+#else
+ str = print_number(str, end, num, base, field_width, flags);
+#endif /* RT_PRINTF_PRECISION */
+ }
+
+ if (size > 0)
+ {
+ if (str < end) *str = '\0';
+ else
+ {
+ end[-1] = '\0';
+ }
+ }
+
+ /* the trailing null byte doesn't count towards the total
+ * ++str;
+ */
+ return str - buf;
+}
+RTM_EXPORT(rt_vsnprintf);
+
+/**
+ * This function will fill a formatted string to buffer.
+ *
+ * @param buf is the buffer to save formatted string.
+ *
+ * @param size is the size of buffer.
+ *
+ * @param fmt is the format parameters.
+ *
+ * @return The number of characters actually written to buffer.
+ */
+int rt_snprintf(char *buf, rt_size_t size, const char *fmt, ...)
+{
+ rt_int32_t n;
+ va_list args;
+
+ va_start(args, fmt);
+ n = rt_vsnprintf(buf, size, fmt, args);
+ va_end(args);
+
+ return n;
+}
+RTM_EXPORT(rt_snprintf);
+
+/**
+ * This function will fill a formatted string to buffer.
+ *
+ * @param buf is the buffer to save formatted string.
+ *
+ * @param format is the format parameters.
+ *
+ * @param arg_ptr is a list of variable parameters.
+ *
+ * @return The number of characters actually written to buffer.
+ */
+int rt_vsprintf(char *buf, const char *format, va_list arg_ptr)
+{
+ return rt_vsnprintf(buf, (rt_size_t) - 1, format, arg_ptr);
+}
+RTM_EXPORT(rt_vsprintf);
+
+/**
+ * This function will fill a formatted string to buffer
+ *
+ * @param buf the buffer to save formatted string.
+ *
+ * @param format is the format parameters.
+ *
+ * @return The number of characters actually written to buffer.
+ */
+int rt_sprintf(char *buf, const char *format, ...)
+{
+ rt_int32_t n;
+ va_list arg_ptr;
+
+ va_start(arg_ptr, format);
+ n = rt_vsprintf(buf, format, arg_ptr);
+ va_end(arg_ptr);
+
+ return n;
+}
+RTM_EXPORT(rt_sprintf);
+
+#ifdef RT_USING_CONSOLE
+
+#ifdef RT_USING_DEVICE
+/**
+ * This function returns the device using in console.
+ *
+ * @return Returns the console device pointer or RT_NULL.
+ */
+rt_device_t rt_console_get_device(void)
+{
+ return _console_device;
+}
+RTM_EXPORT(rt_console_get_device);
+
+/**
+ * This function will set a device as console device.
+ * After set a device to console, all output of rt_kprintf will be
+ * redirected to this new device.
+ *
+ * @param name is the name of new console device.
+ *
+ * @return the old console device handler on successful, or RT_NULL on failure.
+ */
+rt_device_t rt_console_set_device(const char *name)
+{
+ rt_device_t new_device, old_device;
+
+ /* save old device */
+ old_device = _console_device;
+
+ /* find new console device */
+ new_device = rt_device_find(name);
+
+ /* check whether it's a same device */
+ if (new_device == old_device) return RT_NULL;
+
+ if (new_device != RT_NULL)
+ {
+ if (_console_device != RT_NULL)
+ {
+ /* close old console device */
+ rt_device_close(_console_device);
+ }
+
+ /* set new console device */
+ rt_device_open(new_device, RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_STREAM);
+ _console_device = new_device;
+ }
+
+ return old_device;
+}
+RTM_EXPORT(rt_console_set_device);
+#endif /* RT_USING_DEVICE */
+
+RT_WEAK void rt_hw_console_output(const char *str)
+{
+ /* empty console output */
+}
+RTM_EXPORT(rt_hw_console_output);
+
+/**
+ * This function will put string to the console.
+ *
+ * @param str is the string output to the console.
+ */
+void rt_kputs(const char *str)
+{
+ if (!str) return;
+
+#ifdef RT_USING_DEVICE
+ if (_console_device == RT_NULL)
+ {
+ rt_hw_console_output(str);
+ }
+ else
+ {
+ rt_device_write(_console_device, 0, str, rt_strlen(str));
+ }
+#else
+ rt_hw_console_output(str);
+#endif /* RT_USING_DEVICE */
+}
+
+/**
+ * This function will print a formatted string on system console.
+ *
+ * @param fmt is the format parameters.
+ *
+ * @return The number of characters actually written to buffer.
+ */
+RT_WEAK int rt_kprintf(const char *fmt, ...)
+{
+ va_list args;
+ rt_size_t length;
+ static char rt_log_buf[RT_CONSOLEBUF_SIZE];
+
+ va_start(args, fmt);
+ /* the return value of vsnprintf is the number of bytes that would be
+ * written to buffer had if the size of the buffer been sufficiently
+ * large excluding the terminating null byte. If the output string
+ * would be larger than the rt_log_buf, we have to adjust the output
+ * length. */
+ length = rt_vsnprintf(rt_log_buf, sizeof(rt_log_buf) - 1, fmt, args);
+ if (length > RT_CONSOLEBUF_SIZE - 1)
+ length = RT_CONSOLEBUF_SIZE - 1;
+#ifdef RT_USING_DEVICE
+ if (_console_device == RT_NULL)
+ {
+ rt_hw_console_output(rt_log_buf);
+ }
+ else
+ {
+ rt_device_write(_console_device, 0, rt_log_buf, length);
+ }
+#else
+ rt_hw_console_output(rt_log_buf);
+#endif /* RT_USING_DEVICE */
+ va_end(args);
+
+ return length;
+}
+RTM_EXPORT(rt_kprintf);
+#endif /* RT_USING_CONSOLE */
+
+#if defined(RT_USING_HEAP) && !defined(RT_USING_USERHEAP)
+#ifdef RT_USING_HOOK
+static void (*rt_malloc_hook)(void *ptr, rt_size_t size);
+static void (*rt_free_hook)(void *ptr);
+
+/**
+ * @addtogroup Hook
+ */
+
+/**@{*/
+
+/**
+ * @brief This function will set a hook function, which will be invoked when a memory
+ * block is allocated from heap memory.
+ *
+ * @param hook the hook function.
+ */
+void rt_malloc_sethook(void (*hook)(void *ptr, rt_size_t size))
+{
+ rt_malloc_hook = hook;
+}
+
+/**
+ * @brief This function will set a hook function, which will be invoked when a memory
+ * block is released to heap memory.
+ *
+ * @param hook the hook function
+ */
+void rt_free_sethook(void (*hook)(void *ptr))
+{
+ rt_free_hook = hook;
+}
+
+/**@}*/
+
+#endif /* RT_USING_HOOK */
+
+#if defined(RT_USING_HEAP_ISR)
+#elif defined(RT_USING_MUTEX)
+static struct rt_mutex _lock;
+#endif
+
+rt_inline void _heap_lock_init(void)
+{
+#if defined(RT_USING_HEAP_ISR)
+#elif defined(RT_USING_MUTEX)
+ rt_mutex_init(&_lock, "heap", RT_IPC_FLAG_PRIO);
+#endif
+}
+
+rt_inline rt_base_t _heap_lock(void)
+{
+#if defined(RT_USING_HEAP_ISR)
+ return rt_hw_interrupt_disable();
+#elif defined(RT_USING_MUTEX)
+ if (rt_thread_self())
+ return rt_mutex_take(&_lock, RT_WAITING_FOREVER);
+ else
+ return RT_EOK;
+#else
+ rt_enter_critical();
+ return RT_EOK;
+#endif
+}
+
+rt_inline void _heap_unlock(rt_base_t level)
+{
+#if defined(RT_USING_HEAP_ISR)
+ rt_hw_interrupt_enable(level);
+#elif defined(RT_USING_MUTEX)
+ RT_ASSERT(level == RT_EOK);
+ if (rt_thread_self())
+ rt_mutex_release(&_lock);
+#else
+ rt_exit_critical();
+#endif
+}
+
+#if defined(RT_USING_SMALL_MEM_AS_HEAP)
+static rt_smem_t system_heap;
+rt_inline void _smem_info(rt_size_t *total,
+ rt_size_t *used, rt_size_t *max_used)
+{
+ if (total)
+ *total = system_heap->total;
+ if (used)
+ *used = system_heap->used;
+ if (max_used)
+ *max_used = system_heap->max;
+}
+#define _MEM_INIT(_name, _start, _size) \
+ system_heap = rt_smem_init(_name, _start, _size)
+#define _MEM_MALLOC(_size) \
+ rt_smem_alloc(system_heap, _size)
+#define _MEM_REALLOC(_ptr, _newsize)\
+ rt_smem_realloc(system_heap, _ptr, _newsize)
+#define _MEM_FREE(_ptr) \
+ rt_smem_free(_ptr)
+#define _MEM_INFO(_total, _used, _max) \
+ _smem_info(_total, _used, _max)
+#elif defined(RT_USING_MEMHEAP_AS_HEAP)
+static struct rt_memheap system_heap;
+void *_memheap_alloc(struct rt_memheap *heap, rt_size_t size);
+void _memheap_free(void *rmem);
+void *_memheap_realloc(struct rt_memheap *heap, void *rmem, rt_size_t newsize);
+#define _MEM_INIT(_name, _start, _size) \
+ rt_memheap_init(&system_heap, _name, _start, _size)
+#define _MEM_MALLOC(_size) \
+ _memheap_alloc(&system_heap, _size)
+#define _MEM_REALLOC(_ptr, _newsize) \
+ _memheap_realloc(&system_heap, _ptr, _newsize)
+#define _MEM_FREE(_ptr) \
+ _memheap_free(_ptr)
+#define _MEM_INFO(_total, _used, _max) \
+ rt_memheap_info(&system_heap, _total, _used, _max)
+#elif defined(RT_USING_SLAB_AS_HEAP)
+static rt_slab_t system_heap;
+rt_inline void _slab_info(rt_size_t *total,
+ rt_size_t *used, rt_size_t *max_used)
+{
+ if (total)
+ *total = system_heap->total;
+ if (used)
+ *used = system_heap->used;
+ if (max_used)
+ *max_used = system_heap->max;
+}
+#define _MEM_INIT(_name, _start, _size) \
+ system_heap = rt_slab_init(_name, _start, _size)
+#define _MEM_MALLOC(_size) \
+ rt_slab_alloc(system_heap, _size)
+#define _MEM_REALLOC(_ptr, _newsize) \
+ rt_slab_realloc(system_heap, _ptr, _newsize)
+#define _MEM_FREE(_ptr) \
+ rt_slab_free(system_heap, _ptr)
+#define _MEM_INFO _slab_info
+#else
+#define _MEM_INIT(...)
+#define _MEM_MALLOC(...) RT_NULL
+#define _MEM_REALLOC(...) RT_NULL
+#define _MEM_FREE(...)
+#define _MEM_INFO(...)
+#endif
+
+/**
+ * @brief This function will init system heap.
+ *
+ * @param begin_addr the beginning address of system page.
+ *
+ * @param end_addr the end address of system page.
+ */
+RT_WEAK void rt_system_heap_init(void *begin_addr, void *end_addr)
+{
+ rt_ubase_t begin_align = RT_ALIGN((rt_ubase_t)begin_addr, RT_ALIGN_SIZE);
+ rt_ubase_t end_align = RT_ALIGN_DOWN((rt_ubase_t)end_addr, RT_ALIGN_SIZE);
+
+ RT_ASSERT(end_align > begin_align);
+
+ /* Initialize system memory heap */
+ _MEM_INIT("heap", begin_addr, end_align - begin_align);
+ /* Initialize multi thread contention lock */
+ _heap_lock_init();
+}
+
+/**
+ * @brief Allocate a block of memory with a minimum of 'size' bytes.
+ *
+ * @param size is the minimum size of the requested block in bytes.
+ *
+ * @return the pointer to allocated memory or NULL if no free memory was found.
+ */
+RT_WEAK void *rt_malloc(rt_size_t size)
+{
+ rt_base_t level;
+ void *ptr;
+
+ /* Enter critical zone */
+ level = _heap_lock();
+ /* allocate memory block from system heap */
+ ptr = _MEM_MALLOC(size);
+ /* Exit critical zone */
+ _heap_unlock(level);
+ /* call 'rt_malloc' hook */
+ RT_OBJECT_HOOK_CALL(rt_malloc_hook, (ptr, size));
+ return ptr;
+}
+RTM_EXPORT(rt_malloc);
+
+/**
+ * @brief This function will change the size of previously allocated memory block.
+ *
+ * @param rmem is the pointer to memory allocated by rt_malloc.
+ *
+ * @param newsize is the required new size.
+ *
+ * @return the changed memory block address.
+ */
+RT_WEAK void *rt_realloc(void *rmem, rt_size_t newsize)
+{
+ rt_base_t level;
+ void *nptr;
+
+ /* Enter critical zone */
+ level = _heap_lock();
+ /* Change the size of previously allocated memory block */
+ nptr = _MEM_REALLOC(rmem, newsize);
+ /* Exit critical zone */
+ _heap_unlock(level);
+ return nptr;
+}
+RTM_EXPORT(rt_realloc);
+
+/**
+ * @brief This function will contiguously allocate enough space for count objects
+ * that are size bytes of memory each and returns a pointer to the allocated
+ * memory.
+ *
+ * @note The allocated memory is filled with bytes of value zero.
+ *
+ * @param count is the number of objects to allocate.
+ *
+ * @param size is the size of one object to allocate.
+ *
+ * @return pointer to allocated memory / NULL pointer if there is an error.
+ */
+RT_WEAK void *rt_calloc(rt_size_t count, rt_size_t size)
+{
+ void *p;
+
+ /* allocate 'count' objects of size 'size' */
+ p = rt_malloc(count * size);
+ /* zero the memory */
+ if (p)
+ {
+ rt_memset(p, 0, count * size);
+ }
+ return p;
+}
+RTM_EXPORT(rt_calloc);
+
+/**
+ * @brief This function will release the previously allocated memory block by
+ * rt_malloc. The released memory block is taken back to system heap.
+ *
+ * @param rmem the address of memory which will be released.
+ */
+RT_WEAK void rt_free(void *rmem)
+{
+ rt_base_t level;
+
+ /* call 'rt_free' hook */
+ RT_OBJECT_HOOK_CALL(rt_free_hook, (rmem));
+ /* NULL check */
+ if (rmem == RT_NULL) return;
+ /* Enter critical zone */
+ level = _heap_lock();
+ _MEM_FREE(rmem);
+ /* Exit critical zone */
+ _heap_unlock(level);
+}
+RTM_EXPORT(rt_free);
+
+/**
+* @brief This function will caculate the total memory, the used memory, and
+* the max used memory.
+*
+* @param total is a pointer to get the total size of the memory.
+*
+* @param used is a pointer to get the size of memory used.
+*
+* @param max_used is a pointer to get the maximum memory used.
+*/
+RT_WEAK void rt_memory_info(rt_size_t *total,
+ rt_size_t *used,
+ rt_size_t *max_used)
+{
+ rt_base_t level;
+
+ /* Enter critical zone */
+ level = _heap_lock();
+ _MEM_INFO(total, used, max_used);
+ /* Exit critical zone */
+ _heap_unlock(level);
+}
+RTM_EXPORT(rt_memory_info);
+
+#if defined(RT_USING_SLAB) && defined(RT_USING_SLAB_AS_HEAP)
+void *rt_page_alloc(rt_size_t npages)
+{
+ rt_base_t level;
+ void *ptr;
+
+ /* Enter critical zone */
+ level = _heap_lock();
+ /* alloc page */
+ ptr = rt_slab_page_alloc(system_heap, npages);
+ /* Exit critical zone */
+ _heap_unlock(level);
+ return ptr;
+}
+
+void rt_page_free(void *addr, rt_size_t npages)
+{
+ rt_base_t level;
+
+ /* Enter critical zone */
+ level = _heap_lock();
+ /* free page */
+ rt_slab_page_free(system_heap, addr, npages);
+ /* Exit critical zone */
+ _heap_unlock(level);
+}
+#endif
+
+/**
+ * This function allocates a memory block, which address is aligned to the
+ * specified alignment size.
+ *
+ * @param size is the allocated memory block size.
+ *
+ * @param align is the alignment size.
+ *
+ * @return The memory block address was returned successfully, otherwise it was
+ * returned empty RT_NULL.
+ */
+RT_WEAK void *rt_malloc_align(rt_size_t size, rt_size_t align)
+{
+ void *ptr;
+ void *align_ptr;
+ int uintptr_size;
+ rt_size_t align_size;
+
+ /* sizeof pointer */
+ uintptr_size = sizeof(void*);
+ uintptr_size -= 1;
+
+ /* align the alignment size to uintptr size byte */
+ align = ((align + uintptr_size) & ~uintptr_size);
+
+ /* get total aligned size */
+ align_size = ((size + uintptr_size) & ~uintptr_size) + align;
+ /* allocate memory block from heap */
+ ptr = rt_malloc(align_size);
+ if (ptr != RT_NULL)
+ {
+ /* the allocated memory block is aligned */
+ if (((rt_ubase_t)ptr & (align - 1)) == 0)
+ {
+ align_ptr = (void *)((rt_ubase_t)ptr + align);
+ }
+ else
+ {
+ align_ptr = (void *)(((rt_ubase_t)ptr + (align - 1)) & ~(align - 1));
+ }
+
+ /* set the pointer before alignment pointer to the real pointer */
+ *((rt_ubase_t *)((rt_ubase_t)align_ptr - sizeof(void *))) = (rt_ubase_t)ptr;
+
+ ptr = align_ptr;
+ }
+
+ return ptr;
+}
+RTM_EXPORT(rt_malloc_align);
+
+/**
+ * This function release the memory block, which is allocated by
+ * rt_malloc_align function and address is aligned.
+ *
+ * @param ptr is the memory block pointer.
+ */
+RT_WEAK void rt_free_align(void *ptr)
+{
+ void *real_ptr;
+
+ /* NULL check */
+ if (ptr == RT_NULL) return;
+ real_ptr = (void *) * (rt_ubase_t *)((rt_ubase_t)ptr - sizeof(void *));
+ rt_free(real_ptr);
+}
+RTM_EXPORT(rt_free_align);
+#endif /* RT_USING_HEAP */
+
+#ifndef RT_USING_CPU_FFS
+#ifdef RT_USING_TINY_FFS
+const rt_uint8_t __lowest_bit_bitmap[] =
+{
+ /* 0 - 7 */ 0, 1, 2, 27, 3, 24, 28, 32,
+ /* 8 - 15 */ 4, 17, 25, 31, 29, 12, 32, 14,
+ /* 16 - 23 */ 5, 8, 18, 32, 26, 23, 32, 16,
+ /* 24 - 31 */ 30, 11, 13, 7, 32, 22, 15, 10,
+ /* 32 - 36 */ 6, 21, 9, 20, 19
+};
+
+/**
+ * This function finds the first bit set (beginning with the least significant bit)
+ * in value and return the index of that bit.
+ *
+ * Bits are numbered starting at 1 (the least significant bit). A return value of
+ * zero from any of these functions means that the argument was zero.
+ *
+ * @return return the index of the first bit set. If value is 0, then this function
+ * shall return 0.
+ */
+int __rt_ffs(int value)
+{
+ return __lowest_bit_bitmap[(rt_uint32_t)(value & (value - 1) ^ value) % 37];
+}
+#else
+const rt_uint8_t __lowest_bit_bitmap[] =
+{
+ /* 00 */ 0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
+ /* 10 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
+ /* 20 */ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
+ /* 30 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
+ /* 40 */ 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
+ /* 50 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
+ /* 60 */ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
+ /* 70 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
+ /* 80 */ 7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
+ /* 90 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
+ /* A0 */ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
+ /* B0 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
+ /* C0 */ 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
+ /* D0 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
+ /* E0 */ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
+ /* F0 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
+};
+
+/**
+ * This function finds the first bit set (beginning with the least significant bit)
+ * in value and return the index of that bit.
+ *
+ * Bits are numbered starting at 1 (the least significant bit). A return value of
+ * zero from any of these functions means that the argument was zero.
+ *
+ * @return Return the index of the first bit set. If value is 0, then this function
+ * shall return 0.
+ */
+int __rt_ffs(int value)
+{
+ if (value == 0) return 0;
+
+ if (value & 0xff)
+ return __lowest_bit_bitmap[value & 0xff] + 1;
+
+ if (value & 0xff00)
+ return __lowest_bit_bitmap[(value & 0xff00) >> 8] + 9;
+
+ if (value & 0xff0000)
+ return __lowest_bit_bitmap[(value & 0xff0000) >> 16] + 17;
+
+ return __lowest_bit_bitmap[(value & 0xff000000) >> 24] + 25;
+}
+#endif /* RT_USING_TINY_FFS */
+#endif /* RT_USING_CPU_FFS */
+
+#ifndef __on_rt_assert_hook
+ #define __on_rt_assert_hook(ex, func, line) __ON_HOOK_ARGS(rt_assert_hook, (ex, func, line))
+#endif
+
+#ifdef RT_DEBUG
+/* RT_ASSERT(EX)'s hook */
+
+void (*rt_assert_hook)(const char *ex, const char *func, rt_size_t line);
+
+/**
+ * This function will set a hook function to RT_ASSERT(EX). It will run when the expression is false.
+ *
+ * @param hook is the hook function.
+ */
+void rt_assert_set_hook(void (*hook)(const char *ex, const char *func, rt_size_t line))
+{
+ rt_assert_hook = hook;
+}
+
+/**
+ * The RT_ASSERT function.
+ *
+ * @param ex_string is the assertion condition string.
+ *
+ * @param func is the function name when assertion.
+ *
+ * @param line is the file line number when assertion.
+ */
+void rt_assert_handler(const char *ex_string, const char *func, rt_size_t line)
+{
+ volatile char dummy = 0;
+
+ if (rt_assert_hook == RT_NULL)
+ {
+#ifdef RT_USING_MODULE
+ if (dlmodule_self())
+ {
+ /* close assertion module */
+ dlmodule_exit(-1);
+ }
+ else
+#endif /*RT_USING_MODULE*/
+ {
+ rt_kprintf("(%s) assertion failed at function:%s, line number:%d \n", ex_string, func, line);
+ while (dummy == 0);
+ }
+ }
+ else
+ {
+ rt_assert_hook(ex_string, func, line);
+ }
+}
+RTM_EXPORT(rt_assert_handler);
+#endif /* RT_DEBUG */
+
+/**@}*/
diff --git a/User/system/rt-thread/src/mem.c b/User/system/rt-thread/src/mem.c
new file mode 100644
index 0000000..14593bc
--- /dev/null
+++ b/User/system/rt-thread/src/mem.c
@@ -0,0 +1,675 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2008-7-12 Bernard the first version
+ * 2010-06-09 Bernard fix the end stub of heap
+ * fix memory check in rt_realloc function
+ * 2010-07-13 Bernard fix RT_ALIGN issue found by kuronca
+ * 2010-10-14 Bernard fix rt_realloc issue when realloc a NULL pointer.
+ * 2017-07-14 armink fix rt_realloc issue when new size is 0
+ * 2018-10-02 Bernard Add 64bit support
+ */
+
+/*
+ * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * This file is part of the lwIP TCP/IP stack.
+ *
+ * Author: Adam Dunkels
+ * Simon Goldschmidt
+ *
+ */
+
+#include
+#include
+
+#if defined (RT_USING_SMALL_MEM)
+ /**
+ * memory item on the small mem
+ */
+struct rt_small_mem_item
+{
+ rt_ubase_t pool_ptr; /**< small memory object addr */
+#ifdef ARCH_CPU_64BIT
+ rt_uint32_t resv;
+#endif /* ARCH_CPU_64BIT */
+ rt_size_t next; /**< next free item */
+ rt_size_t prev; /**< prev free item */
+#ifdef RT_USING_MEMTRACE
+#ifdef ARCH_CPU_64BIT
+ rt_uint8_t thread[8]; /**< thread name */
+#else
+ rt_uint8_t thread[4]; /**< thread name */
+#endif /* ARCH_CPU_64BIT */
+#endif /* RT_USING_MEMTRACE */
+};
+
+/**
+ * Base structure of small memory object
+ */
+struct rt_small_mem
+{
+ struct rt_memory parent; /**< inherit from rt_memory */
+ rt_uint8_t *heap_ptr; /**< pointer to the heap */
+ struct rt_small_mem_item *heap_end;
+ struct rt_small_mem_item *lfree;
+ rt_size_t mem_size_aligned; /**< aligned memory size */
+};
+
+#define HEAP_MAGIC 0x1ea0
+
+#ifdef ARCH_CPU_64BIT
+#define MIN_SIZE 24
+#else
+#define MIN_SIZE 12
+#endif /* ARCH_CPU_64BIT */
+
+#define MEM_MASK 0xfffffffe
+#define MEM_USED() ((((rt_base_t)(small_mem)) & MEM_MASK) | 0x1)
+#define MEM_FREED() ((((rt_base_t)(small_mem)) & MEM_MASK) | 0x0)
+#define MEM_ISUSED(_mem) \
+ (((rt_base_t)(((struct rt_small_mem_item *)(_mem))->pool_ptr)) & (~MEM_MASK))
+#define MEM_POOL(_mem) \
+ ((struct rt_small_mem *)(((rt_base_t)(((struct rt_small_mem_item *)(_mem))->pool_ptr)) & (MEM_MASK)))
+#define MEM_SIZE(_heap, _mem) \
+ (((struct rt_small_mem_item *)(_mem))->next - ((rt_ubase_t)(_mem) - \
+ (rt_ubase_t)((_heap)->heap_ptr)) - RT_ALIGN(sizeof(struct rt_small_mem_item), RT_ALIGN_SIZE))
+
+#define MIN_SIZE_ALIGNED RT_ALIGN(MIN_SIZE, RT_ALIGN_SIZE)
+#define SIZEOF_STRUCT_MEM RT_ALIGN(sizeof(struct rt_small_mem_item), RT_ALIGN_SIZE)
+
+#ifdef RT_USING_MEMTRACE
+rt_inline void rt_smem_setname(struct rt_small_mem_item *mem, const char *name)
+{
+ int index;
+ for (index = 0; index < sizeof(mem->thread); index ++)
+ {
+ if (name[index] == '\0') break;
+ mem->thread[index] = name[index];
+ }
+
+ for (; index < sizeof(mem->thread); index ++)
+ {
+ mem->thread[index] = ' ';
+ }
+}
+#endif /* RT_USING_MEMTRACE */
+
+static void plug_holes(struct rt_small_mem *m, struct rt_small_mem_item *mem)
+{
+ struct rt_small_mem_item *nmem;
+ struct rt_small_mem_item *pmem;
+
+ RT_ASSERT((rt_uint8_t *)mem >= m->heap_ptr);
+ RT_ASSERT((rt_uint8_t *)mem < (rt_uint8_t *)m->heap_end);
+
+ /* plug hole forward */
+ nmem = (struct rt_small_mem_item *)&m->heap_ptr[mem->next];
+ if (mem != nmem && !MEM_ISUSED(nmem) &&
+ (rt_uint8_t *)nmem != (rt_uint8_t *)m->heap_end)
+ {
+ /* if mem->next is unused and not end of m->heap_ptr,
+ * combine mem and mem->next
+ */
+ if (m->lfree == nmem)
+ {
+ m->lfree = mem;
+ }
+ nmem->pool_ptr = 0;
+ mem->next = nmem->next;
+ ((struct rt_small_mem_item *)&m->heap_ptr[nmem->next])->prev = (rt_uint8_t *)mem - m->heap_ptr;
+ }
+
+ /* plug hole backward */
+ pmem = (struct rt_small_mem_item *)&m->heap_ptr[mem->prev];
+ if (pmem != mem && !MEM_ISUSED(pmem))
+ {
+ /* if mem->prev is unused, combine mem and mem->prev */
+ if (m->lfree == mem)
+ {
+ m->lfree = pmem;
+ }
+ mem->pool_ptr = 0;
+ pmem->next = mem->next;
+ ((struct rt_small_mem_item *)&m->heap_ptr[mem->next])->prev = (rt_uint8_t *)pmem - m->heap_ptr;
+ }
+}
+
+/**
+ * @brief This function will initialize small memory management algorithm.
+ *
+ * @param m the small memory management object.
+ *
+ * @param name is the name of the small memory management object.
+ *
+ * @param begin_addr the beginning address of memory.
+ *
+ * @param size is the size of the memory.
+ *
+ * @return Return a pointer to the memory object. When the return value is RT_NULL, it means the init failed.
+ */
+rt_smem_t rt_smem_init(const char *name,
+ void *begin_addr,
+ rt_size_t size)
+{
+ struct rt_small_mem_item *mem;
+ struct rt_small_mem *small_mem;
+ rt_ubase_t start_addr, begin_align, end_align, mem_size;
+
+ small_mem = (struct rt_small_mem *)RT_ALIGN((rt_ubase_t)begin_addr, RT_ALIGN_SIZE);
+ start_addr = (rt_ubase_t)small_mem + sizeof(*small_mem);
+ begin_align = RT_ALIGN((rt_ubase_t)start_addr, RT_ALIGN_SIZE);
+ end_align = RT_ALIGN_DOWN((rt_ubase_t)begin_addr + size, RT_ALIGN_SIZE);
+
+ /* alignment addr */
+ if ((end_align > (2 * SIZEOF_STRUCT_MEM)) &&
+ ((end_align - 2 * SIZEOF_STRUCT_MEM) >= start_addr))
+ {
+ /* calculate the aligned memory size */
+ mem_size = end_align - begin_align - 2 * SIZEOF_STRUCT_MEM;
+ }
+ else
+ {
+ rt_kprintf("mem init, error begin address 0x%x, and end address 0x%x\n",
+ (rt_ubase_t)begin_addr, (rt_ubase_t)begin_addr + size);
+
+ return RT_NULL;
+ }
+
+ rt_memset(small_mem, 0, sizeof(*small_mem));
+ /* initialize small memory object */
+ rt_object_init(&(small_mem->parent.parent), RT_Object_Class_Memory, name);
+ small_mem->parent.algorithm = "small";
+ small_mem->parent.address = begin_align;
+ small_mem->parent.total = mem_size;
+ small_mem->mem_size_aligned = mem_size;
+
+ /* point to begin address of heap */
+ small_mem->heap_ptr = (rt_uint8_t *)begin_align;
+
+ RT_DEBUG_LOG(RT_DEBUG_MEM, ("mem init, heap begin address 0x%x, size %d\n",
+ (rt_ubase_t)small_mem->heap_ptr, small_mem->mem_size_aligned));
+
+ /* initialize the start of the heap */
+ mem = (struct rt_small_mem_item *)small_mem->heap_ptr;
+ mem->pool_ptr = MEM_FREED();
+ mem->next = small_mem->mem_size_aligned + SIZEOF_STRUCT_MEM;
+ mem->prev = 0;
+#ifdef RT_USING_MEMTRACE
+ rt_smem_setname(mem, "INIT");
+#endif /* RT_USING_MEMTRACE */
+
+ /* initialize the end of the heap */
+ small_mem->heap_end = (struct rt_small_mem_item *)&small_mem->heap_ptr[mem->next];
+ small_mem->heap_end->pool_ptr = MEM_USED();
+ small_mem->heap_end->next = small_mem->mem_size_aligned + SIZEOF_STRUCT_MEM;
+ small_mem->heap_end->prev = small_mem->mem_size_aligned + SIZEOF_STRUCT_MEM;
+#ifdef RT_USING_MEMTRACE
+ rt_smem_setname(small_mem->heap_end, "INIT");
+#endif /* RT_USING_MEMTRACE */
+
+ /* initialize the lowest-free pointer to the start of the heap */
+ small_mem->lfree = (struct rt_small_mem_item *)small_mem->heap_ptr;
+
+ return &small_mem->parent;
+}
+RTM_EXPORT(rt_smem_init);
+
+/**
+ * @brief This function will remove a small mem from the system.
+ *
+ * @param m the small memory management object.
+ *
+ * @return RT_EOK
+ */
+rt_err_t rt_smem_detach(rt_smem_t m)
+{
+ RT_ASSERT(m != RT_NULL);
+ RT_ASSERT(rt_object_get_type(&m->parent) == RT_Object_Class_Memory);
+ RT_ASSERT(rt_object_is_systemobject(&m->parent));
+
+ rt_object_detach(&(m->parent));
+
+ return RT_EOK;
+}
+RTM_EXPORT(rt_smem_detach);
+
+/**
+ * @addtogroup MM
+ */
+
+/**@{*/
+
+/**
+ * @brief Allocate a block of memory with a minimum of 'size' bytes.
+ *
+ * @param m the small memory management object.
+ *
+ * @param size is the minimum size of the requested block in bytes.
+ *
+ * @return the pointer to allocated memory or NULL if no free memory was found.
+ */
+void *rt_smem_alloc(rt_smem_t m, rt_size_t size)
+{
+ rt_size_t ptr, ptr2;
+ struct rt_small_mem_item *mem, *mem2;
+ struct rt_small_mem *small_mem;
+
+ if (size == 0)
+ return RT_NULL;
+
+ RT_ASSERT(m != RT_NULL);
+ RT_ASSERT(rt_object_get_type(&m->parent) == RT_Object_Class_Memory);
+ RT_ASSERT(rt_object_is_systemobject(&m->parent));
+
+ if (size != RT_ALIGN(size, RT_ALIGN_SIZE))
+ {
+ RT_DEBUG_LOG(RT_DEBUG_MEM, ("malloc size %d, but align to %d\n",
+ size, RT_ALIGN(size, RT_ALIGN_SIZE)));
+ }
+ else
+ {
+ RT_DEBUG_LOG(RT_DEBUG_MEM, ("malloc size %d\n", size));
+ }
+
+ small_mem = (struct rt_small_mem *)m;
+ /* alignment size */
+ size = RT_ALIGN(size, RT_ALIGN_SIZE);
+
+ /* every data block must be at least MIN_SIZE_ALIGNED long */
+ if (size < MIN_SIZE_ALIGNED)
+ size = MIN_SIZE_ALIGNED;
+
+ if (size > small_mem->mem_size_aligned)
+ {
+ RT_DEBUG_LOG(RT_DEBUG_MEM, ("no memory\n"));
+
+ return RT_NULL;
+ }
+
+ for (ptr = (rt_uint8_t *)small_mem->lfree - small_mem->heap_ptr;
+ ptr <= small_mem->mem_size_aligned - size;
+ ptr = ((struct rt_small_mem_item *)&small_mem->heap_ptr[ptr])->next)
+ {
+ mem = (struct rt_small_mem_item *)&small_mem->heap_ptr[ptr];
+
+ if ((!MEM_ISUSED(mem)) && (mem->next - (ptr + SIZEOF_STRUCT_MEM)) >= size)
+ {
+ /* mem is not used and at least perfect fit is possible:
+ * mem->next - (ptr + SIZEOF_STRUCT_MEM) gives us the 'user data size' of mem */
+
+ if (mem->next - (ptr + SIZEOF_STRUCT_MEM) >=
+ (size + SIZEOF_STRUCT_MEM + MIN_SIZE_ALIGNED))
+ {
+ /* (in addition to the above, we test if another struct rt_small_mem_item (SIZEOF_STRUCT_MEM) containing
+ * at least MIN_SIZE_ALIGNED of data also fits in the 'user data space' of 'mem')
+ * -> split large block, create empty remainder,
+ * remainder must be large enough to contain MIN_SIZE_ALIGNED data: if
+ * mem->next - (ptr + (2*SIZEOF_STRUCT_MEM)) == size,
+ * struct rt_small_mem_item would fit in but no data between mem2 and mem2->next
+ * @todo we could leave out MIN_SIZE_ALIGNED. We would create an empty
+ * region that couldn't hold data, but when mem->next gets freed,
+ * the 2 regions would be combined, resulting in more free memory
+ */
+ ptr2 = ptr + SIZEOF_STRUCT_MEM + size;
+
+ /* create mem2 struct */
+ mem2 = (struct rt_small_mem_item *)&small_mem->heap_ptr[ptr2];
+ mem2->pool_ptr = MEM_FREED();
+ mem2->next = mem->next;
+ mem2->prev = ptr;
+#ifdef RT_USING_MEMTRACE
+ rt_smem_setname(mem2, " ");
+#endif /* RT_USING_MEMTRACE */
+
+ /* and insert it between mem and mem->next */
+ mem->next = ptr2;
+
+ if (mem2->next != small_mem->mem_size_aligned + SIZEOF_STRUCT_MEM)
+ {
+ ((struct rt_small_mem_item *)&small_mem->heap_ptr[mem2->next])->prev = ptr2;
+ }
+ small_mem->parent.used += (size + SIZEOF_STRUCT_MEM);
+ if (small_mem->parent.max < small_mem->parent.used)
+ small_mem->parent.max = small_mem->parent.used;
+ }
+ else
+ {
+ /* (a mem2 struct does no fit into the user data space of mem and mem->next will always
+ * be used at this point: if not we have 2 unused structs in a row, plug_holes should have
+ * take care of this).
+ * -> near fit or excact fit: do not split, no mem2 creation
+ * also can't move mem->next directly behind mem, since mem->next
+ * will always be used at this point!
+ */
+ small_mem->parent.used += mem->next - ((rt_uint8_t *)mem - small_mem->heap_ptr);
+ if (small_mem->parent.max < small_mem->parent.used)
+ small_mem->parent.max = small_mem->parent.used;
+ }
+ /* set small memory object */
+ mem->pool_ptr = MEM_USED();
+#ifdef RT_USING_MEMTRACE
+ if (rt_thread_self())
+ rt_smem_setname(mem, rt_thread_self()->name);
+ else
+ rt_smem_setname(mem, "NONE");
+#endif /* RT_USING_MEMTRACE */
+
+ if (mem == small_mem->lfree)
+ {
+ /* Find next free block after mem and update lowest free pointer */
+ while (MEM_ISUSED(small_mem->lfree) && small_mem->lfree != small_mem->heap_end)
+ small_mem->lfree = (struct rt_small_mem_item *)&small_mem->heap_ptr[small_mem->lfree->next];
+
+ RT_ASSERT(((small_mem->lfree == small_mem->heap_end) || (!MEM_ISUSED(small_mem->lfree))));
+ }
+ RT_ASSERT((rt_ubase_t)mem + SIZEOF_STRUCT_MEM + size <= (rt_ubase_t)small_mem->heap_end);
+ RT_ASSERT((rt_ubase_t)((rt_uint8_t *)mem + SIZEOF_STRUCT_MEM) % RT_ALIGN_SIZE == 0);
+ RT_ASSERT((((rt_ubase_t)mem) & (RT_ALIGN_SIZE - 1)) == 0);
+
+ RT_DEBUG_LOG(RT_DEBUG_MEM,
+ ("allocate memory at 0x%x, size: %d\n",
+ (rt_ubase_t)((rt_uint8_t *)mem + SIZEOF_STRUCT_MEM),
+ (rt_ubase_t)(mem->next - ((rt_uint8_t *)mem - small_mem->heap_ptr))));
+
+ /* return the memory data except mem struct */
+ return (rt_uint8_t *)mem + SIZEOF_STRUCT_MEM;
+ }
+ }
+
+ return RT_NULL;
+}
+RTM_EXPORT(rt_smem_alloc);
+
+/**
+ * @brief This function will change the size of previously allocated memory block.
+ *
+ * @param m the small memory management object.
+ *
+ * @param rmem is the pointer to memory allocated by rt_mem_alloc.
+ *
+ * @param newsize is the required new size.
+ *
+ * @return the changed memory block address.
+ */
+void *rt_smem_realloc(rt_smem_t m, void *rmem, rt_size_t newsize)
+{
+ rt_size_t size;
+ rt_size_t ptr, ptr2;
+ struct rt_small_mem_item *mem, *mem2;
+ struct rt_small_mem *small_mem;
+ void *nmem;
+
+ RT_ASSERT(m != RT_NULL);
+ RT_ASSERT(rt_object_get_type(&m->parent) == RT_Object_Class_Memory);
+ RT_ASSERT(rt_object_is_systemobject(&m->parent));
+
+ small_mem = (struct rt_small_mem *)m;
+ /* alignment size */
+ newsize = RT_ALIGN(newsize, RT_ALIGN_SIZE);
+ if (newsize > small_mem->mem_size_aligned)
+ {
+ RT_DEBUG_LOG(RT_DEBUG_MEM, ("realloc: out of memory\n"));
+
+ return RT_NULL;
+ }
+ else if (newsize == 0)
+ {
+ rt_smem_free(rmem);
+ return RT_NULL;
+ }
+
+ /* allocate a new memory block */
+ if (rmem == RT_NULL)
+ return rt_smem_alloc(&small_mem->parent, newsize);
+
+ RT_ASSERT((((rt_ubase_t)rmem) & (RT_ALIGN_SIZE - 1)) == 0);
+ RT_ASSERT((rt_uint8_t *)rmem >= (rt_uint8_t *)small_mem->heap_ptr);
+ RT_ASSERT((rt_uint8_t *)rmem < (rt_uint8_t *)small_mem->heap_end);
+
+ mem = (struct rt_small_mem_item *)((rt_uint8_t *)rmem - SIZEOF_STRUCT_MEM);
+
+ /* current memory block size */
+ ptr = (rt_uint8_t *)mem - small_mem->heap_ptr;
+ size = mem->next - ptr - SIZEOF_STRUCT_MEM;
+ if (size == newsize)
+ {
+ /* the size is the same as */
+ return rmem;
+ }
+
+ if (newsize + SIZEOF_STRUCT_MEM + MIN_SIZE < size)
+ {
+ /* split memory block */
+ small_mem->parent.used -= (size - newsize);
+
+ ptr2 = ptr + SIZEOF_STRUCT_MEM + newsize;
+ mem2 = (struct rt_small_mem_item *)&small_mem->heap_ptr[ptr2];
+ mem2->pool_ptr = MEM_FREED();
+ mem2->next = mem->next;
+ mem2->prev = ptr;
+#ifdef RT_USING_MEMTRACE
+ rt_smem_setname(mem2, " ");
+#endif /* RT_USING_MEMTRACE */
+ mem->next = ptr2;
+ if (mem2->next != small_mem->mem_size_aligned + SIZEOF_STRUCT_MEM)
+ {
+ ((struct rt_small_mem_item *)&small_mem->heap_ptr[mem2->next])->prev = ptr2;
+ }
+
+ if (mem2 < small_mem->lfree)
+ {
+ /* the splited struct is now the lowest */
+ small_mem->lfree = mem2;
+ }
+
+ plug_holes(small_mem, mem2);
+
+ return rmem;
+ }
+
+ /* expand memory */
+ nmem = rt_smem_alloc(&small_mem->parent, newsize);
+ if (nmem != RT_NULL) /* check memory */
+ {
+ rt_memcpy(nmem, rmem, size < newsize ? size : newsize);
+ rt_smem_free(rmem);
+ }
+
+ return nmem;
+}
+RTM_EXPORT(rt_smem_realloc);
+
+/**
+ * @brief This function will release the previously allocated memory block by
+ * rt_mem_alloc. The released memory block is taken back to system heap.
+ *
+ * @param rmem the address of memory which will be released.
+ */
+void rt_smem_free(void *rmem)
+{
+ struct rt_small_mem_item *mem;
+ struct rt_small_mem *small_mem;
+
+ if (rmem == RT_NULL)
+ return;
+
+ RT_ASSERT((((rt_ubase_t)rmem) & (RT_ALIGN_SIZE - 1)) == 0);
+
+ /* Get the corresponding struct rt_small_mem_item ... */
+ mem = (struct rt_small_mem_item *)((rt_uint8_t *)rmem - SIZEOF_STRUCT_MEM);
+
+ RT_DEBUG_LOG(RT_DEBUG_MEM,
+ ("release memory 0x%x, size: %d\n",
+ (rt_ubase_t)rmem,
+ (rt_ubase_t)(mem->next - ((rt_uint8_t *)mem - small_mem->heap_ptr))));
+
+ /* ... which has to be in a used state ... */
+ small_mem = MEM_POOL(mem);
+ RT_ASSERT(small_mem != RT_NULL);
+ RT_ASSERT(MEM_ISUSED(mem));
+ RT_ASSERT(rt_object_get_type(&small_mem->parent.parent) == RT_Object_Class_Memory);
+ RT_ASSERT(rt_object_is_systemobject(&small_mem->parent.parent));
+ RT_ASSERT((rt_uint8_t *)rmem >= (rt_uint8_t *)small_mem->heap_ptr &&
+ (rt_uint8_t *)rmem < (rt_uint8_t *)small_mem->heap_end);
+ RT_ASSERT(MEM_POOL(&small_mem->heap_ptr[mem->next]) == small_mem);
+
+ /* ... and is now unused. */
+ mem->pool_ptr = MEM_FREED();
+#ifdef RT_USING_MEMTRACE
+ rt_smem_setname(mem, " ");
+#endif /* RT_USING_MEMTRACE */
+
+ if (mem < small_mem->lfree)
+ {
+ /* the newly freed struct is now the lowest */
+ small_mem->lfree = mem;
+ }
+
+ small_mem->parent.used -= (mem->next - ((rt_uint8_t *)mem - small_mem->heap_ptr));
+
+ /* finally, see if prev or next are free also */
+ plug_holes(small_mem, mem);
+}
+RTM_EXPORT(rt_smem_free);
+
+#ifdef RT_USING_FINSH
+#include
+
+#ifdef RT_USING_MEMTRACE
+int memcheck(int argc, char *argv[])
+{
+ int position;
+ rt_base_t level;
+ struct rt_small_mem_item *mem;
+ struct rt_small_mem *m;
+ struct rt_object_information *information;
+ struct rt_list_node *node;
+ struct rt_object *object;
+ char *name;
+
+ name = argc > 1 ? argv[1] : RT_NULL;
+ level = rt_hw_interrupt_disable();
+ /* get mem object */
+ information = rt_object_get_information(RT_Object_Class_Memory);
+ for (node = information->object_list.next;
+ node != &(information->object_list);
+ node = node->next)
+ {
+ object = rt_list_entry(node, struct rt_object, list);
+ /* find the specified object */
+ if (name != RT_NULL && rt_strncmp(name, object->name, RT_NAME_MAX) != 0)
+ continue;
+ /* mem object */
+ m = (struct rt_small_mem *)object;
+ /* check mem */
+ for (mem = (struct rt_small_mem_item *)m->heap_ptr; mem != m->heap_end; mem = (struct rt_small_mem_item *)&m->heap_ptr[mem->next])
+ {
+ position = (rt_ubase_t)mem - (rt_ubase_t)m->heap_ptr;
+ if (position < 0) goto __exit;
+ if (position > (int)m->mem_size_aligned) goto __exit;
+ if (MEM_POOL(mem) != m) goto __exit;
+ }
+ }
+ rt_hw_interrupt_enable(level);
+
+ return 0;
+__exit:
+ rt_kprintf("Memory block wrong:\n");
+ rt_kprintf(" name: %s\n", m->parent.parent.name);
+ rt_kprintf("address: 0x%08x\n", mem);
+ rt_kprintf(" pool: 0x%04x\n", mem->pool_ptr);
+ rt_kprintf(" size: %d\n", mem->next - position - SIZEOF_STRUCT_MEM);
+ rt_hw_interrupt_enable(level);
+
+ return 0;
+}
+MSH_CMD_EXPORT(memcheck, check memory data);
+
+int memtrace(int argc, char **argv)
+{
+ struct rt_small_mem_item *mem;
+ struct rt_small_mem *m;
+ struct rt_object_information *information;
+ struct rt_list_node *node;
+ struct rt_object *object;
+ char *name;
+
+ name = argc > 1 ? argv[1] : RT_NULL;
+ /* get mem object */
+ information = rt_object_get_information(RT_Object_Class_Memory);
+ for (node = information->object_list.next;
+ node != &(information->object_list);
+ node = node->next)
+ {
+ object = rt_list_entry(node, struct rt_object, list);
+ /* find the specified object */
+ if (name != RT_NULL && rt_strncmp(name, object->name, RT_NAME_MAX) != 0)
+ continue;
+ /* mem object */
+ m = (struct rt_small_mem *)object;
+ /* show memory information */
+ rt_kprintf("\nmemory heap address:\n");
+ rt_kprintf("name : %s\n", m->parent.parent.name);
+ rt_kprintf("total : 0x%d\n", m->parent.total);
+ rt_kprintf("used : 0x%d\n", m->parent.used);
+ rt_kprintf("max_used: 0x%d\n", m->parent.max);
+ rt_kprintf("heap_ptr: 0x%08x\n", m->heap_ptr);
+ rt_kprintf("lfree : 0x%08x\n", m->lfree);
+ rt_kprintf("heap_end: 0x%08x\n", m->heap_end);
+ rt_kprintf("\n--memory item information --\n");
+ for (mem = (struct rt_small_mem_item *)m->heap_ptr; mem != m->heap_end; mem = (struct rt_small_mem_item *)&m->heap_ptr[mem->next])
+ {
+ int size = MEM_SIZE(m, mem);
+
+ rt_kprintf("[0x%08x - ", mem);
+ if (size < 1024)
+ rt_kprintf("%5d", size);
+ else if (size < 1024 * 1024)
+ rt_kprintf("%4dK", size / 1024);
+ else
+ rt_kprintf("%4dM", size / (1024 * 1024));
+
+ rt_kprintf("] %c%c%c%c", mem->thread[0], mem->thread[1], mem->thread[2], mem->thread[3]);
+ if (MEM_POOL(mem) != m)
+ rt_kprintf(": ***\n");
+ else
+ rt_kprintf("\n");
+ }
+ }
+ return 0;
+}
+MSH_CMD_EXPORT(memtrace, dump memory trace information);
+#endif /* RT_USING_MEMTRACE */
+#endif /* RT_USING_FINSH */
+
+#endif /* defined (RT_USING_SMALL_MEM) */
+
+/**@}*/
diff --git a/User/system/rt-thread/src/memheap.c b/User/system/rt-thread/src/memheap.c
new file mode 100644
index 0000000..71e4358
--- /dev/null
+++ b/User/system/rt-thread/src/memheap.c
@@ -0,0 +1,1001 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/*
+ * File : memheap.c
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2012-04-10 Bernard first implementation
+ * 2012-10-16 Bernard add the mutex lock for heap object.
+ * 2012-12-29 Bernard memheap can be used as system heap.
+ * change mutex lock to semaphore lock.
+ * 2013-04-10 Bernard add rt_memheap_realloc function.
+ * 2013-05-24 Bernard fix the rt_memheap_realloc issue.
+ * 2013-07-11 Grissiom fix the memory block splitting issue.
+ * 2013-07-15 Grissiom optimize rt_memheap_realloc
+ * 2021-06-03 Flybreak Fix the crash problem after opening Oz optimization on ac6.
+ */
+
+#include
+#include
+
+#ifdef RT_USING_MEMHEAP
+
+/* dynamic pool magic and mask */
+#define RT_MEMHEAP_MAGIC 0x1ea01ea0
+#define RT_MEMHEAP_MASK 0xFFFFFFFE
+#define RT_MEMHEAP_USED 0x01
+#define RT_MEMHEAP_FREED 0x00
+
+#define RT_MEMHEAP_IS_USED(i) ((i)->magic & RT_MEMHEAP_USED)
+#define RT_MEMHEAP_MINIALLOC 12
+
+#define RT_MEMHEAP_SIZE RT_ALIGN(sizeof(struct rt_memheap_item), RT_ALIGN_SIZE)
+#define MEMITEM_SIZE(item) ((rt_ubase_t)item->next - (rt_ubase_t)item - RT_MEMHEAP_SIZE)
+#define MEMITEM(ptr) (struct rt_memheap_item*)((rt_uint8_t*)ptr - RT_MEMHEAP_SIZE)
+
+static void _remove_next_ptr(struct rt_memheap_item *next_ptr)
+{
+ /* Fix the crash problem after opening Oz optimization on ac6 */
+ /* Fix IAR compiler warning */
+ next_ptr->next_free->prev_free = next_ptr->prev_free;
+ next_ptr->prev_free->next_free = next_ptr->next_free;
+ next_ptr->next->prev = next_ptr->prev;
+ next_ptr->prev->next = next_ptr->next;
+}
+
+/**
+ * @brief This function initializes a piece of memory called memheap.
+ *
+ * @note The initialized memory pool will be:
+ * +-----------------------------------+--------------------------+
+ * | whole freed memory block | Used Memory Block Tailer |
+ * +-----------------------------------+--------------------------+
+ *
+ * block_list --> whole freed memory block
+ *
+ * The length of Used Memory Block Tailer is 0,
+ * which is prevents block merging across list
+ *
+ * @param memheap is a pointer of the memheap object.
+ *
+ * @param name is the name of the memheap.
+ *
+ * @param start_addr is the start address of the memheap.
+ *
+ * @param size is the size of the memheap.
+ *
+ * @return RT_EOK
+ */
+rt_err_t rt_memheap_init(struct rt_memheap *memheap,
+ const char *name,
+ void *start_addr,
+ rt_size_t size)
+{
+ struct rt_memheap_item *item;
+
+ RT_ASSERT(memheap != RT_NULL);
+
+ /* initialize pool object */
+ rt_object_init(&(memheap->parent), RT_Object_Class_MemHeap, name);
+
+ memheap->start_addr = start_addr;
+ memheap->pool_size = RT_ALIGN_DOWN(size, RT_ALIGN_SIZE);
+ memheap->available_size = memheap->pool_size - (2 * RT_MEMHEAP_SIZE);
+ memheap->max_used_size = memheap->pool_size - memheap->available_size;
+
+ /* initialize the free list header */
+ item = &(memheap->free_header);
+ item->magic = (RT_MEMHEAP_MAGIC | RT_MEMHEAP_FREED);
+ item->pool_ptr = memheap;
+ item->next = RT_NULL;
+ item->prev = RT_NULL;
+ item->next_free = item;
+ item->prev_free = item;
+
+ /* set the free list to free list header */
+ memheap->free_list = item;
+
+ /* initialize the first big memory block */
+ item = (struct rt_memheap_item *)start_addr;
+ item->magic = (RT_MEMHEAP_MAGIC | RT_MEMHEAP_FREED);
+ item->pool_ptr = memheap;
+ item->next = RT_NULL;
+ item->prev = RT_NULL;
+ item->next_free = item;
+ item->prev_free = item;
+
+#ifdef RT_USING_MEMTRACE
+ rt_memset(item->owner_thread_name, ' ', sizeof(item->owner_thread_name));
+#endif /* RT_USING_MEMTRACE */
+
+ item->next = (struct rt_memheap_item *)
+ ((rt_uint8_t *)item + memheap->available_size + RT_MEMHEAP_SIZE);
+ item->prev = item->next;
+
+ /* block list header */
+ memheap->block_list = item;
+
+ /* place the big memory block to free list */
+ item->next_free = memheap->free_list->next_free;
+ item->prev_free = memheap->free_list;
+ memheap->free_list->next_free->prev_free = item;
+ memheap->free_list->next_free = item;
+
+ /* move to the end of memory pool to build a small tailer block,
+ * which prevents block merging
+ */
+ item = item->next;
+ /* it's a used memory block */
+ item->magic = (RT_MEMHEAP_MAGIC | RT_MEMHEAP_USED);
+ item->pool_ptr = memheap;
+ item->next = (struct rt_memheap_item *)start_addr;
+ item->prev = (struct rt_memheap_item *)start_addr;
+ /* not in free list */
+ item->next_free = item->prev_free = RT_NULL;
+
+ /* initialize semaphore lock */
+ rt_sem_init(&(memheap->lock), name, 1, RT_IPC_FLAG_PRIO);
+ memheap->locked = RT_FALSE;
+
+ RT_DEBUG_LOG(RT_DEBUG_MEMHEAP,
+ ("memory heap: start addr 0x%08x, size %d, free list header 0x%08x\n",
+ start_addr, size, &(memheap->free_header)));
+
+ return RT_EOK;
+}
+RTM_EXPORT(rt_memheap_init);
+
+/**
+ * @brief This function will remove a memheap from the system.
+ *
+ * @param heap is a pointer of memheap object.
+ *
+ * @return RT_EOK
+ */
+rt_err_t rt_memheap_detach(struct rt_memheap *heap)
+{
+ RT_ASSERT(heap);
+ RT_ASSERT(rt_object_get_type(&heap->parent) == RT_Object_Class_MemHeap);
+ RT_ASSERT(rt_object_is_systemobject(&heap->parent));
+
+ rt_sem_detach(&heap->lock);
+ rt_object_detach(&(heap->parent));
+
+ /* Return a successful completion. */
+ return RT_EOK;
+}
+RTM_EXPORT(rt_memheap_detach);
+
+/**
+ * @brief Allocate a block of memory with a minimum of 'size' bytes on memheap.
+ *
+ * @param heap is a pointer for memheap object.
+ *
+ * @param size is the minimum size of the requested block in bytes.
+ *
+ * @return the pointer to allocated memory or NULL if no free memory was found.
+ */
+void *rt_memheap_alloc(struct rt_memheap *heap, rt_size_t size)
+{
+ rt_err_t result;
+ rt_size_t free_size;
+ struct rt_memheap_item *header_ptr;
+
+ RT_ASSERT(heap != RT_NULL);
+ RT_ASSERT(rt_object_get_type(&heap->parent) == RT_Object_Class_MemHeap);
+
+ /* align allocated size */
+ size = RT_ALIGN(size, RT_ALIGN_SIZE);
+ if (size < RT_MEMHEAP_MINIALLOC)
+ size = RT_MEMHEAP_MINIALLOC;
+
+ RT_DEBUG_LOG(RT_DEBUG_MEMHEAP, ("allocate %d on heap:%8.*s",
+ size, RT_NAME_MAX, heap->parent.name));
+
+ if (size < heap->available_size)
+ {
+ /* search on free list */
+ free_size = 0;
+
+ /* lock memheap */
+ if (heap->locked == RT_FALSE)
+ {
+ result = rt_sem_take(&(heap->lock), RT_WAITING_FOREVER);
+ if (result != RT_EOK)
+ {
+ rt_set_errno(result);
+
+ return RT_NULL;
+ }
+ }
+
+ /* get the first free memory block */
+ header_ptr = heap->free_list->next_free;
+ while (header_ptr != heap->free_list && free_size < size)
+ {
+ /* get current freed memory block size */
+ free_size = MEMITEM_SIZE(header_ptr);
+ if (free_size < size)
+ {
+ /* move to next free memory block */
+ header_ptr = header_ptr->next_free;
+ }
+ }
+
+ /* determine if the memory is available. */
+ if (free_size >= size)
+ {
+ /* a block that satisfies the request has been found. */
+
+ /* determine if the block needs to be split. */
+ if (free_size >= (size + RT_MEMHEAP_SIZE + RT_MEMHEAP_MINIALLOC))
+ {
+ struct rt_memheap_item *new_ptr;
+
+ /* split the block. */
+ new_ptr = (struct rt_memheap_item *)
+ (((rt_uint8_t *)header_ptr) + size + RT_MEMHEAP_SIZE);
+
+ RT_DEBUG_LOG(RT_DEBUG_MEMHEAP,
+ ("split: block[0x%08x] nextm[0x%08x] prevm[0x%08x] to new[0x%08x]\n",
+ header_ptr,
+ header_ptr->next,
+ header_ptr->prev,
+ new_ptr));
+
+ /* mark the new block as a memory block and freed. */
+ new_ptr->magic = (RT_MEMHEAP_MAGIC | RT_MEMHEAP_FREED);
+
+ /* put the pool pointer into the new block. */
+ new_ptr->pool_ptr = heap;
+
+#ifdef RT_USING_MEMTRACE
+ rt_memset(new_ptr->owner_thread_name, ' ', sizeof(new_ptr->owner_thread_name));
+#endif /* RT_USING_MEMTRACE */
+
+ /* break down the block list */
+ new_ptr->prev = header_ptr;
+ new_ptr->next = header_ptr->next;
+ header_ptr->next->prev = new_ptr;
+ header_ptr->next = new_ptr;
+
+ /* remove header ptr from free list */
+ header_ptr->next_free->prev_free = header_ptr->prev_free;
+ header_ptr->prev_free->next_free = header_ptr->next_free;
+ header_ptr->next_free = RT_NULL;
+ header_ptr->prev_free = RT_NULL;
+
+ /* insert new_ptr to free list */
+ new_ptr->next_free = heap->free_list->next_free;
+ new_ptr->prev_free = heap->free_list;
+ heap->free_list->next_free->prev_free = new_ptr;
+ heap->free_list->next_free = new_ptr;
+ RT_DEBUG_LOG(RT_DEBUG_MEMHEAP, ("new ptr: next_free 0x%08x, prev_free 0x%08x\n",
+ new_ptr->next_free,
+ new_ptr->prev_free));
+
+ /* decrement the available byte count. */
+ heap->available_size = heap->available_size -
+ size -
+ RT_MEMHEAP_SIZE;
+ if (heap->pool_size - heap->available_size > heap->max_used_size)
+ heap->max_used_size = heap->pool_size - heap->available_size;
+ }
+ else
+ {
+ /* decrement the entire free size from the available bytes count. */
+ heap->available_size = heap->available_size - free_size;
+ if (heap->pool_size - heap->available_size > heap->max_used_size)
+ heap->max_used_size = heap->pool_size - heap->available_size;
+
+ /* remove header_ptr from free list */
+ RT_DEBUG_LOG(RT_DEBUG_MEMHEAP,
+ ("one block: block[0x%08x], next_free 0x%08x, prev_free 0x%08x\n",
+ header_ptr,
+ header_ptr->next_free,
+ header_ptr->prev_free));
+
+ header_ptr->next_free->prev_free = header_ptr->prev_free;
+ header_ptr->prev_free->next_free = header_ptr->next_free;
+ header_ptr->next_free = RT_NULL;
+ header_ptr->prev_free = RT_NULL;
+ }
+
+ /* Mark the allocated block as not available. */
+ header_ptr->magic = (RT_MEMHEAP_MAGIC | RT_MEMHEAP_USED);
+
+#ifdef RT_USING_MEMTRACE
+ if (rt_thread_self())
+ rt_memcpy(header_ptr->owner_thread_name, rt_thread_self()->name, sizeof(header_ptr->owner_thread_name));
+ else
+ rt_memcpy(header_ptr->owner_thread_name, "NONE", sizeof(header_ptr->owner_thread_name));
+#endif /* RT_USING_MEMTRACE */
+
+ if (heap->locked == RT_FALSE)
+ {
+ /* release lock */
+ rt_sem_release(&(heap->lock));
+ }
+
+ /* Return a memory address to the caller. */
+ RT_DEBUG_LOG(RT_DEBUG_MEMHEAP,
+ ("alloc mem: memory[0x%08x], heap[0x%08x], size: %d\n",
+ (void *)((rt_uint8_t *)header_ptr + RT_MEMHEAP_SIZE),
+ header_ptr,
+ size));
+
+ return (void *)((rt_uint8_t *)header_ptr + RT_MEMHEAP_SIZE);
+ }
+
+ if (heap->locked == RT_FALSE)
+ {
+ /* release lock */
+ rt_sem_release(&(heap->lock));
+ }
+ }
+
+ RT_DEBUG_LOG(RT_DEBUG_MEMHEAP, ("allocate memory: failed\n"));
+
+ /* Return the completion status. */
+ return RT_NULL;
+}
+RTM_EXPORT(rt_memheap_alloc);
+
+/**
+ * @brief This function will change the size of previously allocated memory block.
+ *
+ * @param heap is a pointer to the memheap object, which will reallocate
+ * memory from the block
+ *
+ * @param ptr is a pointer to start address of memory.
+ *
+ * @param newsize is the required new size.
+ *
+ * @return the changed memory block address.
+ */
+void *rt_memheap_realloc(struct rt_memheap *heap, void *ptr, rt_size_t newsize)
+{
+ rt_err_t result;
+ rt_size_t oldsize;
+ struct rt_memheap_item *header_ptr;
+ struct rt_memheap_item *new_ptr;
+
+ RT_ASSERT(heap);
+ RT_ASSERT(rt_object_get_type(&heap->parent) == RT_Object_Class_MemHeap);
+
+ if (newsize == 0)
+ {
+ rt_memheap_free(ptr);
+
+ return RT_NULL;
+ }
+ /* align allocated size */
+ newsize = RT_ALIGN(newsize, RT_ALIGN_SIZE);
+ if (newsize < RT_MEMHEAP_MINIALLOC)
+ newsize = RT_MEMHEAP_MINIALLOC;
+
+ if (ptr == RT_NULL)
+ {
+ return rt_memheap_alloc(heap, newsize);
+ }
+
+ /* get memory block header and get the size of memory block */
+ header_ptr = (struct rt_memheap_item *)
+ ((rt_uint8_t *)ptr - RT_MEMHEAP_SIZE);
+ oldsize = MEMITEM_SIZE(header_ptr);
+ /* re-allocate memory */
+ if (newsize > oldsize)
+ {
+ void *new_ptr;
+ struct rt_memheap_item *next_ptr;
+
+ if (heap->locked == RT_FALSE)
+ {
+ /* lock memheap */
+ result = rt_sem_take(&(heap->lock), RT_WAITING_FOREVER);
+ if (result != RT_EOK)
+ {
+ rt_set_errno(result);
+ return RT_NULL;
+ }
+ }
+
+ next_ptr = header_ptr->next;
+
+ /* header_ptr should not be the tail */
+ RT_ASSERT(next_ptr > header_ptr);
+
+ /* check whether the following free space is enough to expand */
+ if (!RT_MEMHEAP_IS_USED(next_ptr))
+ {
+ rt_int32_t nextsize;
+
+ nextsize = MEMITEM_SIZE(next_ptr);
+ RT_ASSERT(next_ptr > 0);
+
+ /* Here is the ASCII art of the situation that we can make use of
+ * the next free node without alloc/memcpy, |*| is the control
+ * block:
+ *
+ * oldsize free node
+ * |*|-----------|*|----------------------|*|
+ * newsize >= minialloc
+ * |*|----------------|*|-----------------|*|
+ */
+ if (nextsize + oldsize > newsize + RT_MEMHEAP_MINIALLOC)
+ {
+ /* decrement the entire free size from the available bytes count. */
+ heap->available_size = heap->available_size - (newsize - oldsize);
+ if (heap->pool_size - heap->available_size > heap->max_used_size)
+ heap->max_used_size = heap->pool_size - heap->available_size;
+
+ /* remove next_ptr from free list */
+ RT_DEBUG_LOG(RT_DEBUG_MEMHEAP,
+ ("remove block: block[0x%08x], next_free 0x%08x, prev_free 0x%08x",
+ next_ptr,
+ next_ptr->next_free,
+ next_ptr->prev_free));
+
+ _remove_next_ptr(next_ptr);
+
+ /* build a new one on the right place */
+ next_ptr = (struct rt_memheap_item *)((char *)ptr + newsize);
+
+ RT_DEBUG_LOG(RT_DEBUG_MEMHEAP,
+ ("new free block: block[0x%08x] nextm[0x%08x] prevm[0x%08x]",
+ next_ptr,
+ next_ptr->next,
+ next_ptr->prev));
+
+ /* mark the new block as a memory block and freed. */
+ next_ptr->magic = (RT_MEMHEAP_MAGIC | RT_MEMHEAP_FREED);
+
+ /* put the pool pointer into the new block. */
+ next_ptr->pool_ptr = heap;
+
+#ifdef RT_USING_MEMTRACE
+ rt_memset((void *)next_ptr->owner_thread_name, ' ', sizeof(next_ptr->owner_thread_name));
+#endif /* RT_USING_MEMTRACE */
+
+ next_ptr->prev = header_ptr;
+ next_ptr->next = header_ptr->next;
+ header_ptr->next->prev = (struct rt_memheap_item *)next_ptr;
+ header_ptr->next = (struct rt_memheap_item *)next_ptr;
+
+ /* insert next_ptr to free list */
+ next_ptr->next_free = heap->free_list->next_free;
+ next_ptr->prev_free = heap->free_list;
+ heap->free_list->next_free->prev_free = (struct rt_memheap_item *)next_ptr;
+ heap->free_list->next_free = (struct rt_memheap_item *)next_ptr;
+ RT_DEBUG_LOG(RT_DEBUG_MEMHEAP, ("new ptr: next_free 0x%08x, prev_free 0x%08x",
+ next_ptr->next_free,
+ next_ptr->prev_free));
+ if (heap->locked == RT_FALSE)
+ {
+ /* release lock */
+ rt_sem_release(&(heap->lock));
+ }
+
+ return ptr;
+ }
+ }
+
+ if (heap->locked == RT_FALSE)
+ {
+ /* release lock */
+ rt_sem_release(&(heap->lock));
+ }
+
+ /* re-allocate a memory block */
+ new_ptr = (void *)rt_memheap_alloc(heap, newsize);
+ if (new_ptr != RT_NULL)
+ {
+ rt_memcpy(new_ptr, ptr, oldsize < newsize ? oldsize : newsize);
+ rt_memheap_free(ptr);
+ }
+
+ return new_ptr;
+ }
+
+ /* don't split when there is less than one node space left */
+ if (newsize + RT_MEMHEAP_SIZE + RT_MEMHEAP_MINIALLOC >= oldsize)
+ return ptr;
+
+ if (heap->locked == RT_FALSE)
+ {
+ /* lock memheap */
+ result = rt_sem_take(&(heap->lock), RT_WAITING_FOREVER);
+ if (result != RT_EOK)
+ {
+ rt_set_errno(result);
+
+ return RT_NULL;
+ }
+ }
+
+ /* split the block. */
+ new_ptr = (struct rt_memheap_item *)
+ (((rt_uint8_t *)header_ptr) + newsize + RT_MEMHEAP_SIZE);
+
+ RT_DEBUG_LOG(RT_DEBUG_MEMHEAP,
+ ("split: block[0x%08x] nextm[0x%08x] prevm[0x%08x] to new[0x%08x]\n",
+ header_ptr,
+ header_ptr->next,
+ header_ptr->prev,
+ new_ptr));
+
+ /* mark the new block as a memory block and freed. */
+ new_ptr->magic = (RT_MEMHEAP_MAGIC | RT_MEMHEAP_FREED);
+ /* put the pool pointer into the new block. */
+ new_ptr->pool_ptr = heap;
+
+#ifdef RT_USING_MEMTRACE
+ rt_memset(new_ptr->owner_thread_name, ' ', sizeof(new_ptr->owner_thread_name));
+#endif /* RT_USING_MEMTRACE */
+
+ /* break down the block list */
+ new_ptr->prev = header_ptr;
+ new_ptr->next = header_ptr->next;
+ header_ptr->next->prev = new_ptr;
+ header_ptr->next = new_ptr;
+
+ /* determine if the block can be merged with the next neighbor. */
+ if (!RT_MEMHEAP_IS_USED(new_ptr->next))
+ {
+ struct rt_memheap_item *free_ptr;
+
+ /* merge block with next neighbor. */
+ free_ptr = new_ptr->next;
+ heap->available_size = heap->available_size - MEMITEM_SIZE(free_ptr);
+
+ RT_DEBUG_LOG(RT_DEBUG_MEMHEAP,
+ ("merge: right node 0x%08x, next_free 0x%08x, prev_free 0x%08x\n",
+ header_ptr, header_ptr->next_free, header_ptr->prev_free));
+
+ free_ptr->next->prev = new_ptr;
+ new_ptr->next = free_ptr->next;
+
+ /* remove free ptr from free list */
+ free_ptr->next_free->prev_free = free_ptr->prev_free;
+ free_ptr->prev_free->next_free = free_ptr->next_free;
+ }
+
+ /* insert the split block to free list */
+ new_ptr->next_free = heap->free_list->next_free;
+ new_ptr->prev_free = heap->free_list;
+ heap->free_list->next_free->prev_free = new_ptr;
+ heap->free_list->next_free = new_ptr;
+ RT_DEBUG_LOG(RT_DEBUG_MEMHEAP, ("new free ptr: next_free 0x%08x, prev_free 0x%08x\n",
+ new_ptr->next_free,
+ new_ptr->prev_free));
+
+ /* increment the available byte count. */
+ heap->available_size = heap->available_size + MEMITEM_SIZE(new_ptr);
+
+ if (heap->locked == RT_FALSE)
+ {
+ /* release lock */
+ rt_sem_release(&(heap->lock));
+ }
+
+ /* return the old memory block */
+ return ptr;
+}
+RTM_EXPORT(rt_memheap_realloc);
+
+/**
+ * @brief This function will release the allocated memory block by
+ * rt_malloc. The released memory block is taken back to system heap.
+ *
+ * @param ptr the address of memory which will be released.
+ */
+void rt_memheap_free(void *ptr)
+{
+ rt_err_t result;
+ struct rt_memheap *heap;
+ struct rt_memheap_item *header_ptr, *new_ptr;
+ rt_bool_t insert_header;
+
+ /* NULL check */
+ if (ptr == RT_NULL) return;
+
+ /* set initial status as OK */
+ insert_header = RT_TRUE;
+ new_ptr = RT_NULL;
+ header_ptr = (struct rt_memheap_item *)
+ ((rt_uint8_t *)ptr - RT_MEMHEAP_SIZE);
+
+ RT_DEBUG_LOG(RT_DEBUG_MEMHEAP, ("free memory: memory[0x%08x], block[0x%08x]\n",
+ ptr, header_ptr));
+
+ /* check magic */
+ if (header_ptr->magic != (RT_MEMHEAP_MAGIC | RT_MEMHEAP_USED) ||
+ (header_ptr->next->magic & RT_MEMHEAP_MASK) != RT_MEMHEAP_MAGIC)
+ {
+ RT_DEBUG_LOG(RT_DEBUG_MEMHEAP, ("bad magic:0x%08x @ memheap\n",
+ header_ptr->magic));
+ RT_ASSERT(header_ptr->magic == (RT_MEMHEAP_MAGIC | RT_MEMHEAP_USED));
+ /* check whether this block of memory has been over-written. */
+ RT_ASSERT((header_ptr->next->magic & RT_MEMHEAP_MASK) == RT_MEMHEAP_MAGIC);
+ }
+
+ /* get pool ptr */
+ heap = header_ptr->pool_ptr;
+
+ RT_ASSERT(heap);
+ RT_ASSERT(rt_object_get_type(&heap->parent) == RT_Object_Class_MemHeap);
+
+ if (heap->locked == RT_FALSE)
+ {
+ /* lock memheap */
+ result = rt_sem_take(&(heap->lock), RT_WAITING_FOREVER);
+ if (result != RT_EOK)
+ {
+ rt_set_errno(result);
+
+ return ;
+ }
+ }
+
+ /* Mark the memory as available. */
+ header_ptr->magic = (RT_MEMHEAP_MAGIC | RT_MEMHEAP_FREED);
+ /* Adjust the available number of bytes. */
+ heap->available_size += MEMITEM_SIZE(header_ptr);
+
+ /* Determine if the block can be merged with the previous neighbor. */
+ if (!RT_MEMHEAP_IS_USED(header_ptr->prev))
+ {
+ RT_DEBUG_LOG(RT_DEBUG_MEMHEAP, ("merge: left node 0x%08x\n",
+ header_ptr->prev));
+
+ /* adjust the available number of bytes. */
+ heap->available_size += RT_MEMHEAP_SIZE;
+
+ /* yes, merge block with previous neighbor. */
+ (header_ptr->prev)->next = header_ptr->next;
+ (header_ptr->next)->prev = header_ptr->prev;
+
+ /* move header pointer to previous. */
+ header_ptr = header_ptr->prev;
+ /* don't insert header to free list */
+ insert_header = RT_FALSE;
+ }
+
+ /* determine if the block can be merged with the next neighbor. */
+ if (!RT_MEMHEAP_IS_USED(header_ptr->next))
+ {
+ /* adjust the available number of bytes. */
+ heap->available_size += RT_MEMHEAP_SIZE;
+
+ /* merge block with next neighbor. */
+ new_ptr = header_ptr->next;
+
+ RT_DEBUG_LOG(RT_DEBUG_MEMHEAP,
+ ("merge: right node 0x%08x, next_free 0x%08x, prev_free 0x%08x\n",
+ new_ptr, new_ptr->next_free, new_ptr->prev_free));
+
+ new_ptr->next->prev = header_ptr;
+ header_ptr->next = new_ptr->next;
+
+ /* remove new ptr from free list */
+ new_ptr->next_free->prev_free = new_ptr->prev_free;
+ new_ptr->prev_free->next_free = new_ptr->next_free;
+ }
+
+ if (insert_header)
+ {
+ struct rt_memheap_item *n = heap->free_list->next_free;;
+#if defined(RT_MEMHEAP_BSET_MODE)
+ rt_size_t blk_size = MEMITEM_SIZE(header_ptr);
+ for (;n != heap->free_list; n = n->next_free)
+ {
+ rt_size_t m = MEMITEM_SIZE(n);
+ if (blk_size <= m)
+ {
+ break;
+ }
+ }
+#endif
+ /* no left merge, insert to free list */
+ header_ptr->next_free = n;
+ header_ptr->prev_free = n->prev_free;
+ n->prev_free->next_free = header_ptr;
+ n->prev_free = header_ptr;
+
+ RT_DEBUG_LOG(RT_DEBUG_MEMHEAP,
+ ("insert to free list: next_free 0x%08x, prev_free 0x%08x\n",
+ header_ptr->next_free, header_ptr->prev_free));
+ }
+
+#ifdef RT_USING_MEMTRACE
+ rt_memset(header_ptr->owner_thread_name, ' ', sizeof(header_ptr->owner_thread_name));
+#endif /* RT_USING_MEMTRACE */
+
+ if (heap->locked == RT_FALSE)
+ {
+ /* release lock */
+ rt_sem_release(&(heap->lock));
+ }
+}
+RTM_EXPORT(rt_memheap_free);
+
+/**
+* @brief This function will caculate the total memory, the used memory, and
+* the max used memory.
+*
+* @param heap is a pointer to the memheap object, which will reallocate
+* memory from the block
+*
+* @param total is a pointer to get the total size of the memory.
+*
+* @param used is a pointer to get the size of memory used.
+*
+* @param max_used is a pointer to get the maximum memory used.
+*/
+void rt_memheap_info(struct rt_memheap *heap,
+ rt_size_t *total,
+ rt_size_t *used,
+ rt_size_t *max_used)
+{
+ rt_err_t result;
+
+ if (heap->locked == RT_FALSE)
+ {
+ /* lock memheap */
+ result = rt_sem_take(&(heap->lock), RT_WAITING_FOREVER);
+ if (result != RT_EOK)
+ {
+ rt_set_errno(result);
+ return;
+ }
+ }
+
+ if (total != RT_NULL)
+ *total = heap->pool_size;
+
+ if (used != RT_NULL)
+ *used = heap->pool_size - heap->available_size;
+
+ if (max_used != RT_NULL)
+ *max_used = heap->max_used_size;
+
+ if (heap->locked == RT_FALSE)
+ {
+ /* release lock */
+ rt_sem_release(&(heap->lock));
+ }
+}
+
+#ifdef RT_USING_MEMHEAP_AS_HEAP
+/*
+ * rt_malloc port function
+*/
+void *_memheap_alloc(struct rt_memheap *heap, rt_size_t size)
+{
+ void *ptr;
+
+ /* try to allocate in system heap */
+ ptr = rt_memheap_alloc(heap, size);
+#ifdef RT_USING_MEMHEAP_AUTO_BINDING
+ if (ptr == RT_NULL)
+ {
+ struct rt_object *object;
+ struct rt_list_node *node;
+ struct rt_memheap *_heap;
+ struct rt_object_information *information;
+
+ /* try to allocate on other memory heap */
+ information = rt_object_get_information(RT_Object_Class_MemHeap);
+ RT_ASSERT(information != RT_NULL);
+ for (node = information->object_list.next;
+ node != &(information->object_list);
+ node = node->next)
+ {
+ object = rt_list_entry(node, struct rt_object, list);
+ _heap = (struct rt_memheap *)object;
+
+ /* not allocate in the default system heap */
+ if (heap == _heap)
+ continue;
+
+ ptr = rt_memheap_alloc(_heap, size);
+ if (ptr != RT_NULL)
+ break;
+ }
+ }
+#endif /* RT_USING_MEMHEAP_AUTO_BINDING */
+ return ptr;
+}
+
+/*
+ * rt_free port function
+*/
+void _memheap_free(void *rmem)
+{
+ rt_memheap_free(rmem);
+}
+
+/*
+ * rt_realloc port function
+*/
+void *_memheap_realloc(struct rt_memheap *heap, void *rmem, rt_size_t newsize)
+{
+ void *new_ptr;
+ struct rt_memheap_item *header_ptr;
+
+ if (rmem == RT_NULL)
+ return _memheap_alloc(heap, newsize);
+
+ if (newsize == 0)
+ {
+ _memheap_free(rmem);
+ return RT_NULL;
+ }
+
+ /* get old memory item */
+ header_ptr = (struct rt_memheap_item *)
+ ((rt_uint8_t *)rmem - RT_MEMHEAP_SIZE);
+
+ new_ptr = rt_memheap_realloc(header_ptr->pool_ptr, rmem, newsize);
+ if (new_ptr == RT_NULL && newsize != 0)
+ {
+ /* allocate memory block from other memheap */
+ new_ptr = _memheap_alloc(heap, newsize);
+ if (new_ptr != RT_NULL && rmem != RT_NULL)
+ {
+ rt_size_t oldsize;
+
+ /* get the size of old memory block */
+ oldsize = MEMITEM_SIZE(header_ptr);
+ if (newsize > oldsize)
+ rt_memcpy(new_ptr, rmem, oldsize);
+ else
+ rt_memcpy(new_ptr, rmem, newsize);
+
+ _memheap_free(rmem);
+ }
+ }
+
+ return new_ptr;
+}
+#endif
+
+#ifdef RT_USING_MEMTRACE
+int memheapcheck(int argc, char *argv[])
+{
+ struct rt_object_information *info;
+ struct rt_list_node *list;
+ struct rt_memheap *heap;
+ struct rt_list_node *node;
+ struct rt_memheap_item *item;
+ rt_bool_t has_bad = RT_FALSE;
+ rt_base_t level;
+ char *name;
+
+ name = argc > 1 ? argv[1] : RT_NULL;
+ level = rt_hw_interrupt_disable();
+ info = rt_object_get_information(RT_Object_Class_MemHeap);
+ list = &info->object_list;
+ for (node = list->next; node != list; node = node->next)
+ {
+ heap = (struct rt_memheap *)rt_list_entry(node, struct rt_object, list);
+ /* find the specified object */
+ if (name != RT_NULL && rt_strncmp(name, heap->parent.name, RT_NAME_MAX) != 0)
+ continue;
+ /* check memheap */
+ for (item = heap->block_list; item->next != heap->block_list; item = item->next)
+ {
+ /* check magic */
+ if (!((item->magic & (RT_MEMHEAP_MAGIC | RT_MEMHEAP_FREED)) == (RT_MEMHEAP_MAGIC | RT_MEMHEAP_FREED) ||
+ (item->magic & (RT_MEMHEAP_MAGIC | RT_MEMHEAP_USED)) == (RT_MEMHEAP_MAGIC | RT_MEMHEAP_USED)))
+ {
+ has_bad = RT_TRUE;
+ break;
+ }
+ /* check pool_ptr */
+ if (heap != item->pool_ptr)
+ {
+ has_bad = RT_TRUE;
+ break;
+ }
+ /* check next and prev */
+ if (!((rt_ubase_t)item->next <= (rt_ubase_t)((rt_ubase_t)heap->start_addr + heap->pool_size) &&
+ (rt_ubase_t)item->prev >= (rt_ubase_t)heap->start_addr) &&
+ (rt_ubase_t)item->next == RT_ALIGN((rt_ubase_t)item->next, RT_ALIGN_SIZE) &&
+ (rt_ubase_t)item->prev == RT_ALIGN((rt_ubase_t)item->prev, RT_ALIGN_SIZE))
+ {
+ has_bad = RT_TRUE;
+ break;
+ }
+ /* check item */
+ if (item->next == item->next->prev)
+ {
+ has_bad = RT_TRUE;
+ break;
+ }
+ }
+ }
+ rt_hw_interrupt_enable(level);
+ if (has_bad)
+ {
+ rt_kprintf("Memory block wrong:\n");
+ rt_kprintf("name: %s\n", heap->parent.name);
+ rt_kprintf("item: 0x%p\n", item);
+ }
+ return 0;
+}
+MSH_CMD_EXPORT(memheapcheck, check memory for memheap);
+
+int memheaptrace(int argc, char *argv[])
+{
+ struct rt_object_information *info;
+ struct rt_list_node *list;
+ struct rt_memheap *mh;
+ struct rt_list_node *node;
+ char *name;
+
+ name = argc > 1 ? argv[1] : RT_NULL;
+ info = rt_object_get_information(RT_Object_Class_MemHeap);
+ list = &info->object_list;
+ for (node = list->next; node != list; node = node->next)
+ {
+ struct rt_memheap_item *header_ptr;
+ long block_size;
+
+ mh = (struct rt_memheap *)rt_list_entry(node, struct rt_object, list);
+ /* find the specified object */
+ if (name != RT_NULL && rt_strncmp(name, mh->parent.name, RT_NAME_MAX) != 0)
+ continue;
+ /* memheap dump */
+ rt_kprintf("\nmemory heap address:\n");
+ rt_kprintf("name : %s\n", mh->parent.name);
+ rt_kprintf("heap_ptr: 0x%p\n", mh->start_addr);
+ rt_kprintf("free : 0x%08x\n", mh->available_size);
+ rt_kprintf("max_used: 0x%08x\n", mh->max_used_size);
+ rt_kprintf("size : 0x%08x\n", mh->pool_size);
+ rt_kprintf("\n--memory used information --\n");
+ /* memheap item */
+ for (header_ptr = mh->block_list;
+ header_ptr->next != mh->block_list;
+ header_ptr = header_ptr->next)
+ {
+ if ((header_ptr->magic & RT_MEMHEAP_MASK) != RT_MEMHEAP_MAGIC)
+ {
+ rt_kprintf("[0x%p - incorrect magic: 0x%08x\n",
+ header_ptr, header_ptr->magic);
+ break;
+ }
+ /* get current memory block size */
+ block_size = MEMITEM_SIZE(header_ptr);
+ if (block_size < 0)
+ break;
+
+ rt_kprintf("[0x%p - ", header_ptr);
+ if (block_size < 1024)
+ rt_kprintf("%5d", block_size);
+ else if (block_size < 1024 * 1024)
+ rt_kprintf("%4dK", block_size / 1024);
+ else
+ rt_kprintf("%4dM", block_size / (1024 * 1024));
+ /* dump thread name */
+ rt_kprintf("] %c%c%c%c\n",
+ header_ptr->owner_thread_name[0],
+ header_ptr->owner_thread_name[1],
+ header_ptr->owner_thread_name[2],
+ header_ptr->owner_thread_name[3]);
+ }
+ }
+ return 0;
+}
+
+#ifdef RT_USING_FINSH
+#include
+MSH_CMD_EXPORT(memheaptrace, dump memory trace for memheap);
+#endif /* RT_USING_FINSH */
+#endif /* RT_USING_MEMTRACE */
+#endif /* RT_USING_MEMHEAP */
diff --git a/User/system/rt-thread/src/mempool.c b/User/system/rt-thread/src/mempool.c
new file mode 100644
index 0000000..197c8af
--- /dev/null
+++ b/User/system/rt-thread/src/mempool.c
@@ -0,0 +1,470 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2006-05-27 Bernard implement memory pool
+ * 2006-06-03 Bernard fix the thread timer init bug
+ * 2006-06-30 Bernard fix the allocate/free block bug
+ * 2006-08-04 Bernard add hook support
+ * 2006-08-10 Bernard fix interrupt bug in rt_mp_alloc
+ * 2010-07-13 Bernard fix RT_ALIGN issue found by kuronca
+ * 2010-10-26 yi.qiu add module support in rt_mp_delete
+ * 2011-01-24 Bernard add object allocation check.
+ * 2012-03-22 Bernard fix align issue in rt_mp_init and rt_mp_create.
+ * 2022-01-07 Gabriel Moving __on_rt_xxxxx_hook to mempool.c
+ */
+
+#include
+#include
+
+#ifdef RT_USING_MEMPOOL
+
+#ifndef __on_rt_mp_alloc_hook
+ #define __on_rt_mp_alloc_hook(mp, block) __ON_HOOK_ARGS(rt_mp_alloc_hook, (mp, block))
+#endif
+#ifndef __on_rt_mp_free_hook
+ #define __on_rt_mp_free_hook(mp, block) __ON_HOOK_ARGS(rt_mp_free_hook, (mp, block))
+#endif
+
+#if defined(RT_USING_HOOK) && defined(RT_HOOK_USING_FUNC_PTR)
+static void (*rt_mp_alloc_hook)(struct rt_mempool *mp, void *block);
+static void (*rt_mp_free_hook)(struct rt_mempool *mp, void *block);
+
+/**
+ * @addtogroup Hook
+ */
+
+/**@{*/
+
+/**
+ * @brief This function will set a hook function, which will be invoked when a memory
+ * block is allocated from the memory pool.
+ *
+ * @param hook the hook function
+ */
+void rt_mp_alloc_sethook(void (*hook)(struct rt_mempool *mp, void *block))
+{
+ rt_mp_alloc_hook = hook;
+}
+
+/**
+ * @brief This function will set a hook function, which will be invoked when a memory
+ * block is released to the memory pool.
+ *
+ * @param hook the hook function
+ */
+void rt_mp_free_sethook(void (*hook)(struct rt_mempool *mp, void *block))
+{
+ rt_mp_free_hook = hook;
+}
+
+/**@}*/
+#endif /* RT_USING_HOOK */
+
+/**
+ * @addtogroup MM
+ */
+
+/**@{*/
+
+/**
+ * @brief This function will initialize a memory pool object, normally which is used
+ * for static object.
+ *
+ * @param mp is the memory pool object.
+ *
+ * @param name is the name of the memory pool.
+ *
+ * @param start is the start address of the memory pool.
+ *
+ * @param size is the total size of the memory pool.
+ *
+ * @param block_size is the size for each block..
+ *
+ * @return RT_EOK
+ */
+rt_err_t rt_mp_init(struct rt_mempool *mp,
+ const char *name,
+ void *start,
+ rt_size_t size,
+ rt_size_t block_size)
+{
+ rt_uint8_t *block_ptr;
+ rt_size_t offset;
+
+ /* parameter check */
+ RT_ASSERT(mp != RT_NULL);
+ RT_ASSERT(name != RT_NULL);
+ RT_ASSERT(start != RT_NULL);
+ RT_ASSERT(size > 0 && block_size > 0);
+
+ /* initialize object */
+ rt_object_init(&(mp->parent), RT_Object_Class_MemPool, name);
+
+ /* initialize memory pool */
+ mp->start_address = start;
+ mp->size = RT_ALIGN_DOWN(size, RT_ALIGN_SIZE);
+
+ /* align the block size */
+ block_size = RT_ALIGN(block_size, RT_ALIGN_SIZE);
+ mp->block_size = block_size;
+
+ /* align to align size byte */
+ mp->block_total_count = mp->size / (mp->block_size + sizeof(rt_uint8_t *));
+ mp->block_free_count = mp->block_total_count;
+
+ /* initialize suspended thread list */
+ rt_list_init(&(mp->suspend_thread));
+
+ /* initialize free block list */
+ block_ptr = (rt_uint8_t *)mp->start_address;
+ for (offset = 0; offset < mp->block_total_count; offset ++)
+ {
+ *(rt_uint8_t **)(block_ptr + offset * (block_size + sizeof(rt_uint8_t *))) =
+ (rt_uint8_t *)(block_ptr + (offset + 1) * (block_size + sizeof(rt_uint8_t *)));
+ }
+
+ *(rt_uint8_t **)(block_ptr + (offset - 1) * (block_size + sizeof(rt_uint8_t *))) =
+ RT_NULL;
+
+ mp->block_list = block_ptr;
+
+ return RT_EOK;
+}
+RTM_EXPORT(rt_mp_init);
+
+/**
+ * @brief This function will detach a memory pool from system object management.
+ *
+ * @param mp is the memory pool object.
+ *
+ * @return RT_EOK
+ */
+rt_err_t rt_mp_detach(struct rt_mempool *mp)
+{
+ struct rt_thread *thread;
+ rt_base_t level;
+
+ /* parameter check */
+ RT_ASSERT(mp != RT_NULL);
+ RT_ASSERT(rt_object_get_type(&mp->parent) == RT_Object_Class_MemPool);
+ RT_ASSERT(rt_object_is_systemobject(&mp->parent));
+
+ /* wake up all suspended threads */
+ while (!rt_list_isempty(&(mp->suspend_thread)))
+ {
+ /* disable interrupt */
+ level = rt_hw_interrupt_disable();
+
+ /* get next suspend thread */
+ thread = rt_list_entry(mp->suspend_thread.next, struct rt_thread, tlist);
+ /* set error code to RT_ERROR */
+ thread->error = -RT_ERROR;
+
+ /*
+ * resume thread
+ * In rt_thread_resume function, it will remove current thread from
+ * suspend list
+ */
+ rt_thread_resume(thread);
+
+ /* enable interrupt */
+ rt_hw_interrupt_enable(level);
+ }
+
+ /* detach object */
+ rt_object_detach(&(mp->parent));
+
+ return RT_EOK;
+}
+RTM_EXPORT(rt_mp_detach);
+
+#ifdef RT_USING_HEAP
+/**
+ * @brief This function will create a mempool object and allocate the memory pool from
+ * heap.
+ *
+ * @param name is the name of memory pool.
+ *
+ * @param block_count is the count of blocks in memory pool.
+ *
+ * @param block_size is the size for each block.
+ *
+ * @return the created mempool object
+ */
+rt_mp_t rt_mp_create(const char *name,
+ rt_size_t block_count,
+ rt_size_t block_size)
+{
+ rt_uint8_t *block_ptr;
+ struct rt_mempool *mp;
+ rt_size_t offset;
+
+ RT_DEBUG_NOT_IN_INTERRUPT;
+
+ /* parameter check */
+ RT_ASSERT(name != RT_NULL);
+ RT_ASSERT(block_count > 0 && block_size > 0);
+
+ /* allocate object */
+ mp = (struct rt_mempool *)rt_object_allocate(RT_Object_Class_MemPool, name);
+ /* allocate object failed */
+ if (mp == RT_NULL)
+ return RT_NULL;
+
+ /* initialize memory pool */
+ block_size = RT_ALIGN(block_size, RT_ALIGN_SIZE);
+ mp->block_size = block_size;
+ mp->size = (block_size + sizeof(rt_uint8_t *)) * block_count;
+
+ /* allocate memory */
+ mp->start_address = rt_malloc((block_size + sizeof(rt_uint8_t *)) *
+ block_count);
+ if (mp->start_address == RT_NULL)
+ {
+ /* no memory, delete memory pool object */
+ rt_object_delete(&(mp->parent));
+
+ return RT_NULL;
+ }
+
+ mp->block_total_count = block_count;
+ mp->block_free_count = mp->block_total_count;
+
+ /* initialize suspended thread list */
+ rt_list_init(&(mp->suspend_thread));
+
+ /* initialize free block list */
+ block_ptr = (rt_uint8_t *)mp->start_address;
+ for (offset = 0; offset < mp->block_total_count; offset ++)
+ {
+ *(rt_uint8_t **)(block_ptr + offset * (block_size + sizeof(rt_uint8_t *)))
+ = block_ptr + (offset + 1) * (block_size + sizeof(rt_uint8_t *));
+ }
+
+ *(rt_uint8_t **)(block_ptr + (offset - 1) * (block_size + sizeof(rt_uint8_t *)))
+ = RT_NULL;
+
+ mp->block_list = block_ptr;
+
+ return mp;
+}
+RTM_EXPORT(rt_mp_create);
+
+/**
+ * @brief This function will delete a memory pool and release the object memory.
+ *
+ * @param mp is the memory pool object.
+ *
+ * @return RT_EOK
+ */
+rt_err_t rt_mp_delete(rt_mp_t mp)
+{
+ struct rt_thread *thread;
+ rt_base_t level;
+
+ RT_DEBUG_NOT_IN_INTERRUPT;
+
+ /* parameter check */
+ RT_ASSERT(mp != RT_NULL);
+ RT_ASSERT(rt_object_get_type(&mp->parent) == RT_Object_Class_MemPool);
+ RT_ASSERT(rt_object_is_systemobject(&mp->parent) == RT_FALSE);
+
+ /* wake up all suspended threads */
+ while (!rt_list_isempty(&(mp->suspend_thread)))
+ {
+ /* disable interrupt */
+ level = rt_hw_interrupt_disable();
+
+ /* get next suspend thread */
+ thread = rt_list_entry(mp->suspend_thread.next, struct rt_thread, tlist);
+ /* set error code to RT_ERROR */
+ thread->error = -RT_ERROR;
+
+ /*
+ * resume thread
+ * In rt_thread_resume function, it will remove current thread from
+ * suspend list
+ */
+ rt_thread_resume(thread);
+
+ /* enable interrupt */
+ rt_hw_interrupt_enable(level);
+ }
+
+ /* release allocated room */
+ rt_free(mp->start_address);
+
+ /* detach object */
+ rt_object_delete(&(mp->parent));
+
+ return RT_EOK;
+}
+RTM_EXPORT(rt_mp_delete);
+#endif /* RT_USING_HEAP */
+
+/**
+ * @brief This function will allocate a block from memory pool.
+ *
+ * @param mp is the memory pool object.
+ *
+ * @param time is the maximum waiting time for allocating memory.
+ * - 0 for not waiting, allocating memory immediately.
+ *
+ * @return the allocated memory block or RT_NULL on allocated failed.
+ */
+void *rt_mp_alloc(rt_mp_t mp, rt_int32_t time)
+{
+ rt_uint8_t *block_ptr;
+ rt_base_t level;
+ struct rt_thread *thread;
+ rt_uint32_t before_sleep = 0;
+
+ /* parameter check */
+ RT_ASSERT(mp != RT_NULL);
+
+ /* get current thread */
+ thread = rt_thread_self();
+
+ /* disable interrupt */
+ level = rt_hw_interrupt_disable();
+
+ while (mp->block_free_count == 0)
+ {
+ /* memory block is unavailable. */
+ if (time == 0)
+ {
+ /* enable interrupt */
+ rt_hw_interrupt_enable(level);
+
+ rt_set_errno(-RT_ETIMEOUT);
+
+ return RT_NULL;
+ }
+
+ RT_DEBUG_NOT_IN_INTERRUPT;
+
+ thread->error = RT_EOK;
+
+ /* need suspend thread */
+ rt_thread_suspend(thread);
+ rt_list_insert_after(&(mp->suspend_thread), &(thread->tlist));
+
+ if (time > 0)
+ {
+ /* get the start tick of timer */
+ before_sleep = rt_tick_get();
+
+ /* init thread timer and start it */
+ rt_timer_control(&(thread->thread_timer),
+ RT_TIMER_CTRL_SET_TIME,
+ &time);
+ rt_timer_start(&(thread->thread_timer));
+ }
+
+ /* enable interrupt */
+ rt_hw_interrupt_enable(level);
+
+ /* do a schedule */
+ rt_schedule();
+
+ if (thread->error != RT_EOK)
+ return RT_NULL;
+
+ if (time > 0)
+ {
+ time -= rt_tick_get() - before_sleep;
+ if (time < 0)
+ time = 0;
+ }
+ /* disable interrupt */
+ level = rt_hw_interrupt_disable();
+ }
+
+ /* memory block is available. decrease the free block counter */
+ mp->block_free_count--;
+
+ /* get block from block list */
+ block_ptr = mp->block_list;
+ RT_ASSERT(block_ptr != RT_NULL);
+
+ /* Setup the next free node. */
+ mp->block_list = *(rt_uint8_t **)block_ptr;
+
+ /* point to memory pool */
+ *(rt_uint8_t **)block_ptr = (rt_uint8_t *)mp;
+
+ /* enable interrupt */
+ rt_hw_interrupt_enable(level);
+
+ RT_OBJECT_HOOK_CALL(rt_mp_alloc_hook,
+ (mp, (rt_uint8_t *)(block_ptr + sizeof(rt_uint8_t *))));
+
+ return (rt_uint8_t *)(block_ptr + sizeof(rt_uint8_t *));
+}
+RTM_EXPORT(rt_mp_alloc);
+
+/**
+ * @brief This function will release a memory block.
+ *
+ * @param block the address of memory block to be released.
+ */
+void rt_mp_free(void *block)
+{
+ rt_uint8_t **block_ptr;
+ struct rt_mempool *mp;
+ struct rt_thread *thread;
+ rt_base_t level;
+
+ /* parameter check */
+ if (block == RT_NULL) return;
+
+ /* get the control block of pool which the block belongs to */
+ block_ptr = (rt_uint8_t **)((rt_uint8_t *)block - sizeof(rt_uint8_t *));
+ mp = (struct rt_mempool *)*block_ptr;
+
+ RT_OBJECT_HOOK_CALL(rt_mp_free_hook, (mp, block));
+
+ /* disable interrupt */
+ level = rt_hw_interrupt_disable();
+
+ /* increase the free block count */
+ mp->block_free_count ++;
+
+ /* link the block into the block list */
+ *block_ptr = mp->block_list;
+ mp->block_list = (rt_uint8_t *)block_ptr;
+
+ if (!rt_list_isempty(&(mp->suspend_thread)))
+ {
+ /* get the suspended thread */
+ thread = rt_list_entry(mp->suspend_thread.next,
+ struct rt_thread,
+ tlist);
+
+ /* set error */
+ thread->error = RT_EOK;
+
+ /* resume thread */
+ rt_thread_resume(thread);
+
+ /* enable interrupt */
+ rt_hw_interrupt_enable(level);
+
+ /* do a schedule */
+ rt_schedule();
+
+ return;
+ }
+
+ /* enable interrupt */
+ rt_hw_interrupt_enable(level);
+}
+RTM_EXPORT(rt_mp_free);
+
+/**@}*/
+
+#endif /* RT_USING_MEMPOOL */
diff --git a/User/system/rt-thread/src/object.c b/User/system/rt-thread/src/object.c
new file mode 100644
index 0000000..af13731
--- /dev/null
+++ b/User/system/rt-thread/src/object.c
@@ -0,0 +1,609 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2006-03-14 Bernard the first version
+ * 2006-04-21 Bernard change the scheduler lock to interrupt lock
+ * 2006-05-18 Bernard fix the object init bug
+ * 2006-08-03 Bernard add hook support
+ * 2007-01-28 Bernard rename RT_OBJECT_Class_Static to RT_Object_Class_Static
+ * 2010-10-26 yi.qiu add module support in rt_object_allocate and rt_object_free
+ * 2017-12-10 Bernard Add object_info enum.
+ * 2018-01-25 Bernard Fix the object find issue when enable MODULE.
+ * 2022-01-07 Gabriel Moving __on_rt_xxxxx_hook to object.c
+ */
+
+#include
+#include
+
+#ifdef RT_USING_MODULE
+#include
+#endif /* RT_USING_MODULE */
+
+/*
+ * define object_info for the number of _object_container items.
+ */
+enum rt_object_info_type
+{
+ RT_Object_Info_Thread = 0, /**< The object is a thread. */
+#ifdef RT_USING_SEMAPHORE
+ RT_Object_Info_Semaphore, /**< The object is a semaphore. */
+#endif
+#ifdef RT_USING_MUTEX
+ RT_Object_Info_Mutex, /**< The object is a mutex. */
+#endif
+#ifdef RT_USING_EVENT
+ RT_Object_Info_Event, /**< The object is a event. */
+#endif
+#ifdef RT_USING_MAILBOX
+ RT_Object_Info_MailBox, /**< The object is a mail box. */
+#endif
+#ifdef RT_USING_MESSAGEQUEUE
+ RT_Object_Info_MessageQueue, /**< The object is a message queue. */
+#endif
+#ifdef RT_USING_MEMHEAP
+ RT_Object_Info_MemHeap, /**< The object is a memory heap */
+#endif
+#ifdef RT_USING_MEMPOOL
+ RT_Object_Info_MemPool, /**< The object is a memory pool. */
+#endif
+#ifdef RT_USING_DEVICE
+ RT_Object_Info_Device, /**< The object is a device */
+#endif
+ RT_Object_Info_Timer, /**< The object is a timer. */
+#ifdef RT_USING_MODULE
+ RT_Object_Info_Module, /**< The object is a module. */
+#endif
+#ifdef RT_USING_HEAP
+ RT_Object_Info_Memory, /**< The object is a memory. */
+#endif
+ RT_Object_Info_Unknown, /**< The object is unknown. */
+};
+
+#define _OBJ_CONTAINER_LIST_INIT(c) \
+ {&(_object_container[c].object_list), &(_object_container[c].object_list)}
+
+static struct rt_object_information _object_container[RT_Object_Info_Unknown] =
+{
+ /* initialize object container - thread */
+ {RT_Object_Class_Thread, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Thread), sizeof(struct rt_thread)},
+#ifdef RT_USING_SEMAPHORE
+ /* initialize object container - semaphore */
+ {RT_Object_Class_Semaphore, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Semaphore), sizeof(struct rt_semaphore)},
+#endif
+#ifdef RT_USING_MUTEX
+ /* initialize object container - mutex */
+ {RT_Object_Class_Mutex, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Mutex), sizeof(struct rt_mutex)},
+#endif
+#ifdef RT_USING_EVENT
+ /* initialize object container - event */
+ {RT_Object_Class_Event, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Event), sizeof(struct rt_event)},
+#endif
+#ifdef RT_USING_MAILBOX
+ /* initialize object container - mailbox */
+ {RT_Object_Class_MailBox, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_MailBox), sizeof(struct rt_mailbox)},
+#endif
+#ifdef RT_USING_MESSAGEQUEUE
+ /* initialize object container - message queue */
+ {RT_Object_Class_MessageQueue, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_MessageQueue), sizeof(struct rt_messagequeue)},
+#endif
+#ifdef RT_USING_MEMHEAP
+ /* initialize object container - memory heap */
+ {RT_Object_Class_MemHeap, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_MemHeap), sizeof(struct rt_memheap)},
+#endif
+#ifdef RT_USING_MEMPOOL
+ /* initialize object container - memory pool */
+ {RT_Object_Class_MemPool, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_MemPool), sizeof(struct rt_mempool)},
+#endif
+#ifdef RT_USING_DEVICE
+ /* initialize object container - device */
+ {RT_Object_Class_Device, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Device), sizeof(struct rt_device)},
+#endif
+ /* initialize object container - timer */
+ {RT_Object_Class_Timer, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Timer), sizeof(struct rt_timer)},
+#ifdef RT_USING_MODULE
+ /* initialize object container - module */
+ {RT_Object_Class_Module, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Module), sizeof(struct rt_dlmodule)},
+#endif
+#ifdef RT_USING_HEAP
+ /* initialize object container - small memory */
+ {RT_Object_Class_Memory, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Memory), sizeof(struct rt_memory)},
+#endif
+};
+
+#ifndef __on_rt_object_attach_hook
+ #define __on_rt_object_attach_hook(obj) __ON_HOOK_ARGS(rt_object_attach_hook, (obj))
+#endif
+#ifndef __on_rt_object_detach_hook
+ #define __on_rt_object_detach_hook(obj) __ON_HOOK_ARGS(rt_object_detach_hook, (obj))
+#endif
+#ifndef __on_rt_object_trytake_hook
+ #define __on_rt_object_trytake_hook(parent) __ON_HOOK_ARGS(rt_object_trytake_hook, (parent))
+#endif
+#ifndef __on_rt_object_take_hook
+ #define __on_rt_object_take_hook(parent) __ON_HOOK_ARGS(rt_object_take_hook, (parent))
+#endif
+#ifndef __on_rt_object_put_hook
+ #define __on_rt_object_put_hook(parent) __ON_HOOK_ARGS(rt_object_put_hook, (parent))
+#endif
+
+#if defined(RT_USING_HOOK) && defined(RT_HOOK_USING_FUNC_PTR)
+static void (*rt_object_attach_hook)(struct rt_object *object);
+static void (*rt_object_detach_hook)(struct rt_object *object);
+void (*rt_object_trytake_hook)(struct rt_object *object);
+void (*rt_object_take_hook)(struct rt_object *object);
+void (*rt_object_put_hook)(struct rt_object *object);
+
+/**
+ * @addtogroup Hook
+ */
+
+/**@{*/
+
+/**
+ * @brief This function will set a hook function, which will be invoked when object
+ * attaches to kernel object system.
+ *
+ * @param hook is the hook function.
+ */
+void rt_object_attach_sethook(void (*hook)(struct rt_object *object))
+{
+ rt_object_attach_hook = hook;
+}
+
+/**
+ * @brief This function will set a hook function, which will be invoked when object
+ * detaches from kernel object system.
+ *
+ * @param hook is the hook function
+ */
+void rt_object_detach_sethook(void (*hook)(struct rt_object *object))
+{
+ rt_object_detach_hook = hook;
+}
+
+/**
+ * @brief This function will set a hook function, which will be invoked when object
+ * is taken from kernel object system.
+ *
+ * The object is taken means:
+ * semaphore - semaphore is taken by thread
+ * mutex - mutex is taken by thread
+ * event - event is received by thread
+ * mailbox - mail is received by thread
+ * message queue - message is received by thread
+ *
+ * @param hook is the hook function.
+ */
+void rt_object_trytake_sethook(void (*hook)(struct rt_object *object))
+{
+ rt_object_trytake_hook = hook;
+}
+
+/**
+ * @brief This function will set a hook function, which will be invoked when object
+ * have been taken from kernel object system.
+ *
+ * The object have been taken means:
+ * semaphore - semaphore have been taken by thread
+ * mutex - mutex have been taken by thread
+ * event - event have been received by thread
+ * mailbox - mail have been received by thread
+ * message queue - message have been received by thread
+ * timer - timer is started
+ *
+ * @param hook the hook function.
+ */
+void rt_object_take_sethook(void (*hook)(struct rt_object *object))
+{
+ rt_object_take_hook = hook;
+}
+
+/**
+ * @brief This function will set a hook function, which will be invoked when object
+ * is put to kernel object system.
+ *
+ * @param hook is the hook function
+ */
+void rt_object_put_sethook(void (*hook)(struct rt_object *object))
+{
+ rt_object_put_hook = hook;
+}
+
+/**@}*/
+#endif /* RT_USING_HOOK */
+
+/**
+ * @addtogroup KernelObject
+ */
+
+/**@{*/
+
+/**
+ * @brief This function will return the specified type of object information.
+ *
+ * @param type is the type of object, which can be
+ * RT_Object_Class_Thread/Semaphore/Mutex... etc
+ *
+ * @return the object type information or RT_NULL
+ */
+struct rt_object_information *
+rt_object_get_information(enum rt_object_class_type type)
+{
+ int index;
+
+ for (index = 0; index < RT_Object_Info_Unknown; index ++)
+ if (_object_container[index].type == type) return &_object_container[index];
+
+ return RT_NULL;
+}
+RTM_EXPORT(rt_object_get_information);
+
+/**
+ * @brief This function will return the length of object list in object container.
+ *
+ * @param type is the type of object, which can be
+ * RT_Object_Class_Thread/Semaphore/Mutex... etc
+ *
+ * @return the length of object list
+ */
+int rt_object_get_length(enum rt_object_class_type type)
+{
+ int count = 0;
+ rt_base_t level;
+ struct rt_list_node *node = RT_NULL;
+ struct rt_object_information *information = RT_NULL;
+
+ information = rt_object_get_information((enum rt_object_class_type)type);
+ if (information == RT_NULL) return 0;
+
+ level = rt_hw_interrupt_disable();
+ /* get the count of objects */
+ rt_list_for_each(node, &(information->object_list))
+ {
+ count ++;
+ }
+ rt_hw_interrupt_enable(level);
+
+ return count;
+}
+RTM_EXPORT(rt_object_get_length);
+
+/**
+ * @brief This function will copy the object pointer of the specified type,
+ * with the maximum size specified by maxlen.
+ *
+ * @param type is the type of object, which can be
+ * RT_Object_Class_Thread/Semaphore/Mutex... etc
+ *
+ * @param pointers is the pointer will be saved to.
+ *
+ * @param maxlen is the maximum number of pointers can be saved.
+ *
+ * @return the copied number of object pointers.
+ */
+int rt_object_get_pointers(enum rt_object_class_type type, rt_object_t *pointers, int maxlen)
+{
+ int index = 0;
+ rt_base_t level;
+
+ struct rt_object *object;
+ struct rt_list_node *node = RT_NULL;
+ struct rt_object_information *information = RT_NULL;
+
+ if (maxlen <= 0) return 0;
+
+ information = rt_object_get_information((enum rt_object_class_type)type);
+ if (information == RT_NULL) return 0;
+
+ level = rt_hw_interrupt_disable();
+ /* retrieve pointer of object */
+ rt_list_for_each(node, &(information->object_list))
+ {
+ object = rt_list_entry(node, struct rt_object, list);
+
+ pointers[index] = object;
+ index ++;
+
+ if (index >= maxlen) break;
+ }
+ rt_hw_interrupt_enable(level);
+
+ return index;
+}
+RTM_EXPORT(rt_object_get_pointers);
+
+/**
+ * @brief This function will initialize an object and add it to object system
+ * management.
+ *
+ * @param object is the specified object to be initialized.
+ *
+ * @param type is the object type.
+ *
+ * @param name is the object name. In system, the object's name must be unique.
+ */
+void rt_object_init(struct rt_object *object,
+ enum rt_object_class_type type,
+ const char *name)
+{
+ rt_base_t level;
+ struct rt_list_node *node = RT_NULL;
+ struct rt_object_information *information;
+#ifdef RT_USING_MODULE
+ struct rt_dlmodule *module = dlmodule_self();
+#endif /* RT_USING_MODULE */
+
+ /* get object information */
+ information = rt_object_get_information(type);
+ RT_ASSERT(information != RT_NULL);
+
+ /* check object type to avoid re-initialization */
+
+ /* enter critical */
+ rt_enter_critical();
+ /* try to find object */
+ for (node = information->object_list.next;
+ node != &(information->object_list);
+ node = node->next)
+ {
+ struct rt_object *obj;
+
+ obj = rt_list_entry(node, struct rt_object, list);
+ if (obj) /* skip warning when disable debug */
+ {
+ RT_ASSERT(obj != object);
+ }
+ }
+ /* leave critical */
+ rt_exit_critical();
+
+ /* initialize object's parameters */
+ /* set object type to static */
+ object->type = type | RT_Object_Class_Static;
+ /* copy name */
+ rt_strncpy(object->name, name, RT_NAME_MAX);
+
+ RT_OBJECT_HOOK_CALL(rt_object_attach_hook, (object));
+
+ /* lock interrupt */
+ level = rt_hw_interrupt_disable();
+
+#ifdef RT_USING_MODULE
+ if (module)
+ {
+ rt_list_insert_after(&(module->object_list), &(object->list));
+ object->module_id = (void *)module;
+ }
+ else
+#endif /* RT_USING_MODULE */
+ {
+ /* insert object into information object list */
+ rt_list_insert_after(&(information->object_list), &(object->list));
+ }
+
+ /* unlock interrupt */
+ rt_hw_interrupt_enable(level);
+}
+
+/**
+ * @brief This function will detach a static object from object system,
+ * and the memory of static object is not freed.
+ *
+ * @param object the specified object to be detached.
+ */
+void rt_object_detach(rt_object_t object)
+{
+ rt_base_t level;
+
+ /* object check */
+ RT_ASSERT(object != RT_NULL);
+
+ RT_OBJECT_HOOK_CALL(rt_object_detach_hook, (object));
+
+ /* reset object type */
+ object->type = 0;
+
+ /* lock interrupt */
+ level = rt_hw_interrupt_disable();
+
+ /* remove from old list */
+ rt_list_remove(&(object->list));
+
+ /* unlock interrupt */
+ rt_hw_interrupt_enable(level);
+}
+
+#ifdef RT_USING_HEAP
+/**
+ * @brief This function will allocate an object from object system.
+ *
+ * @param type is the type of object.
+ *
+ * @param name is the object name. In system, the object's name must be unique.
+ *
+ * @return object
+ */
+rt_object_t rt_object_allocate(enum rt_object_class_type type, const char *name)
+{
+ struct rt_object *object;
+ rt_base_t level;
+ struct rt_object_information *information;
+#ifdef RT_USING_MODULE
+ struct rt_dlmodule *module = dlmodule_self();
+#endif /* RT_USING_MODULE */
+
+ RT_DEBUG_NOT_IN_INTERRUPT;
+
+ /* get object information */
+ information = rt_object_get_information(type);
+ RT_ASSERT(information != RT_NULL);
+
+ object = (struct rt_object *)RT_KERNEL_MALLOC(information->object_size);
+ if (object == RT_NULL)
+ {
+ /* no memory can be allocated */
+ return RT_NULL;
+ }
+
+ /* clean memory data of object */
+ rt_memset(object, 0x0, information->object_size);
+
+ /* initialize object's parameters */
+
+ /* set object type */
+ object->type = type;
+
+ /* set object flag */
+ object->flag = 0;
+
+ /* copy name */
+ rt_strncpy(object->name, name, RT_NAME_MAX);
+
+ RT_OBJECT_HOOK_CALL(rt_object_attach_hook, (object));
+
+ /* lock interrupt */
+ level = rt_hw_interrupt_disable();
+
+#ifdef RT_USING_MODULE
+ if (module)
+ {
+ rt_list_insert_after(&(module->object_list), &(object->list));
+ object->module_id = (void *)module;
+ }
+ else
+#endif /* RT_USING_MODULE */
+ {
+ /* insert object into information object list */
+ rt_list_insert_after(&(information->object_list), &(object->list));
+ }
+
+ /* unlock interrupt */
+ rt_hw_interrupt_enable(level);
+
+ /* return object */
+ return object;
+}
+
+/**
+ * @brief This function will delete an object and release object memory.
+ *
+ * @param object is the specified object to be deleted.
+ */
+void rt_object_delete(rt_object_t object)
+{
+ rt_base_t level;
+
+ /* object check */
+ RT_ASSERT(object != RT_NULL);
+ RT_ASSERT(!(object->type & RT_Object_Class_Static));
+
+ RT_OBJECT_HOOK_CALL(rt_object_detach_hook, (object));
+
+ /* reset object type */
+ object->type = RT_Object_Class_Null;
+
+ /* lock interrupt */
+ level = rt_hw_interrupt_disable();
+
+ /* remove from old list */
+ rt_list_remove(&(object->list));
+
+ /* unlock interrupt */
+ rt_hw_interrupt_enable(level);
+
+ /* free the memory of object */
+ RT_KERNEL_FREE(object);
+}
+#endif /* RT_USING_HEAP */
+
+/**
+ * @brief This function will judge the object is system object or not.
+ *
+ * @note Normally, the system object is a static object and the type
+ * of object set to RT_Object_Class_Static.
+ *
+ * @param object is the specified object to be judged.
+ *
+ * @return RT_TRUE if a system object, RT_FALSE for others.
+ */
+rt_bool_t rt_object_is_systemobject(rt_object_t object)
+{
+ /* object check */
+ RT_ASSERT(object != RT_NULL);
+
+ if (object->type & RT_Object_Class_Static)
+ return RT_TRUE;
+
+ return RT_FALSE;
+}
+
+/**
+ * @brief This function will return the type of object without
+ * RT_Object_Class_Static flag.
+ *
+ * @param object is the specified object to be get type.
+ *
+ * @return the type of object.
+ */
+rt_uint8_t rt_object_get_type(rt_object_t object)
+{
+ /* object check */
+ RT_ASSERT(object != RT_NULL);
+
+ return object->type & ~RT_Object_Class_Static;
+}
+
+/**
+ * @brief This function will find specified name object from object
+ * container.
+ *
+ * @param name is the specified name of object.
+ *
+ * @param type is the type of object
+ *
+ * @return the found object or RT_NULL if there is no this object
+ * in object container.
+ *
+ * @note this function shall not be invoked in interrupt status.
+ */
+rt_object_t rt_object_find(const char *name, rt_uint8_t type)
+{
+ struct rt_object *object = RT_NULL;
+ struct rt_list_node *node = RT_NULL;
+ struct rt_object_information *information = RT_NULL;
+
+ information = rt_object_get_information((enum rt_object_class_type)type);
+
+ /* parameter check */
+ if ((name == RT_NULL) || (information == RT_NULL)) return RT_NULL;
+
+ /* which is invoke in interrupt status */
+ RT_DEBUG_NOT_IN_INTERRUPT;
+
+ /* enter critical */
+ rt_enter_critical();
+
+ /* try to find object */
+ rt_list_for_each(node, &(information->object_list))
+ {
+ object = rt_list_entry(node, struct rt_object, list);
+ if (rt_strncmp(object->name, name, RT_NAME_MAX) == 0)
+ {
+ /* leave critical */
+ rt_exit_critical();
+
+ return object;
+ }
+ }
+
+ /* leave critical */
+ rt_exit_critical();
+
+ return RT_NULL;
+}
+
+/**@}*/
diff --git a/User/system/rt-thread/src/scheduler.c b/User/system/rt-thread/src/scheduler.c
new file mode 100644
index 0000000..8148c14
--- /dev/null
+++ b/User/system/rt-thread/src/scheduler.c
@@ -0,0 +1,1031 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2006-03-17 Bernard the first version
+ * 2006-04-28 Bernard fix the scheduler algorthm
+ * 2006-04-30 Bernard add SCHEDULER_DEBUG
+ * 2006-05-27 Bernard fix the scheduler algorthm for same priority
+ * thread schedule
+ * 2006-06-04 Bernard rewrite the scheduler algorithm
+ * 2006-08-03 Bernard add hook support
+ * 2006-09-05 Bernard add 32 priority level support
+ * 2006-09-24 Bernard add rt_system_scheduler_start function
+ * 2009-09-16 Bernard fix _rt_scheduler_stack_check
+ * 2010-04-11 yi.qiu add module feature
+ * 2010-07-13 Bernard fix the maximal number of rt_scheduler_lock_nest
+ * issue found by kuronca
+ * 2010-12-13 Bernard add defunct list initialization even if not use heap.
+ * 2011-05-10 Bernard clean scheduler debug log.
+ * 2013-12-21 Grissiom add rt_critical_level
+ * 2018-11-22 Jesven remove the current task from ready queue
+ * add per cpu ready queue
+ * add _scheduler_get_highest_priority_thread to find highest priority task
+ * rt_schedule_insert_thread won't insert current task to ready queue
+ * in smp version, rt_hw_context_switch_interrupt maybe switch to
+ * new task directly
+ * 2022-01-07 Gabriel Moving __on_rt_xxxxx_hook to scheduler.c
+ */
+
+#include
+#include
+
+rt_list_t rt_thread_priority_table[RT_THREAD_PRIORITY_MAX];
+rt_uint32_t rt_thread_ready_priority_group;
+#if RT_THREAD_PRIORITY_MAX > 32
+/* Maximum priority level, 256 */
+rt_uint8_t rt_thread_ready_table[32];
+#endif /* RT_THREAD_PRIORITY_MAX > 32 */
+
+#ifndef RT_USING_SMP
+extern volatile rt_uint8_t rt_interrupt_nest;
+static rt_int16_t rt_scheduler_lock_nest;
+struct rt_thread *rt_current_thread = RT_NULL;
+rt_uint8_t rt_current_priority;
+#endif /* RT_USING_SMP */
+
+#ifndef __on_rt_scheduler_hook
+ #define __on_rt_scheduler_hook(from, to) __ON_HOOK_ARGS(rt_scheduler_hook, (from, to))
+#endif
+#ifndef __on_rt_scheduler_switch_hook
+ #define __on_rt_scheduler_switch_hook(tid) __ON_HOOK_ARGS(rt_scheduler_switch_hook, (tid))
+#endif
+
+#if defined(RT_USING_HOOK) && defined(RT_HOOK_USING_FUNC_PTR)
+static void (*rt_scheduler_hook)(struct rt_thread *from, struct rt_thread *to);
+static void (*rt_scheduler_switch_hook)(struct rt_thread *tid);
+
+/**
+ * @addtogroup Hook
+ */
+
+/**@{*/
+
+/**
+ * @brief This function will set a hook function, which will be invoked when thread
+ * switch happens.
+ *
+ * @param hook is the hook function.
+ */
+void rt_scheduler_sethook(void (*hook)(struct rt_thread *from, struct rt_thread *to))
+{
+ rt_scheduler_hook = hook;
+}
+
+/**
+ * @brief This function will set a hook function, which will be invoked when context
+ * switch happens.
+ *
+ * @param hook is the hook function.
+ */
+void rt_scheduler_switch_sethook(void (*hook)(struct rt_thread *tid))
+{
+ rt_scheduler_switch_hook = hook;
+}
+
+/**@}*/
+#endif /* RT_USING_HOOK */
+
+#ifdef RT_USING_OVERFLOW_CHECK
+static void _scheduler_stack_check(struct rt_thread *thread)
+{
+ RT_ASSERT(thread != RT_NULL);
+
+#ifdef ARCH_CPU_STACK_GROWS_UPWARD
+ if (*((rt_uint8_t *)((rt_ubase_t)thread->stack_addr + thread->stack_size - 1)) != '#' ||
+#else
+ if (*((rt_uint8_t *)thread->stack_addr) != '#' ||
+#endif /* ARCH_CPU_STACK_GROWS_UPWARD */
+ (rt_ubase_t)thread->sp <= (rt_ubase_t)thread->stack_addr ||
+ (rt_ubase_t)thread->sp >
+ (rt_ubase_t)thread->stack_addr + (rt_ubase_t)thread->stack_size)
+ {
+ rt_base_t level;
+
+ rt_kprintf("thread:%s stack overflow\n", thread->name);
+
+ level = rt_hw_interrupt_disable();
+ while (level);
+ }
+#ifdef ARCH_CPU_STACK_GROWS_UPWARD
+ else if ((rt_ubase_t)thread->sp > ((rt_ubase_t)thread->stack_addr + thread->stack_size))
+ {
+ rt_kprintf("warning: %s stack is close to the top of stack address.\n",
+ thread->name);
+ }
+#else
+ else if ((rt_ubase_t)thread->sp <= ((rt_ubase_t)thread->stack_addr + 32))
+ {
+ rt_kprintf("warning: %s stack is close to end of stack address.\n",
+ thread->name);
+ }
+#endif /* ARCH_CPU_STACK_GROWS_UPWARD */
+}
+#endif /* RT_USING_OVERFLOW_CHECK */
+
+/*
+ * get the highest priority thread in ready queue
+ */
+#ifdef RT_USING_SMP
+static struct rt_thread* _scheduler_get_highest_priority_thread(rt_ubase_t *highest_prio)
+{
+ struct rt_thread *highest_priority_thread;
+ rt_ubase_t highest_ready_priority, local_highest_ready_priority;
+ struct rt_cpu* pcpu = rt_cpu_self();
+#if RT_THREAD_PRIORITY_MAX > 32
+ rt_ubase_t number;
+
+ number = __rt_ffs(rt_thread_ready_priority_group) - 1;
+ highest_ready_priority = (number << 3) + __rt_ffs(rt_thread_ready_table[number]) - 1;
+ number = __rt_ffs(pcpu->priority_group) - 1;
+ local_highest_ready_priority = (number << 3) + __rt_ffs(pcpu->ready_table[number]) - 1;
+#else
+ highest_ready_priority = __rt_ffs(rt_thread_ready_priority_group) - 1;
+ local_highest_ready_priority = __rt_ffs(pcpu->priority_group) - 1;
+#endif /* RT_THREAD_PRIORITY_MAX > 32 */
+
+ /* get highest ready priority thread */
+ if (highest_ready_priority < local_highest_ready_priority)
+ {
+ *highest_prio = highest_ready_priority;
+ highest_priority_thread = rt_list_entry(rt_thread_priority_table[highest_ready_priority].next,
+ struct rt_thread,
+ tlist);
+ }
+ else
+ {
+ *highest_prio = local_highest_ready_priority;
+ highest_priority_thread = rt_list_entry(pcpu->priority_table[local_highest_ready_priority].next,
+ struct rt_thread,
+ tlist);
+ }
+
+ return highest_priority_thread;
+}
+#else
+static struct rt_thread* _scheduler_get_highest_priority_thread(rt_ubase_t *highest_prio)
+{
+ struct rt_thread *highest_priority_thread;
+ rt_ubase_t highest_ready_priority;
+
+#if RT_THREAD_PRIORITY_MAX > 32
+ rt_ubase_t number;
+
+ number = __rt_ffs(rt_thread_ready_priority_group) - 1;
+ highest_ready_priority = (number << 3) + __rt_ffs(rt_thread_ready_table[number]) - 1;
+#else
+ highest_ready_priority = __rt_ffs(rt_thread_ready_priority_group) - 1;
+#endif /* RT_THREAD_PRIORITY_MAX > 32 */
+
+ /* get highest ready priority thread */
+ highest_priority_thread = rt_list_entry(rt_thread_priority_table[highest_ready_priority].next,
+ struct rt_thread,
+ tlist);
+
+ *highest_prio = highest_ready_priority;
+
+ return highest_priority_thread;
+}
+#endif /* RT_USING_SMP */
+
+/**
+ * @brief This function will initialize the system scheduler.
+ */
+void rt_system_scheduler_init(void)
+{
+#ifdef RT_USING_SMP
+ int cpu;
+#endif /* RT_USING_SMP */
+ rt_base_t offset;
+
+#ifndef RT_USING_SMP
+ rt_scheduler_lock_nest = 0;
+#endif /* RT_USING_SMP */
+
+ RT_DEBUG_LOG(RT_DEBUG_SCHEDULER, ("start scheduler: max priority 0x%02x\n",
+ RT_THREAD_PRIORITY_MAX));
+
+ for (offset = 0; offset < RT_THREAD_PRIORITY_MAX; offset ++)
+ {
+ rt_list_init(&rt_thread_priority_table[offset]);
+ }
+#ifdef RT_USING_SMP
+ for (cpu = 0; cpu < RT_CPUS_NR; cpu++)
+ {
+ struct rt_cpu *pcpu = rt_cpu_index(cpu);
+ for (offset = 0; offset < RT_THREAD_PRIORITY_MAX; offset ++)
+ {
+ rt_list_init(&pcpu->priority_table[offset]);
+ }
+
+ pcpu->irq_switch_flag = 0;
+ pcpu->current_priority = RT_THREAD_PRIORITY_MAX - 1;
+ pcpu->current_thread = RT_NULL;
+ pcpu->priority_group = 0;
+
+#if RT_THREAD_PRIORITY_MAX > 32
+ rt_memset(pcpu->ready_table, 0, sizeof(pcpu->ready_table));
+#endif /* RT_THREAD_PRIORITY_MAX > 32 */
+ }
+#endif /* RT_USING_SMP */
+
+ /* initialize ready priority group */
+ rt_thread_ready_priority_group = 0;
+
+#if RT_THREAD_PRIORITY_MAX > 32
+ /* initialize ready table */
+ rt_memset(rt_thread_ready_table, 0, sizeof(rt_thread_ready_table));
+#endif /* RT_THREAD_PRIORITY_MAX > 32 */
+}
+
+/**
+ * @brief This function will startup the scheduler. It will select one thread
+ * with the highest priority level, then switch to it.
+ */
+void rt_system_scheduler_start(void)
+{
+ struct rt_thread *to_thread;
+ rt_ubase_t highest_ready_priority;
+
+ to_thread = _scheduler_get_highest_priority_thread(&highest_ready_priority);
+
+#ifdef RT_USING_SMP
+ to_thread->oncpu = rt_hw_cpu_id();
+#else
+ rt_current_thread = to_thread;
+#endif /* RT_USING_SMP */
+
+ rt_schedule_remove_thread(to_thread);
+ to_thread->stat = RT_THREAD_RUNNING;
+
+ /* switch to new thread */
+#ifdef RT_USING_SMP
+ rt_hw_context_switch_to((rt_ubase_t)&to_thread->sp, to_thread);
+#else
+ rt_hw_context_switch_to((rt_ubase_t)&to_thread->sp);
+#endif /* RT_USING_SMP */
+
+ /* never come back */
+}
+
+/**
+ * @addtogroup Thread
+ */
+
+/**@{*/
+
+
+#ifdef RT_USING_SMP
+/**
+ * @brief This function will handle IPI interrupt and do a scheduling in system.
+ *
+ * @param vector is the number of IPI interrupt for system scheduling.
+ *
+ * @param param is not used, and can be set to RT_NULL.
+ *
+ * @note this function should be invoke or register as ISR in BSP.
+ */
+void rt_scheduler_ipi_handler(int vector, void *param)
+{
+ rt_schedule();
+}
+
+/**
+ * @brief This function will perform one scheduling. It will select one thread
+ * with the highest priority level in global ready queue or local ready queue,
+ * then switch to it.
+ */
+void rt_schedule(void)
+{
+ rt_base_t level;
+ struct rt_thread *to_thread;
+ struct rt_thread *current_thread;
+ struct rt_cpu *pcpu;
+ int cpu_id;
+
+ /* disable interrupt */
+ level = rt_hw_interrupt_disable();
+
+ cpu_id = rt_hw_cpu_id();
+ pcpu = rt_cpu_index(cpu_id);
+ current_thread = pcpu->current_thread;
+
+ /* whether do switch in interrupt */
+ if (pcpu->irq_nest)
+ {
+ pcpu->irq_switch_flag = 1;
+ rt_hw_interrupt_enable(level);
+ goto __exit;
+ }
+
+#ifdef RT_USING_SIGNALS
+ if ((current_thread->stat & RT_THREAD_STAT_MASK) == RT_THREAD_SUSPEND)
+ {
+ /* if current_thread signal is in pending */
+
+ if ((current_thread->stat & RT_THREAD_STAT_SIGNAL_MASK) & RT_THREAD_STAT_SIGNAL_PENDING)
+ {
+ rt_thread_resume(current_thread);
+ }
+ }
+#endif /* RT_USING_SIGNALS */
+
+ if (current_thread->scheduler_lock_nest == 1) /* whether lock scheduler */
+ {
+ rt_ubase_t highest_ready_priority;
+
+ if (rt_thread_ready_priority_group != 0 || pcpu->priority_group != 0)
+ {
+ to_thread = _scheduler_get_highest_priority_thread(&highest_ready_priority);
+ current_thread->oncpu = RT_CPU_DETACHED;
+ if ((current_thread->stat & RT_THREAD_STAT_MASK) == RT_THREAD_RUNNING)
+ {
+ if (current_thread->current_priority < highest_ready_priority)
+ {
+ to_thread = current_thread;
+ }
+ else if (current_thread->current_priority == highest_ready_priority && (current_thread->stat & RT_THREAD_STAT_YIELD_MASK) == 0)
+ {
+ to_thread = current_thread;
+ }
+ else
+ {
+ rt_schedule_insert_thread(current_thread);
+ }
+ current_thread->stat &= ~RT_THREAD_STAT_YIELD_MASK;
+ }
+ to_thread->oncpu = cpu_id;
+ if (to_thread != current_thread)
+ {
+ /* if the destination thread is not the same as current thread */
+ pcpu->current_priority = (rt_uint8_t)highest_ready_priority;
+
+ RT_OBJECT_HOOK_CALL(rt_scheduler_hook, (current_thread, to_thread));
+
+ rt_schedule_remove_thread(to_thread);
+ to_thread->stat = RT_THREAD_RUNNING | (to_thread->stat & ~RT_THREAD_STAT_MASK);
+
+ /* switch to new thread */
+ RT_DEBUG_LOG(RT_DEBUG_SCHEDULER,
+ ("[%d]switch to priority#%d "
+ "thread:%.*s(sp:0x%08x), "
+ "from thread:%.*s(sp: 0x%08x)\n",
+ pcpu->irq_nest, highest_ready_priority,
+ RT_NAME_MAX, to_thread->name, to_thread->sp,
+ RT_NAME_MAX, current_thread->name, current_thread->sp));
+
+#ifdef RT_USING_OVERFLOW_CHECK
+ _scheduler_stack_check(to_thread);
+#endif /* RT_USING_OVERFLOW_CHECK */
+
+ RT_OBJECT_HOOK_CALL(rt_scheduler_switch_hook, (current_thread));
+
+ rt_hw_context_switch((rt_ubase_t)¤t_thread->sp,
+ (rt_ubase_t)&to_thread->sp, to_thread);
+ }
+ }
+ }
+
+ /* enable interrupt */
+ rt_hw_interrupt_enable(level);
+
+#ifdef RT_USING_SIGNALS
+ /* check stat of thread for signal */
+ level = rt_hw_interrupt_disable();
+ if (current_thread->stat & RT_THREAD_STAT_SIGNAL_PENDING)
+ {
+ extern void rt_thread_handle_sig(rt_bool_t clean_state);
+
+ current_thread->stat &= ~RT_THREAD_STAT_SIGNAL_PENDING;
+
+ rt_hw_interrupt_enable(level);
+
+ /* check signal status */
+ rt_thread_handle_sig(RT_TRUE);
+ }
+ else
+ {
+ rt_hw_interrupt_enable(level);
+ }
+#endif /* RT_USING_SIGNALS */
+
+__exit:
+ return ;
+}
+#else
+/**
+ * @brief This function will perform scheduling once. It will select one thread
+ * with the highest priority, and switch to it immediately.
+ */
+void rt_schedule(void)
+{
+ rt_base_t level;
+ struct rt_thread *to_thread;
+ struct rt_thread *from_thread;
+
+ /* disable interrupt */
+ level = rt_hw_interrupt_disable();
+
+ /* check the scheduler is enabled or not */
+ if (rt_scheduler_lock_nest == 0)
+ {
+ rt_ubase_t highest_ready_priority;
+
+ if (rt_thread_ready_priority_group != 0)
+ {
+ /* need_insert_from_thread: need to insert from_thread to ready queue */
+ int need_insert_from_thread = 0;
+
+ to_thread = _scheduler_get_highest_priority_thread(&highest_ready_priority);
+
+ if ((rt_current_thread->stat & RT_THREAD_STAT_MASK) == RT_THREAD_RUNNING)
+ {
+ if (rt_current_thread->current_priority < highest_ready_priority)
+ {
+ to_thread = rt_current_thread;
+ }
+ else if (rt_current_thread->current_priority == highest_ready_priority && (rt_current_thread->stat & RT_THREAD_STAT_YIELD_MASK) == 0)
+ {
+ to_thread = rt_current_thread;
+ }
+ else
+ {
+ need_insert_from_thread = 1;
+ }
+ rt_current_thread->stat &= ~RT_THREAD_STAT_YIELD_MASK;
+ }
+
+ if (to_thread != rt_current_thread)
+ {
+ /* if the destination thread is not the same as current thread */
+ rt_current_priority = (rt_uint8_t)highest_ready_priority;
+ from_thread = rt_current_thread;
+ rt_current_thread = to_thread;
+
+ RT_OBJECT_HOOK_CALL(rt_scheduler_hook, (from_thread, to_thread));
+
+ if (need_insert_from_thread)
+ {
+ rt_schedule_insert_thread(from_thread);
+ }
+
+ rt_schedule_remove_thread(to_thread);
+ to_thread->stat = RT_THREAD_RUNNING | (to_thread->stat & ~RT_THREAD_STAT_MASK);
+
+ /* switch to new thread */
+ RT_DEBUG_LOG(RT_DEBUG_SCHEDULER,
+ ("[%d]switch to priority#%d "
+ "thread:%.*s(sp:0x%08x), "
+ "from thread:%.*s(sp: 0x%08x)\n",
+ rt_interrupt_nest, highest_ready_priority,
+ RT_NAME_MAX, to_thread->name, to_thread->sp,
+ RT_NAME_MAX, from_thread->name, from_thread->sp));
+
+#ifdef RT_USING_OVERFLOW_CHECK
+ _scheduler_stack_check(to_thread);
+#endif /* RT_USING_OVERFLOW_CHECK */
+
+ if (rt_interrupt_nest == 0)
+ {
+ extern void rt_thread_handle_sig(rt_bool_t clean_state);
+
+ RT_OBJECT_HOOK_CALL(rt_scheduler_switch_hook, (from_thread));
+
+ rt_hw_context_switch((rt_ubase_t)&from_thread->sp,
+ (rt_ubase_t)&to_thread->sp);
+
+ /* enable interrupt */
+ rt_hw_interrupt_enable(level);
+
+#ifdef RT_USING_SIGNALS
+ /* check stat of thread for signal */
+ level = rt_hw_interrupt_disable();
+ if (rt_current_thread->stat & RT_THREAD_STAT_SIGNAL_PENDING)
+ {
+ extern void rt_thread_handle_sig(rt_bool_t clean_state);
+
+ rt_current_thread->stat &= ~RT_THREAD_STAT_SIGNAL_PENDING;
+
+ rt_hw_interrupt_enable(level);
+
+ /* check signal status */
+ rt_thread_handle_sig(RT_TRUE);
+ }
+ else
+ {
+ rt_hw_interrupt_enable(level);
+ }
+#endif /* RT_USING_SIGNALS */
+ goto __exit;
+ }
+ else
+ {
+ RT_DEBUG_LOG(RT_DEBUG_SCHEDULER, ("switch in interrupt\n"));
+
+ rt_hw_context_switch_interrupt((rt_ubase_t)&from_thread->sp,
+ (rt_ubase_t)&to_thread->sp);
+ }
+ }
+ else
+ {
+ rt_schedule_remove_thread(rt_current_thread);
+ rt_current_thread->stat = RT_THREAD_RUNNING | (rt_current_thread->stat & ~RT_THREAD_STAT_MASK);
+ }
+ }
+ }
+
+ /* enable interrupt */
+ rt_hw_interrupt_enable(level);
+
+__exit:
+ return;
+}
+#endif /* RT_USING_SMP */
+
+/**
+ * @brief This function checks whether a scheduling is needed after an IRQ context switching. If yes,
+ * it will select one thread with the highest priority level, and then switch
+ * to it.
+ */
+#ifdef RT_USING_SMP
+void rt_scheduler_do_irq_switch(void *context)
+{
+ int cpu_id;
+ rt_base_t level;
+ struct rt_cpu* pcpu;
+ struct rt_thread *to_thread;
+ struct rt_thread *current_thread;
+
+ level = rt_hw_interrupt_disable();
+
+ cpu_id = rt_hw_cpu_id();
+ pcpu = rt_cpu_index(cpu_id);
+ current_thread = pcpu->current_thread;
+
+#ifdef RT_USING_SIGNALS
+ if ((current_thread->stat & RT_THREAD_STAT_MASK) == RT_THREAD_SUSPEND)
+ {
+ /* if current_thread signal is in pending */
+
+ if ((current_thread->stat & RT_THREAD_STAT_SIGNAL_MASK) & RT_THREAD_STAT_SIGNAL_PENDING)
+ {
+ rt_thread_resume(current_thread);
+ }
+ }
+#endif /* RT_USING_SIGNALS */
+
+ if (pcpu->irq_switch_flag == 0)
+ {
+ rt_hw_interrupt_enable(level);
+ return;
+ }
+
+ if (current_thread->scheduler_lock_nest == 1 && pcpu->irq_nest == 0)
+ {
+ rt_ubase_t highest_ready_priority;
+
+ /* clear irq switch flag */
+ pcpu->irq_switch_flag = 0;
+
+ if (rt_thread_ready_priority_group != 0 || pcpu->priority_group != 0)
+ {
+ to_thread = _scheduler_get_highest_priority_thread(&highest_ready_priority);
+ current_thread->oncpu = RT_CPU_DETACHED;
+ if ((current_thread->stat & RT_THREAD_STAT_MASK) == RT_THREAD_RUNNING)
+ {
+ if (current_thread->current_priority < highest_ready_priority)
+ {
+ to_thread = current_thread;
+ }
+ else if (current_thread->current_priority == highest_ready_priority && (current_thread->stat & RT_THREAD_STAT_YIELD_MASK) == 0)
+ {
+ to_thread = current_thread;
+ }
+ else
+ {
+ rt_schedule_insert_thread(current_thread);
+ }
+ current_thread->stat &= ~RT_THREAD_STAT_YIELD_MASK;
+ }
+ to_thread->oncpu = cpu_id;
+ if (to_thread != current_thread)
+ {
+ /* if the destination thread is not the same as current thread */
+
+ pcpu->current_priority = (rt_uint8_t)highest_ready_priority;
+
+ RT_OBJECT_HOOK_CALL(rt_scheduler_hook, (current_thread, to_thread));
+
+ rt_schedule_remove_thread(to_thread);
+ to_thread->stat = RT_THREAD_RUNNING | (to_thread->stat & ~RT_THREAD_STAT_MASK);
+
+#ifdef RT_USING_OVERFLOW_CHECK
+ _scheduler_stack_check(to_thread);
+#endif /* RT_USING_OVERFLOW_CHECK */
+ RT_DEBUG_LOG(RT_DEBUG_SCHEDULER, ("switch in interrupt\n"));
+
+ current_thread->cpus_lock_nest--;
+ current_thread->scheduler_lock_nest--;
+
+ RT_OBJECT_HOOK_CALL(rt_scheduler_switch_hook, (current_thread));
+
+ rt_hw_context_switch_interrupt(context, (rt_ubase_t)¤t_thread->sp,
+ (rt_ubase_t)&to_thread->sp, to_thread);
+ }
+ }
+ }
+ rt_hw_interrupt_enable(level);
+}
+#endif /* RT_USING_SMP */
+
+/**
+ * @brief This function will insert a thread to the system ready queue. The state of
+ * thread will be set as READY and the thread will be removed from suspend queue.
+ *
+ * @param thread is the thread to be inserted.
+ *
+ * @note Please do not invoke this function in user application.
+ */
+#ifdef RT_USING_SMP
+void rt_schedule_insert_thread(struct rt_thread *thread)
+{
+ int cpu_id;
+ int bind_cpu;
+ rt_uint32_t cpu_mask;
+ rt_base_t level;
+
+ RT_ASSERT(thread != RT_NULL);
+
+ /* disable interrupt */
+ level = rt_hw_interrupt_disable();
+
+ /* it should be RUNNING thread */
+ if (thread->oncpu != RT_CPU_DETACHED)
+ {
+ thread->stat = RT_THREAD_RUNNING | (thread->stat & ~RT_THREAD_STAT_MASK);
+ goto __exit;
+ }
+
+ /* READY thread, insert to ready queue */
+ thread->stat = RT_THREAD_READY | (thread->stat & ~RT_THREAD_STAT_MASK);
+
+ cpu_id = rt_hw_cpu_id();
+ bind_cpu = thread->bind_cpu ;
+
+ /* insert thread to ready list */
+ if (bind_cpu == RT_CPUS_NR)
+ {
+#if RT_THREAD_PRIORITY_MAX > 32
+ rt_thread_ready_table[thread->number] |= thread->high_mask;
+#endif /* RT_THREAD_PRIORITY_MAX > 32 */
+ rt_thread_ready_priority_group |= thread->number_mask;
+
+ /* there is no time slices left(YIELD), inserting thread before ready list*/
+ if((thread->stat & RT_THREAD_STAT_YIELD_MASK) != 0)
+ {
+ rt_list_insert_before(&(rt_thread_priority_table[thread->current_priority]),
+ &(thread->tlist));
+ }
+ /* there are some time slices left, inserting thread after ready list to schedule it firstly at next time*/
+ else
+ {
+ rt_list_insert_after(&(rt_thread_priority_table[thread->current_priority]),
+ &(thread->tlist));
+ }
+
+ cpu_mask = RT_CPU_MASK ^ (1 << cpu_id);
+ rt_hw_ipi_send(RT_SCHEDULE_IPI, cpu_mask);
+ }
+ else
+ {
+ struct rt_cpu *pcpu = rt_cpu_index(bind_cpu);
+
+#if RT_THREAD_PRIORITY_MAX > 32
+ pcpu->ready_table[thread->number] |= thread->high_mask;
+#endif /* RT_THREAD_PRIORITY_MAX > 32 */
+ pcpu->priority_group |= thread->number_mask;
+
+ /* there is no time slices left(YIELD), inserting thread before ready list*/
+ if((thread->stat & RT_THREAD_STAT_YIELD_MASK) != 0)
+ {
+ rt_list_insert_before(&(rt_cpu_index(bind_cpu)->priority_table[thread->current_priority]),
+ &(thread->tlist));
+ }
+ /* there are some time slices left, inserting thread after ready list to schedule it firstly at next time*/
+ else
+ {
+ rt_list_insert_after(&(rt_cpu_index(bind_cpu)->priority_table[thread->current_priority]),
+ &(thread->tlist));
+ }
+
+ if (cpu_id != bind_cpu)
+ {
+ cpu_mask = 1 << bind_cpu;
+ rt_hw_ipi_send(RT_SCHEDULE_IPI, cpu_mask);
+ }
+ }
+
+ RT_DEBUG_LOG(RT_DEBUG_SCHEDULER, ("insert thread[%.*s], the priority: %d\n",
+ RT_NAME_MAX, thread->name, thread->current_priority));
+
+__exit:
+ /* enable interrupt */
+ rt_hw_interrupt_enable(level);
+}
+#else
+void rt_schedule_insert_thread(struct rt_thread *thread)
+{
+ rt_base_t level;
+
+ RT_ASSERT(thread != RT_NULL);
+
+ /* disable interrupt */
+ level = rt_hw_interrupt_disable();
+
+ /* it's current thread, it should be RUNNING thread */
+ if (thread == rt_current_thread)
+ {
+ thread->stat = RT_THREAD_RUNNING | (thread->stat & ~RT_THREAD_STAT_MASK);
+ goto __exit;
+ }
+
+ /* READY thread, insert to ready queue */
+ thread->stat = RT_THREAD_READY | (thread->stat & ~RT_THREAD_STAT_MASK);
+ /* there is no time slices left(YIELD), inserting thread before ready list*/
+ if((thread->stat & RT_THREAD_STAT_YIELD_MASK) != 0)
+ {
+ rt_list_insert_before(&(rt_thread_priority_table[thread->current_priority]),
+ &(thread->tlist));
+ }
+ /* there are some time slices left, inserting thread after ready list to schedule it firstly at next time*/
+ else
+ {
+ rt_list_insert_after(&(rt_thread_priority_table[thread->current_priority]),
+ &(thread->tlist));
+ }
+
+ RT_DEBUG_LOG(RT_DEBUG_SCHEDULER, ("insert thread[%.*s], the priority: %d\n",
+ RT_NAME_MAX, thread->name, thread->current_priority));
+
+ /* set priority mask */
+#if RT_THREAD_PRIORITY_MAX > 32
+ rt_thread_ready_table[thread->number] |= thread->high_mask;
+#endif /* RT_THREAD_PRIORITY_MAX > 32 */
+ rt_thread_ready_priority_group |= thread->number_mask;
+
+__exit:
+ /* enable interrupt */
+ rt_hw_interrupt_enable(level);
+}
+#endif /* RT_USING_SMP */
+
+/**
+ * @brief This function will remove a thread from system ready queue.
+ *
+ * @param thread is the thread to be removed.
+ *
+ * @note Please do not invoke this function in user application.
+ */
+#ifdef RT_USING_SMP
+void rt_schedule_remove_thread(struct rt_thread *thread)
+{
+ rt_base_t level;
+
+ RT_ASSERT(thread != RT_NULL);
+
+ /* disable interrupt */
+ level = rt_hw_interrupt_disable();
+
+ RT_DEBUG_LOG(RT_DEBUG_SCHEDULER, ("remove thread[%.*s], the priority: %d\n",
+ RT_NAME_MAX, thread->name,
+ thread->current_priority));
+
+ /* remove thread from ready list */
+ rt_list_remove(&(thread->tlist));
+ if (thread->bind_cpu == RT_CPUS_NR)
+ {
+ if (rt_list_isempty(&(rt_thread_priority_table[thread->current_priority])))
+ {
+#if RT_THREAD_PRIORITY_MAX > 32
+ rt_thread_ready_table[thread->number] &= ~thread->high_mask;
+ if (rt_thread_ready_table[thread->number] == 0)
+ {
+ rt_thread_ready_priority_group &= ~thread->number_mask;
+ }
+#else
+ rt_thread_ready_priority_group &= ~thread->number_mask;
+#endif /* RT_THREAD_PRIORITY_MAX > 32 */
+ }
+ }
+ else
+ {
+ struct rt_cpu *pcpu = rt_cpu_index(thread->bind_cpu);
+
+ if (rt_list_isempty(&(pcpu->priority_table[thread->current_priority])))
+ {
+#if RT_THREAD_PRIORITY_MAX > 32
+ pcpu->ready_table[thread->number] &= ~thread->high_mask;
+ if (pcpu->ready_table[thread->number] == 0)
+ {
+ pcpu->priority_group &= ~thread->number_mask;
+ }
+#else
+ pcpu->priority_group &= ~thread->number_mask;
+#endif /* RT_THREAD_PRIORITY_MAX > 32 */
+ }
+ }
+
+ /* enable interrupt */
+ rt_hw_interrupt_enable(level);
+}
+#else
+void rt_schedule_remove_thread(struct rt_thread *thread)
+{
+ rt_base_t level;
+
+ RT_ASSERT(thread != RT_NULL);
+
+ /* disable interrupt */
+ level = rt_hw_interrupt_disable();
+
+ RT_DEBUG_LOG(RT_DEBUG_SCHEDULER, ("remove thread[%.*s], the priority: %d\n",
+ RT_NAME_MAX, thread->name,
+ thread->current_priority));
+
+ /* remove thread from ready list */
+ rt_list_remove(&(thread->tlist));
+ if (rt_list_isempty(&(rt_thread_priority_table[thread->current_priority])))
+ {
+#if RT_THREAD_PRIORITY_MAX > 32
+ rt_thread_ready_table[thread->number] &= ~thread->high_mask;
+ if (rt_thread_ready_table[thread->number] == 0)
+ {
+ rt_thread_ready_priority_group &= ~thread->number_mask;
+ }
+#else
+ rt_thread_ready_priority_group &= ~thread->number_mask;
+#endif /* RT_THREAD_PRIORITY_MAX > 32 */
+ }
+
+ /* enable interrupt */
+ rt_hw_interrupt_enable(level);
+}
+#endif /* RT_USING_SMP */
+
+/**
+ * @brief This function will lock the thread scheduler.
+ */
+#ifdef RT_USING_SMP
+void rt_enter_critical(void)
+{
+ rt_base_t level;
+ struct rt_thread *current_thread;
+
+ /* disable interrupt */
+ level = rt_hw_local_irq_disable();
+
+ current_thread = rt_cpu_self()->current_thread;
+ if (!current_thread)
+ {
+ rt_hw_local_irq_enable(level);
+ return;
+ }
+
+ /*
+ * the maximal number of nest is RT_UINT16_MAX, which is big
+ * enough and does not check here
+ */
+
+ {
+ rt_uint16_t lock_nest = current_thread->cpus_lock_nest;
+ current_thread->cpus_lock_nest++;
+ if (lock_nest == 0)
+ {
+ current_thread->scheduler_lock_nest ++;
+ rt_hw_spin_lock(&_cpus_lock);
+ }
+ }
+ /* critical for local cpu */
+ current_thread->critical_lock_nest ++;
+
+ /* lock scheduler for local cpu */
+ current_thread->scheduler_lock_nest ++;
+
+ /* enable interrupt */
+ rt_hw_local_irq_enable(level);
+}
+#else
+void rt_enter_critical(void)
+{
+ rt_base_t level;
+
+ /* disable interrupt */
+ level = rt_hw_interrupt_disable();
+
+ /*
+ * the maximal number of nest is RT_UINT16_MAX, which is big
+ * enough and does not check here
+ */
+ rt_scheduler_lock_nest ++;
+
+ /* enable interrupt */
+ rt_hw_interrupt_enable(level);
+}
+#endif /* RT_USING_SMP */
+RTM_EXPORT(rt_enter_critical);
+
+/**
+ * @brief This function will unlock the thread scheduler.
+ */
+#ifdef RT_USING_SMP
+void rt_exit_critical(void)
+{
+ rt_base_t level;
+ struct rt_thread *current_thread;
+
+ /* disable interrupt */
+ level = rt_hw_local_irq_disable();
+
+ current_thread = rt_cpu_self()->current_thread;
+ if (!current_thread)
+ {
+ rt_hw_local_irq_enable(level);
+ return;
+ }
+
+ current_thread->scheduler_lock_nest --;
+
+ current_thread->critical_lock_nest --;
+
+ current_thread->cpus_lock_nest--;
+ if (current_thread->cpus_lock_nest == 0)
+ {
+ current_thread->scheduler_lock_nest --;
+ rt_hw_spin_unlock(&_cpus_lock);
+ }
+
+ if (current_thread->scheduler_lock_nest <= 0)
+ {
+ current_thread->scheduler_lock_nest = 0;
+ /* enable interrupt */
+ rt_hw_local_irq_enable(level);
+
+ rt_schedule();
+ }
+ else
+ {
+ /* enable interrupt */
+ rt_hw_local_irq_enable(level);
+ }
+}
+#else
+void rt_exit_critical(void)
+{
+ rt_base_t level;
+
+ /* disable interrupt */
+ level = rt_hw_interrupt_disable();
+
+ rt_scheduler_lock_nest --;
+ if (rt_scheduler_lock_nest <= 0)
+ {
+ rt_scheduler_lock_nest = 0;
+ /* enable interrupt */
+ rt_hw_interrupt_enable(level);
+
+ if (rt_current_thread)
+ {
+ /* if scheduler is started, do a schedule */
+ rt_schedule();
+ }
+ }
+ else
+ {
+ /* enable interrupt */
+ rt_hw_interrupt_enable(level);
+ }
+}
+#endif /* RT_USING_SMP */
+RTM_EXPORT(rt_exit_critical);
+
+/**
+ * @brief Get the scheduler lock level.
+ *
+ * @return the level of the scheduler lock. 0 means unlocked.
+ */
+rt_uint16_t rt_critical_level(void)
+{
+#ifdef RT_USING_SMP
+ struct rt_thread *current_thread = rt_cpu_self()->current_thread;
+
+ return current_thread->critical_lock_nest;
+#else
+ return rt_scheduler_lock_nest;
+#endif /* RT_USING_SMP */
+}
+RTM_EXPORT(rt_critical_level);
+
+/**@}*/
diff --git a/User/system/rt-thread/src/signal.c b/User/system/rt-thread/src/signal.c
new file mode 100644
index 0000000..60996a6
--- /dev/null
+++ b/User/system/rt-thread/src/signal.c
@@ -0,0 +1,651 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2017/10/5 Bernard the first version
+ * 2018/09/17 Jesven fix: in _signal_deliver RT_THREAD_STAT_MASK to RT_THREAD_STAT_SIGNAL_MASK
+ * 2018/11/22 Jesven in smp version rt_hw_context_switch_to add a param
+ */
+
+#include
+#include
+
+#include
+#include
+
+#ifdef RT_USING_SIGNALS
+
+#ifndef RT_SIG_INFO_MAX
+#define RT_SIG_INFO_MAX 32
+#endif /* RT_SIG_INFO_MAX */
+
+#define DBG_TAG "SIGN"
+#define DBG_LVL DBG_WARNING
+#include
+
+#define sig_mask(sig_no) (1u << sig_no)
+#define sig_valid(sig_no) (sig_no >= 0 && sig_no < RT_SIG_MAX)
+
+struct siginfo_node
+{
+ siginfo_t si;
+ struct rt_slist_node list;
+};
+
+static struct rt_mempool *_siginfo_pool;
+static void _signal_deliver(rt_thread_t tid);
+void rt_thread_handle_sig(rt_bool_t clean_state);
+
+static void _signal_default_handler(int signo)
+{
+ LOG_I("handled signo[%d] with default action.", signo);
+ return ;
+}
+
+static void _signal_entry(void *parameter)
+{
+ rt_thread_t tid = rt_thread_self();
+
+ /* handle signal */
+ rt_thread_handle_sig(RT_FALSE);
+
+#ifdef RT_USING_SMP
+ {
+ struct rt_cpu* pcpu = rt_cpu_self();
+
+ pcpu->current_thread->cpus_lock_nest--;
+ if (pcpu->current_thread->cpus_lock_nest == 0)
+ {
+ pcpu->current_thread->scheduler_lock_nest--;
+ }
+
+ }
+#else
+ /* return to thread */
+ tid->sp = tid->sig_ret;
+ tid->sig_ret = RT_NULL;
+#endif /* RT_USING_SMP */
+
+ LOG_D("switch back to: 0x%08x\n", tid->sp);
+ tid->stat &= ~RT_THREAD_STAT_SIGNAL;
+
+#ifdef RT_USING_SMP
+ rt_hw_context_switch_to((rt_base_t)¶meter, tid);
+#else
+ rt_hw_context_switch_to((rt_ubase_t)&(tid->sp));
+#endif /* RT_USING_SMP */
+}
+
+/*
+ * To deliver a signal to thread, there are cases:
+ * 1. When thread is suspended, function resumes thread and
+ * set signal stat;
+ * 2. When thread is ready:
+ * - If function delivers a signal to self thread, just handle
+ * it.
+ * - If function delivers a signal to another ready thread, OS
+ * should build a slice context to handle it.
+ */
+static void _signal_deliver(rt_thread_t tid)
+{
+ rt_base_t level;
+
+ level = rt_hw_interrupt_disable();
+
+ /* thread is not interested in pended signals */
+ if (!(tid->sig_pending & tid->sig_mask))
+ {
+ rt_hw_interrupt_enable(level);
+ return;
+ }
+
+ if ((tid->stat & RT_THREAD_STAT_MASK) == RT_THREAD_SUSPEND)
+ {
+ /* resume thread to handle signal */
+ rt_thread_resume(tid);
+ /* add signal state */
+ tid->stat |= (RT_THREAD_STAT_SIGNAL | RT_THREAD_STAT_SIGNAL_PENDING);
+
+ rt_hw_interrupt_enable(level);
+
+ /* re-schedule */
+ rt_schedule();
+ }
+ else
+ {
+ if (tid == rt_thread_self())
+ {
+ /* add signal state */
+ tid->stat |= RT_THREAD_STAT_SIGNAL;
+
+ rt_hw_interrupt_enable(level);
+
+ /* do signal action in self thread context */
+ if (rt_interrupt_get_nest() == 0)
+ {
+ rt_thread_handle_sig(RT_TRUE);
+ }
+ }
+ else if (!((tid->stat & RT_THREAD_STAT_SIGNAL_MASK) & RT_THREAD_STAT_SIGNAL))
+ {
+ /* add signal state */
+ tid->stat |= (RT_THREAD_STAT_SIGNAL | RT_THREAD_STAT_SIGNAL_PENDING);
+
+#ifdef RT_USING_SMP
+ {
+ int cpu_id;
+
+ cpu_id = tid->oncpu;
+ if ((cpu_id != RT_CPU_DETACHED) && (cpu_id != rt_hw_cpu_id()))
+ {
+ rt_uint32_t cpu_mask;
+
+ cpu_mask = RT_CPU_MASK ^ (1 << cpu_id);
+ rt_hw_ipi_send(RT_SCHEDULE_IPI, cpu_mask);
+ }
+ }
+#else
+ /* point to the signal handle entry */
+ tid->stat &= ~RT_THREAD_STAT_SIGNAL_PENDING;
+ tid->sig_ret = tid->sp;
+ tid->sp = rt_hw_stack_init((void *)_signal_entry, RT_NULL,
+ (void *)((char *)tid->sig_ret - 32), RT_NULL);
+#endif /* RT_USING_SMP */
+
+ rt_hw_interrupt_enable(level);
+ LOG_D("signal stack pointer @ 0x%08x", tid->sp);
+
+ /* re-schedule */
+ rt_schedule();
+ }
+ else
+ {
+ rt_hw_interrupt_enable(level);
+ }
+ }
+}
+
+#ifdef RT_USING_SMP
+void *rt_signal_check(void* context)
+{
+ rt_base_t level;
+ int cpu_id;
+ struct rt_cpu* pcpu;
+ struct rt_thread *current_thread;
+
+ level = rt_hw_interrupt_disable();
+ cpu_id = rt_hw_cpu_id();
+ pcpu = rt_cpu_index(cpu_id);
+ current_thread = pcpu->current_thread;
+
+ if (pcpu->irq_nest)
+ {
+ rt_hw_interrupt_enable(level);
+ return context;
+ }
+
+ if (current_thread->cpus_lock_nest == 1)
+ {
+ if (current_thread->stat & RT_THREAD_STAT_SIGNAL_PENDING)
+ {
+ void *sig_context;
+
+ current_thread->stat &= ~RT_THREAD_STAT_SIGNAL_PENDING;
+
+ rt_hw_interrupt_enable(level);
+ sig_context = rt_hw_stack_init((void *)_signal_entry, context,
+ (void *)(context - 32), RT_NULL);
+ return sig_context;
+ }
+ }
+ rt_hw_interrupt_enable(level);
+ return context;
+}
+#endif /* RT_USING_SMP */
+
+/**
+ * @brief This function will install a processing function to a specific
+ * signal and return the old processing function of this signal.
+ *
+ * @note This function needs to be used in conjunction with the
+ * rt_signal_unmask() function to make the signal effective.
+ *
+ * @see rt_signal_unmask()
+ *
+ * @param signo is a specific signal value (range: 0 ~ RT_SIG_MAX).
+ *
+ * @param handler is sets the processing of signal value.
+ *
+ * @return Return the old processing function of this signal. ONLY When the
+ * return value is SIG_ERR, the operation is failed.
+ */
+rt_sighandler_t rt_signal_install(int signo, rt_sighandler_t handler)
+{
+ rt_base_t level;
+ rt_sighandler_t old = RT_NULL;
+ rt_thread_t tid = rt_thread_self();
+
+ if (!sig_valid(signo)) return SIG_ERR;
+
+ level = rt_hw_interrupt_disable();
+ if (tid->sig_vectors == RT_NULL)
+ {
+ rt_thread_alloc_sig(tid);
+ }
+
+ if (tid->sig_vectors)
+ {
+ old = tid->sig_vectors[signo];
+
+ if (handler == SIG_IGN) tid->sig_vectors[signo] = RT_NULL;
+ else if (handler == SIG_DFL) tid->sig_vectors[signo] = _signal_default_handler;
+ else tid->sig_vectors[signo] = handler;
+ }
+ rt_hw_interrupt_enable(level);
+
+ return old;
+}
+
+/**
+ * @brief This function will block the specified signal.
+ *
+ * @note This function will block the specified signal, even if the
+ * rt_thread_kill() function is called to send this signal to
+ * the current thread, it will no longer take effect.
+ *
+ * @see rt_thread_kill()
+ *
+ * @param signo is a specific signal value (range: 0 ~ RT_SIG_MAX).
+ */
+void rt_signal_mask(int signo)
+{
+ rt_base_t level;
+ rt_thread_t tid = rt_thread_self();
+
+ level = rt_hw_interrupt_disable();
+
+ tid->sig_mask &= ~sig_mask(signo);
+
+ rt_hw_interrupt_enable(level);
+}
+
+/**
+ * @brief This function will unblock the specified signal.
+ *
+ * @note This function will unblock the specified signal. After calling
+ * the rt_thread_kill() function to send this signal to the current
+ * thread, it will take effect.
+ *
+ * @see rt_thread_kill()
+ *
+ * @param signo is a specific signal value (range: 0 ~ RT_SIG_MAX).
+ */
+void rt_signal_unmask(int signo)
+{
+ rt_base_t level;
+ rt_thread_t tid = rt_thread_self();
+
+ level = rt_hw_interrupt_disable();
+
+ tid->sig_mask |= sig_mask(signo);
+
+ /* let thread handle pended signals */
+ if (tid->sig_mask & tid->sig_pending)
+ {
+ rt_hw_interrupt_enable(level);
+ _signal_deliver(tid);
+ }
+ else
+ {
+ rt_hw_interrupt_enable(level);
+ }
+}
+
+/**
+ * @brief This function will wait for the arrival of the set signal. If it does not wait for this signal, the thread will be
+ * suspended until it waits for this signal or the waiting time exceeds the specified timeout: timeout.
+ *
+ * @param set is the set of signal values to be waited for. Use the function
+ * sigaddset() to add the signal.
+ *
+ * @param si is a pointer to the received signal info. If you don't care about this value, you can use RT_NULL to set.
+ *
+ * @param timeout is a timeout period (unit: an OS tick).
+ *
+ * @return Return the operation status. When the return value is RT_EOK, the operation is successful.
+ * If the return value is any other values, it means that the signal wait failed.
+ */
+int rt_signal_wait(const rt_sigset_t *set, rt_siginfo_t *si, rt_int32_t timeout)
+{
+ int ret = RT_EOK;
+ rt_base_t level;
+ rt_thread_t tid = rt_thread_self();
+ struct siginfo_node *si_node = RT_NULL, *si_prev = RT_NULL;
+
+ /* current context checking */
+ RT_DEBUG_IN_THREAD_CONTEXT;
+
+ /* parameters check */
+ if (set == NULL || *set == 0 || si == NULL )
+ {
+ ret = -RT_EINVAL;
+ goto __done_return;
+ }
+
+ /* clear siginfo to avoid unknown value */
+ memset(si, 0x0, sizeof(rt_siginfo_t));
+
+ level = rt_hw_interrupt_disable();
+
+ /* already pending */
+ if (tid->sig_pending & *set) goto __done;
+
+ if (timeout == 0)
+ {
+ ret = -RT_ETIMEOUT;
+ goto __done_int;
+ }
+
+ /* suspend self thread */
+ rt_thread_suspend(tid);
+ /* set thread stat as waiting for signal */
+ tid->stat |= RT_THREAD_STAT_SIGNAL_WAIT;
+
+ /* start timeout timer */
+ if (timeout != RT_WAITING_FOREVER)
+ {
+ /* reset the timeout of thread timer and start it */
+ rt_timer_control(&(tid->thread_timer),
+ RT_TIMER_CTRL_SET_TIME,
+ &timeout);
+ rt_timer_start(&(tid->thread_timer));
+ }
+ rt_hw_interrupt_enable(level);
+
+ /* do thread scheduling */
+ rt_schedule();
+
+ level = rt_hw_interrupt_disable();
+
+ /* remove signal waiting flag */
+ tid->stat &= ~RT_THREAD_STAT_SIGNAL_WAIT;
+
+ /* check errno of thread */
+ if (tid->error == -RT_ETIMEOUT)
+ {
+ tid->error = RT_EOK;
+ rt_hw_interrupt_enable(level);
+
+ /* timer timeout */
+ ret = -RT_ETIMEOUT;
+ goto __done_return;
+ }
+
+__done:
+ /* to get the first matched pending signals */
+ si_node = (struct siginfo_node *)tid->si_list;
+ while (si_node)
+ {
+ int signo;
+
+ signo = si_node->si.si_signo;
+ if (sig_mask(signo) & *set)
+ {
+ *si = si_node->si;
+
+ LOG_D("sigwait: %d sig raised!", signo);
+ if (si_prev) si_prev->list.next = si_node->list.next;
+ else
+ {
+ struct siginfo_node *node_next;
+
+ if (si_node->list.next)
+ {
+ node_next = (void *)rt_slist_entry(si_node->list.next, struct siginfo_node, list);
+ tid->si_list = node_next;
+ }
+ else
+ {
+ tid->si_list = RT_NULL;
+ }
+ }
+
+ /* clear pending */
+ tid->sig_pending &= ~sig_mask(signo);
+ rt_mp_free(si_node);
+ break;
+ }
+
+ si_prev = si_node;
+ if (si_node->list.next)
+ {
+ si_node = (void *)rt_slist_entry(si_node->list.next, struct siginfo_node, list);
+ }
+ else
+ {
+ si_node = RT_NULL;
+ }
+ }
+
+__done_int:
+ rt_hw_interrupt_enable(level);
+
+__done_return:
+ return ret;
+}
+
+void rt_thread_handle_sig(rt_bool_t clean_state)
+{
+ rt_base_t level;
+
+ rt_thread_t tid = rt_thread_self();
+ struct siginfo_node *si_node;
+
+ level = rt_hw_interrupt_disable();
+ if (tid->sig_pending & tid->sig_mask)
+ {
+ /* if thread is not waiting for signal */
+ if (!(tid->stat & RT_THREAD_STAT_SIGNAL_WAIT))
+ {
+ while (tid->sig_pending & tid->sig_mask)
+ {
+ int signo, error;
+ rt_sighandler_t handler;
+
+ si_node = (struct siginfo_node *)tid->si_list;
+ if (!si_node) break;
+
+ /* remove this sig info node from list */
+ if (si_node->list.next == RT_NULL)
+ tid->si_list = RT_NULL;
+ else
+ tid->si_list = (void *)rt_slist_entry(si_node->list.next, struct siginfo_node, list);
+
+ signo = si_node->si.si_signo;
+ handler = tid->sig_vectors[signo];
+ tid->sig_pending &= ~sig_mask(signo);
+ rt_hw_interrupt_enable(level);
+
+ LOG_D("handle signal: %d, handler 0x%08x", signo, handler);
+ if (handler) handler(signo);
+
+ level = rt_hw_interrupt_disable();
+ error = -RT_EINTR;
+
+ rt_mp_free(si_node); /* release this siginfo node */
+ /* set errno in thread tcb */
+ tid->error = error;
+ }
+
+ /* whether clean signal status */
+ if (clean_state == RT_TRUE)
+ {
+ tid->stat &= ~RT_THREAD_STAT_SIGNAL;
+ }
+ else
+ {
+ return;
+ }
+ }
+ }
+ rt_hw_interrupt_enable(level);
+}
+
+void rt_thread_alloc_sig(rt_thread_t tid)
+{
+ int index;
+ rt_base_t level;
+ rt_sighandler_t *vectors;
+
+ vectors = (rt_sighandler_t *)RT_KERNEL_MALLOC(sizeof(rt_sighandler_t) * RT_SIG_MAX);
+ RT_ASSERT(vectors != RT_NULL);
+
+ for (index = 0; index < RT_SIG_MAX; index ++)
+ {
+ vectors[index] = _signal_default_handler;
+ }
+
+ level = rt_hw_interrupt_disable();
+ tid->sig_vectors = vectors;
+ rt_hw_interrupt_enable(level);
+}
+
+void rt_thread_free_sig(rt_thread_t tid)
+{
+ rt_base_t level;
+ struct siginfo_node *si_node;
+ rt_sighandler_t *sig_vectors;
+
+ level = rt_hw_interrupt_disable();
+ si_node = (struct siginfo_node *)tid->si_list;
+ tid->si_list = RT_NULL;
+
+ sig_vectors = tid->sig_vectors;
+ tid->sig_vectors = RT_NULL;
+ rt_hw_interrupt_enable(level);
+
+ if (si_node)
+ {
+ struct rt_slist_node *node;
+ struct rt_slist_node *node_to_free;
+
+ LOG_D("free signal info list");
+ node = &(si_node->list);
+ do
+ {
+ node_to_free = node;
+ node = node->next;
+ si_node = rt_slist_entry(node_to_free, struct siginfo_node, list);
+ rt_mp_free(si_node);
+ } while (node);
+ }
+
+ if (sig_vectors)
+ {
+ RT_KERNEL_FREE(sig_vectors);
+ }
+}
+
+/**
+ * @brief This function can be used to send any signal to any thread.
+ *
+ * @param tid is a pointer to the thread that receives the signal.
+ *
+ * @param sig is a specific signal value (range: 0 ~ RT_SIG_MAX).
+ *
+ * @return Return the operation status. When the return value is RT_EOK, the operation is successful.
+ * If the return value is any other values, it means that the signal send failed.
+ */
+int rt_thread_kill(rt_thread_t tid, int sig)
+{
+ siginfo_t si;
+ rt_base_t level;
+ struct siginfo_node *si_node;
+
+ RT_ASSERT(tid != RT_NULL);
+ if (!sig_valid(sig)) return -RT_EINVAL;
+
+ LOG_I("send signal: %d", sig);
+ si.si_signo = sig;
+ si.si_code = SI_USER;
+ si.si_value.sival_ptr = RT_NULL;
+
+ level = rt_hw_interrupt_disable();
+ if (tid->sig_pending & sig_mask(sig))
+ {
+ /* whether already emits this signal? */
+ struct rt_slist_node *node;
+ struct siginfo_node *entry;
+
+ si_node = (struct siginfo_node *)tid->si_list;
+ if (si_node)
+ node = (struct rt_slist_node *)&si_node->list;
+ else
+ node = RT_NULL;
+
+ /* update sig info */
+ for (; (node) != RT_NULL; node = node->next)
+ {
+ entry = rt_slist_entry(node, struct siginfo_node, list);
+ if (entry->si.si_signo == sig)
+ {
+ memcpy(&(entry->si), &si, sizeof(siginfo_t));
+ rt_hw_interrupt_enable(level);
+ return 0;
+ }
+ }
+ }
+ rt_hw_interrupt_enable(level);
+
+ si_node = (struct siginfo_node *) rt_mp_alloc(_siginfo_pool, 0);
+ if (si_node)
+ {
+ rt_slist_init(&(si_node->list));
+ memcpy(&(si_node->si), &si, sizeof(siginfo_t));
+
+ level = rt_hw_interrupt_disable();
+
+ if (tid->si_list)
+ {
+ struct siginfo_node *si_list;
+
+ si_list = (struct siginfo_node *)tid->si_list;
+ rt_slist_append(&(si_list->list), &(si_node->list));
+ }
+ else
+ {
+ tid->si_list = si_node;
+ }
+
+ /* a new signal */
+ tid->sig_pending |= sig_mask(sig);
+
+ rt_hw_interrupt_enable(level);
+ }
+ else
+ {
+ LOG_E("The allocation of signal info node failed.");
+ }
+
+ /* deliver signal to this thread */
+ _signal_deliver(tid);
+
+ return RT_EOK;
+}
+
+int rt_system_signal_init(void)
+{
+ _siginfo_pool = rt_mp_create("signal", RT_SIG_INFO_MAX, sizeof(struct siginfo_node));
+ if (_siginfo_pool == RT_NULL)
+ {
+ LOG_E("create memory pool for signal info failed.");
+ RT_ASSERT(0);
+ }
+
+ return 0;
+}
+
+#endif /* RT_USING_SIGNALS */
diff --git a/User/system/rt-thread/src/slab.c b/User/system/rt-thread/src/slab.c
new file mode 100644
index 0000000..f48179a
--- /dev/null
+++ b/User/system/rt-thread/src/slab.c
@@ -0,0 +1,856 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/*
+ * File : slab.c
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2008-07-12 Bernard the first version
+ * 2010-07-13 Bernard fix RT_ALIGN issue found by kuronca
+ * 2010-10-23 yi.qiu add module memory allocator
+ * 2010-12-18 yi.qiu fix zone release bug
+ */
+
+/*
+ * KERN_SLABALLOC.C - Kernel SLAB memory allocator
+ *
+ * Copyright (c) 2003,2004 The DragonFly Project. All rights reserved.
+ *
+ * This code is derived from software contributed to The DragonFly Project
+ * by Matthew Dillon
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name of The DragonFly Project nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific, prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include
+#include
+
+#if defined (RT_USING_SLAB)
+/*
+ * slab allocator implementation
+ *
+ * A slab allocator reserves a ZONE for each chunk size, then lays the
+ * chunks out in an array within the zone. Allocation and deallocation
+ * is nearly instantanious, and fragmentation/overhead losses are limited
+ * to a fixed worst-case amount.
+ *
+ * The downside of this slab implementation is in the chunk size
+ * multiplied by the number of zones. ~80 zones * 128K = 10MB of VM per cpu.
+ * In a kernel implementation all this memory will be physical so
+ * the zone size is adjusted downward on machines with less physical
+ * memory. The upside is that overhead is bounded... this is the *worst*
+ * case overhead.
+ *
+ * Slab management is done on a per-cpu basis and no locking or mutexes
+ * are required, only a critical section. When one cpu frees memory
+ * belonging to another cpu's slab manager an asynchronous IPI message
+ * will be queued to execute the operation. In addition, both the
+ * high level slab allocator and the low level zone allocator optimize
+ * M_ZERO requests, and the slab allocator does not have to pre initialize
+ * the linked list of chunks.
+ *
+ * XXX Balancing is needed between cpus. Balance will be handled through
+ * asynchronous IPIs primarily by reassigning the z_Cpu ownership of chunks.
+ *
+ * XXX If we have to allocate a new zone and M_USE_RESERVE is set, use of
+ * the new zone should be restricted to M_USE_RESERVE requests only.
+ *
+ * Alloc Size Chunking Number of zones
+ * 0-127 8 16
+ * 128-255 16 8
+ * 256-511 32 8
+ * 512-1023 64 8
+ * 1024-2047 128 8
+ * 2048-4095 256 8
+ * 4096-8191 512 8
+ * 8192-16383 1024 8
+ * 16384-32767 2048 8
+ * (if RT_MM_PAGE_SIZE is 4K the maximum zone allocation is 16383)
+ *
+ * Allocations >= zone_limit go directly to kmem.
+ *
+ * API REQUIREMENTS AND SIDE EFFECTS
+ *
+ * To operate as a drop-in replacement to the FreeBSD-4.x malloc() we
+ * have remained compatible with the following API requirements:
+ *
+ * + small power-of-2 sized allocations are power-of-2 aligned (kern_tty)
+ * + all power-of-2 sized allocations are power-of-2 aligned (twe)
+ * + malloc(0) is allowed and returns non-RT_NULL (ahc driver)
+ * + ability to allocate arbitrarily large chunks of memory
+ */
+
+#define ZALLOC_SLAB_MAGIC 0x51ab51ab
+#define ZALLOC_ZONE_LIMIT (16 * 1024) /* max slab-managed alloc */
+#define ZALLOC_MIN_ZONE_SIZE (32 * 1024) /* minimum zone size */
+#define ZALLOC_MAX_ZONE_SIZE (128 * 1024) /* maximum zone size */
+#define ZONE_RELEASE_THRESH 2 /* threshold number of zones */
+
+/*
+ * Misc constants. Note that allocations that are exact multiples of
+ * RT_MM_PAGE_SIZE, or exceed the zone limit, fall through to the kmem module.
+ */
+#define MIN_CHUNK_SIZE 8 /* in bytes */
+#define MIN_CHUNK_MASK (MIN_CHUNK_SIZE - 1)
+
+/*
+ * Array of descriptors that describe the contents of each page
+ */
+#define PAGE_TYPE_FREE 0x00
+#define PAGE_TYPE_SMALL 0x01
+#define PAGE_TYPE_LARGE 0x02
+
+#define btokup(addr) \
+ (&slab->memusage[((rt_ubase_t)(addr) - slab->heap_start) >> RT_MM_PAGE_BITS])
+
+/**
+ * Base structure of slab memory object
+ */
+
+/*
+ * The IN-BAND zone header is placed at the beginning of each zone.
+ */
+struct rt_slab_zone
+{
+ rt_uint32_t z_magic; /**< magic number for sanity check */
+ rt_uint32_t z_nfree; /**< total free chunks / ualloc space in zone */
+ rt_uint32_t z_nmax; /**< maximum free chunks */
+ struct rt_slab_zone *z_next; /**< zoneary[] link if z_nfree non-zero */
+ rt_uint8_t *z_baseptr; /**< pointer to start of chunk array */
+
+ rt_uint32_t z_uindex; /**< current initial allocation index */
+ rt_uint32_t z_chunksize; /**< chunk size for validation */
+
+ rt_uint32_t z_zoneindex; /**< zone index */
+ struct rt_slab_chunk *z_freechunk; /**< free chunk list */
+};
+
+/*
+ * Chunk structure for free elements
+ */
+struct rt_slab_chunk
+{
+ struct rt_slab_chunk *c_next;
+};
+
+struct rt_slab_memusage
+{
+ rt_uint32_t type: 2 ; /**< page type */
+ rt_uint32_t size: 30; /**< pages allocated or offset from zone */
+};
+
+/*
+ * slab page allocator
+ */
+struct rt_slab_page
+{
+ struct rt_slab_page *next; /**< next valid page */
+ rt_size_t page; /**< number of page */
+
+ /* dummy */
+ char dummy[RT_MM_PAGE_SIZE - (sizeof(struct rt_slab_page *) + sizeof(rt_size_t))];
+};
+
+#define RT_SLAB_NZONES 72 /* number of zones */
+
+/*
+ * slab object
+ */
+struct rt_slab
+{
+ struct rt_memory parent; /**< inherit from rt_memory */
+ rt_ubase_t heap_start; /**< memory start address */
+ rt_ubase_t heap_end; /**< memory end address */
+ struct rt_slab_memusage *memusage;
+ struct rt_slab_zone *zone_array[RT_SLAB_NZONES]; /* linked list of zones NFree > 0 */
+ struct rt_slab_zone *zone_free; /* whole zones that have become free */
+ rt_uint32_t zone_free_cnt;
+ rt_uint32_t zone_size;
+ rt_uint32_t zone_limit;
+ rt_uint32_t zone_page_cnt;
+ struct rt_slab_page *page_list;
+};
+
+/**
+ * @brief Alloc memory size by page.
+ *
+ * @param slab the slab memory management object.
+ *
+ * @param npages the number of pages.
+ */
+void *rt_slab_page_alloc(rt_slab_t m, rt_size_t npages)
+{
+ struct rt_slab_page *b, *n;
+ struct rt_slab_page **prev;
+ struct rt_slab *slab = (struct rt_slab *)m;
+
+ if (npages == 0)
+ return RT_NULL;
+
+ for (prev = &slab->page_list; (b = *prev) != RT_NULL; prev = &(b->next))
+ {
+ if (b->page > npages)
+ {
+ /* splite pages */
+ n = b + npages;
+ n->next = b->next;
+ n->page = b->page - npages;
+ *prev = n;
+ break;
+ }
+
+ if (b->page == npages)
+ {
+ /* this node fit, remove this node */
+ *prev = b->next;
+ break;
+ }
+ }
+
+ return b;
+}
+
+/**
+ * @brief Free memory by page.
+ *
+ * @param slab the slab memory management object.
+ *
+ * @param addr is the head address of first page.
+ *
+ * @param npages is the number of pages.
+ */
+void rt_slab_page_free(rt_slab_t m, void *addr, rt_size_t npages)
+{
+ struct rt_slab_page *b, *n;
+ struct rt_slab_page **prev;
+ struct rt_slab *slab = (struct rt_slab *)m;
+
+ RT_ASSERT(addr != RT_NULL);
+ RT_ASSERT((rt_ubase_t)addr % RT_MM_PAGE_SIZE == 0);
+ RT_ASSERT(npages != 0);
+
+ n = (struct rt_slab_page *)addr;
+
+ for (prev = &slab->page_list; (b = *prev) != RT_NULL; prev = &(b->next))
+ {
+ RT_ASSERT(b->page > 0);
+ RT_ASSERT(b > n || b + b->page <= n);
+
+ if (b + b->page == n)
+ {
+ if (b + (b->page += npages) == b->next)
+ {
+ b->page += b->next->page;
+ b->next = b->next->next;
+ }
+ return;
+ }
+
+ if (b == n + npages)
+ {
+ n->page = b->page + npages;
+ n->next = b->next;
+ *prev = n;
+ return;
+ }
+
+ if (b > n + npages)
+ break;
+ }
+
+ n->page = npages;
+ n->next = b;
+ *prev = n;
+}
+
+/*
+ * Initialize the page allocator
+ */
+static void rt_slab_page_init(struct rt_slab *slab, void *addr, rt_size_t npages)
+{
+ RT_ASSERT(addr != RT_NULL);
+ RT_ASSERT(npages != 0);
+
+ slab->page_list = RT_NULL;
+ rt_slab_page_free((rt_slab_t)(&slab->parent), addr, npages);
+}
+
+/**
+ * @brief This function will init slab memory management algorithm
+ *
+ * @param slab the slab memory management object.
+ *
+ * @param name is the name of the slab memory management object.
+ *
+ * @param begin_addr the beginning address of system page.
+ *
+ * @param size is the size of the memory.
+ *
+ * @return Return a pointer to the slab memory object.
+ */
+rt_slab_t rt_slab_init(const char *name, void *begin_addr, rt_size_t size)
+{
+ rt_uint32_t limsize, npages;
+ rt_ubase_t start_addr, begin_align, end_align;
+ struct rt_slab *slab;
+
+ slab = (struct rt_slab *)RT_ALIGN((rt_ubase_t)begin_addr, RT_ALIGN_SIZE);
+ start_addr = (rt_ubase_t)slab + sizeof(*slab);
+ /* align begin and end addr to page */
+ begin_align = RT_ALIGN((rt_ubase_t)start_addr, RT_MM_PAGE_SIZE);
+ end_align = RT_ALIGN_DOWN((rt_ubase_t)begin_addr + size, RT_MM_PAGE_SIZE);
+ if (begin_align >= end_align)
+ {
+ rt_kprintf("slab init errr. wrong address[0x%x - 0x%x]\n",
+ (rt_ubase_t)begin_addr, (rt_ubase_t)begin_addr + size);
+ return RT_NULL;
+ }
+
+ limsize = end_align - begin_align;
+ npages = limsize / RT_MM_PAGE_SIZE;
+ RT_DEBUG_LOG(RT_DEBUG_SLAB, ("heap[0x%x - 0x%x], size 0x%x, 0x%x pages\n",
+ begin_align, end_align, limsize, npages));
+
+ rt_memset(slab, 0, sizeof(*slab));
+ /* initialize slab memory object */
+ rt_object_init(&(slab->parent.parent), RT_Object_Class_Memory, name);
+ slab->parent.algorithm = "slab";
+ slab->parent.address = begin_align;
+ slab->parent.total = limsize;
+ slab->parent.used = 0;
+ slab->parent.max = 0;
+ slab->heap_start = begin_align;
+ slab->heap_end = end_align;
+
+ /* init pages */
+ rt_slab_page_init(slab, (void *)slab->heap_start, npages);
+
+ /* calculate zone size */
+ slab->zone_size = ZALLOC_MIN_ZONE_SIZE;
+ while (slab->zone_size < ZALLOC_MAX_ZONE_SIZE && (slab->zone_size << 1) < (limsize / 1024))
+ slab->zone_size <<= 1;
+
+ slab->zone_limit = slab->zone_size / 4;
+ if (slab->zone_limit > ZALLOC_ZONE_LIMIT)
+ slab->zone_limit = ZALLOC_ZONE_LIMIT;
+
+ slab->zone_page_cnt = slab->zone_size / RT_MM_PAGE_SIZE;
+
+ RT_DEBUG_LOG(RT_DEBUG_SLAB, ("zone size 0x%x, zone page count 0x%x\n",
+ slab->zone_size, slab->zone_page_cnt));
+
+ /* allocate slab->memusage array */
+ limsize = npages * sizeof(struct rt_slab_memusage);
+ limsize = RT_ALIGN(limsize, RT_MM_PAGE_SIZE);
+ slab->memusage = rt_slab_page_alloc((rt_slab_t)(&slab->parent), limsize / RT_MM_PAGE_SIZE);
+
+ RT_DEBUG_LOG(RT_DEBUG_SLAB, ("slab->memusage 0x%x, size 0x%x\n",
+ (rt_ubase_t)slab->memusage, limsize));
+ return &slab->parent;
+}
+RTM_EXPORT(rt_slab_init);
+
+/**
+ * @brief This function will remove a slab object from the system.
+ *
+ * @param m the slab memory management object.
+ *
+ * @return RT_EOK
+ */
+rt_err_t rt_slab_detach(rt_slab_t m)
+{
+ struct rt_slab *slab = (struct rt_slab *)m;
+
+ RT_ASSERT(slab != RT_NULL);
+ RT_ASSERT(rt_object_get_type(&slab->parent.parent) == RT_Object_Class_Memory);
+ RT_ASSERT(rt_object_is_systemobject(&slab->parent.parent));
+
+ rt_object_detach(&(slab->parent.parent));
+
+ return RT_EOK;
+}
+RTM_EXPORT(rt_slab_detach);
+
+/*
+ * Calculate the zone index for the allocation request size and set the
+ * allocation request size to that particular zone's chunk size.
+ */
+rt_inline int zoneindex(rt_size_t *bytes)
+{
+ /* unsigned for shift opt */
+ rt_ubase_t n = (rt_ubase_t)(*bytes);
+
+ if (n < 128)
+ {
+ *bytes = n = (n + 7) & ~7;
+
+ /* 8 byte chunks, 16 zones */
+ return (n / 8 - 1);
+ }
+ if (n < 256)
+ {
+ *bytes = n = (n + 15) & ~15;
+
+ return (n / 16 + 7);
+ }
+ if (n < 8192)
+ {
+ if (n < 512)
+ {
+ *bytes = n = (n + 31) & ~31;
+
+ return (n / 32 + 15);
+ }
+ if (n < 1024)
+ {
+ *bytes = n = (n + 63) & ~63;
+
+ return (n / 64 + 23);
+ }
+ if (n < 2048)
+ {
+ *bytes = n = (n + 127) & ~127;
+
+ return (n / 128 + 31);
+ }
+ if (n < 4096)
+ {
+ *bytes = n = (n + 255) & ~255;
+
+ return (n / 256 + 39);
+ }
+ *bytes = n = (n + 511) & ~511;
+
+ return (n / 512 + 47);
+ }
+ if (n < 16384)
+ {
+ *bytes = n = (n + 1023) & ~1023;
+
+ return (n / 1024 + 55);
+ }
+
+ rt_kprintf("Unexpected byte count %d", n);
+
+ return 0;
+}
+
+/**
+ * @addtogroup MM
+ */
+
+/**@{*/
+
+/**
+ * @brief This function will allocate a block from slab object.
+ *
+ * @note the RT_NULL is returned if
+ * - the nbytes is less than zero.
+ * - there is no nbytes sized memory valid in system.
+ *
+ * @param m the slab memory management object.
+ *
+ * @param size is the size of memory to be allocated.
+ *
+ * @return the allocated memory.
+ */
+void *rt_slab_alloc(rt_slab_t m, rt_size_t size)
+{
+ struct rt_slab_zone *z;
+ rt_int32_t zi;
+ struct rt_slab_chunk *chunk;
+ struct rt_slab_memusage *kup;
+ struct rt_slab *slab = (struct rt_slab *)m;
+
+ /* zero size, return RT_NULL */
+ if (size == 0)
+ return RT_NULL;
+
+ /*
+ * Handle large allocations directly. There should not be very many of
+ * these so performance is not a big issue.
+ */
+ if (size >= slab->zone_limit)
+ {
+ size = RT_ALIGN(size, RT_MM_PAGE_SIZE);
+
+ chunk = rt_slab_page_alloc(m, size >> RT_MM_PAGE_BITS);
+ if (chunk == RT_NULL)
+ return RT_NULL;
+
+ /* set kup */
+ kup = btokup(chunk);
+ kup->type = PAGE_TYPE_LARGE;
+ kup->size = size >> RT_MM_PAGE_BITS;
+
+ RT_DEBUG_LOG(RT_DEBUG_SLAB,
+ ("alloc a large memory 0x%x, page cnt %d, kup %d\n",
+ size,
+ size >> RT_MM_PAGE_BITS,
+ ((rt_ubase_t)chunk - slab->heap_start) >> RT_MM_PAGE_BITS));
+ /* mem stat */
+ slab->parent.used += size;
+ if (slab->parent.used > slab->parent.max)
+ slab->parent.max = slab->parent.used;
+ return chunk;
+ }
+
+ /*
+ * Attempt to allocate out of an existing zone. First try the free list,
+ * then allocate out of unallocated space. If we find a good zone move
+ * it to the head of the list so later allocations find it quickly
+ * (we might have thousands of zones in the list).
+ *
+ * Note: zoneindex() will panic of size is too large.
+ */
+ zi = zoneindex(&size);
+ RT_ASSERT(zi < RT_SLAB_NZONES);
+
+ RT_DEBUG_LOG(RT_DEBUG_SLAB, ("try to alloc 0x%x on zone: %d\n", size, zi));
+
+ if ((z = slab->zone_array[zi]) != RT_NULL)
+ {
+ RT_ASSERT(z->z_nfree > 0);
+
+ /* Remove us from the zone_array[] when we become full */
+ if (--z->z_nfree == 0)
+ {
+ slab->zone_array[zi] = z->z_next;
+ z->z_next = RT_NULL;
+ }
+
+ /*
+ * No chunks are available but nfree said we had some memory, so
+ * it must be available in the never-before-used-memory area
+ * governed by uindex. The consequences are very serious if our zone
+ * got corrupted so we use an explicit rt_kprintf rather then a KASSERT.
+ */
+ if (z->z_uindex + 1 != z->z_nmax)
+ {
+ z->z_uindex = z->z_uindex + 1;
+ chunk = (struct rt_slab_chunk *)(z->z_baseptr + z->z_uindex * size);
+ }
+ else
+ {
+ /* find on free chunk list */
+ chunk = z->z_freechunk;
+
+ /* remove this chunk from list */
+ z->z_freechunk = z->z_freechunk->c_next;
+ }
+ /* mem stats */
+ slab->parent.used += z->z_chunksize;
+ if (slab->parent.used > slab->parent.max)
+ slab->parent.max = slab->parent.used;
+
+ return chunk;
+ }
+
+ /*
+ * If all zones are exhausted we need to allocate a new zone for this
+ * index.
+ *
+ * At least one subsystem, the tty code (see CROUND) expects power-of-2
+ * allocations to be power-of-2 aligned. We maintain compatibility by
+ * adjusting the base offset below.
+ */
+ {
+ rt_uint32_t off;
+
+ if ((z = slab->zone_free) != RT_NULL)
+ {
+ /* remove zone from free zone list */
+ slab->zone_free = z->z_next;
+ -- slab->zone_free_cnt;
+ }
+ else
+ {
+ /* allocate a zone from page */
+ z = rt_slab_page_alloc(m, slab->zone_size / RT_MM_PAGE_SIZE);
+ if (z == RT_NULL)
+ {
+ return RT_NULL;
+ }
+
+ RT_DEBUG_LOG(RT_DEBUG_SLAB, ("alloc a new zone: 0x%x\n",
+ (rt_ubase_t)z));
+
+ /* set message usage */
+ for (off = 0, kup = btokup(z); off < slab->zone_page_cnt; off ++)
+ {
+ kup->type = PAGE_TYPE_SMALL;
+ kup->size = off;
+
+ kup ++;
+ }
+ }
+
+ /* clear to zero */
+ rt_memset(z, 0, sizeof(struct rt_slab_zone));
+
+ /* offset of slab zone struct in zone */
+ off = sizeof(struct rt_slab_zone);
+
+ /*
+ * Guarentee power-of-2 alignment for power-of-2-sized chunks.
+ * Otherwise just 8-byte align the data.
+ */
+ if ((size | (size - 1)) + 1 == (size << 1))
+ off = (off + size - 1) & ~(size - 1);
+ else
+ off = (off + MIN_CHUNK_MASK) & ~MIN_CHUNK_MASK;
+
+ z->z_magic = ZALLOC_SLAB_MAGIC;
+ z->z_zoneindex = zi;
+ z->z_nmax = (slab->zone_size - off) / size;
+ z->z_nfree = z->z_nmax - 1;
+ z->z_baseptr = (rt_uint8_t *)z + off;
+ z->z_uindex = 0;
+ z->z_chunksize = size;
+
+ chunk = (struct rt_slab_chunk *)(z->z_baseptr + z->z_uindex * size);
+
+ /* link to zone array */
+ z->z_next = slab->zone_array[zi];
+ slab->zone_array[zi] = z;
+ /* mem stats */
+ slab->parent.used += z->z_chunksize;
+ if (slab->parent.used > slab->parent.max)
+ slab->parent.max = slab->parent.used;
+ }
+
+ return chunk;
+}
+RTM_EXPORT(rt_slab_alloc);
+
+/**
+ * @brief This function will change the size of previously allocated memory block.
+ *
+ * @param m the slab memory management object.
+ *
+ * @param ptr is the previously allocated memory block.
+ *
+ * @param size is the new size of memory block.
+ *
+ * @return the allocated memory.
+ */
+void *rt_slab_realloc(rt_slab_t m, void *ptr, rt_size_t size)
+{
+ void *nptr;
+ struct rt_slab_zone *z;
+ struct rt_slab_memusage *kup;
+ struct rt_slab *slab = (struct rt_slab *)m;
+
+ if (ptr == RT_NULL)
+ return rt_slab_alloc(m, size);
+
+ if (size == 0)
+ {
+ rt_slab_free(m, ptr);
+ return RT_NULL;
+ }
+
+ /*
+ * Get the original allocation's zone. If the new request winds up
+ * using the same chunk size we do not have to do anything.
+ */
+ kup = btokup((rt_ubase_t)ptr & ~RT_MM_PAGE_MASK);
+ if (kup->type == PAGE_TYPE_LARGE)
+ {
+ rt_size_t osize;
+
+ osize = kup->size << RT_MM_PAGE_BITS;
+ if ((nptr = rt_slab_alloc(m, size)) == RT_NULL)
+ return RT_NULL;
+ rt_memcpy(nptr, ptr, size > osize ? osize : size);
+ rt_slab_free(m, ptr);
+
+ return nptr;
+ }
+ else if (kup->type == PAGE_TYPE_SMALL)
+ {
+ z = (struct rt_slab_zone *)(((rt_ubase_t)ptr & ~RT_MM_PAGE_MASK) -
+ kup->size * RT_MM_PAGE_SIZE);
+ RT_ASSERT(z->z_magic == ZALLOC_SLAB_MAGIC);
+
+ zoneindex(&size);
+ if (z->z_chunksize == size)
+ return (ptr); /* same chunk */
+
+ /*
+ * Allocate memory for the new request size. Note that zoneindex has
+ * already adjusted the request size to the appropriate chunk size, which
+ * should optimize our bcopy(). Then copy and return the new pointer.
+ */
+ if ((nptr = rt_slab_alloc(m, size)) == RT_NULL)
+ return RT_NULL;
+
+ rt_memcpy(nptr, ptr, size > z->z_chunksize ? z->z_chunksize : size);
+ rt_slab_free(m, ptr);
+
+ return nptr;
+ }
+
+ return RT_NULL;
+}
+RTM_EXPORT(rt_slab_realloc);
+
+/**
+ * @brief This function will release the previous allocated memory block by rt_slab_alloc.
+ *
+ * @note The released memory block is taken back to system heap.
+ *
+ * @param m the slab memory management object.
+ * @param ptr is the address of memory which will be released
+ */
+void rt_slab_free(rt_slab_t m, void *ptr)
+{
+ struct rt_slab_zone *z;
+ struct rt_slab_chunk *chunk;
+ struct rt_slab_memusage *kup;
+ struct rt_slab *slab = (struct rt_slab *)m;
+
+ /* free a RT_NULL pointer */
+ if (ptr == RT_NULL)
+ return ;
+
+ /* get memory usage */
+#if RT_DEBUG_SLAB
+ {
+ rt_ubase_t addr = ((rt_ubase_t)ptr & ~RT_MM_PAGE_MASK);
+ RT_DEBUG_LOG(RT_DEBUG_SLAB,
+ ("free a memory 0x%x and align to 0x%x, kup index %d\n",
+ (rt_ubase_t)ptr,
+ (rt_ubase_t)addr,
+ ((rt_ubase_t)(addr) - slab->heap_start) >> RT_MM_PAGE_BITS));
+ }
+#endif /* RT_DEBUG_SLAB */
+
+ kup = btokup((rt_ubase_t)ptr & ~RT_MM_PAGE_MASK);
+ /* release large allocation */
+ if (kup->type == PAGE_TYPE_LARGE)
+ {
+ rt_ubase_t size;
+
+ /* clear page counter */
+ size = kup->size;
+ kup->size = 0;
+ /* mem stats */
+ slab->parent.used -= size * RT_MM_PAGE_SIZE;
+
+ RT_DEBUG_LOG(RT_DEBUG_SLAB,
+ ("free large memory block 0x%x, page count %d\n",
+ (rt_ubase_t)ptr, size));
+
+ /* free this page */
+ rt_slab_page_free(m, ptr, size);
+
+ return;
+ }
+
+ /* zone case. get out zone. */
+ z = (struct rt_slab_zone *)(((rt_ubase_t)ptr & ~RT_MM_PAGE_MASK) -
+ kup->size * RT_MM_PAGE_SIZE);
+ RT_ASSERT(z->z_magic == ZALLOC_SLAB_MAGIC);
+
+ chunk = (struct rt_slab_chunk *)ptr;
+ chunk->c_next = z->z_freechunk;
+ z->z_freechunk = chunk;
+ /* mem stats */
+ slab->parent.used -= z->z_chunksize;
+
+ /*
+ * Bump the number of free chunks. If it becomes non-zero the zone
+ * must be added back onto the appropriate list.
+ */
+ if (z->z_nfree++ == 0)
+ {
+ z->z_next = slab->zone_array[z->z_zoneindex];
+ slab->zone_array[z->z_zoneindex] = z;
+ }
+
+ /*
+ * If the zone becomes totally free, and there are other zones we
+ * can allocate from, move this zone to the FreeZones list. Since
+ * this code can be called from an IPI callback, do *NOT* try to mess
+ * with kernel_map here. Hysteresis will be performed at malloc() time.
+ */
+ if (z->z_nfree == z->z_nmax &&
+ (z->z_next || slab->zone_array[z->z_zoneindex] != z))
+ {
+ struct rt_slab_zone **pz;
+
+ RT_DEBUG_LOG(RT_DEBUG_SLAB, ("free zone 0x%x\n",
+ (rt_ubase_t)z, z->z_zoneindex));
+
+ /* remove zone from zone array list */
+ for (pz = &slab->zone_array[z->z_zoneindex]; z != *pz; pz = &(*pz)->z_next)
+ ;
+ *pz = z->z_next;
+
+ /* reset zone */
+ z->z_magic = RT_UINT32_MAX;
+
+ /* insert to free zone list */
+ z->z_next = slab->zone_free;
+ slab->zone_free = z;
+
+ ++ slab->zone_free_cnt;
+
+ /* release zone to page allocator */
+ if (slab->zone_free_cnt > ZONE_RELEASE_THRESH)
+ {
+ register rt_uint32_t i;
+
+ z = slab->zone_free;
+ slab->zone_free = z->z_next;
+ -- slab->zone_free_cnt;
+
+ /* set message usage */
+ for (i = 0, kup = btokup(z); i < slab->zone_page_cnt; i ++)
+ {
+ kup->type = PAGE_TYPE_FREE;
+ kup->size = 0;
+ kup ++;
+ }
+
+ /* release pages */
+ rt_slab_page_free(m, z, slab->zone_size / RT_MM_PAGE_SIZE);
+
+ return;
+ }
+ }
+}
+RTM_EXPORT(rt_slab_free);
+
+#endif /* defined (RT_USING_SLAB) */
diff --git a/User/system/rt-thread/src/thread.c b/User/system/rt-thread/src/thread.c
new file mode 100644
index 0000000..f840fdd
--- /dev/null
+++ b/User/system/rt-thread/src/thread.c
@@ -0,0 +1,939 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2006-03-28 Bernard first version
+ * 2006-04-29 Bernard implement thread timer
+ * 2006-04-30 Bernard added THREAD_DEBUG
+ * 2006-05-27 Bernard fixed the rt_thread_yield bug
+ * 2006-06-03 Bernard fixed the thread timer init bug
+ * 2006-08-10 Bernard fixed the timer bug in thread_sleep
+ * 2006-09-03 Bernard changed rt_timer_delete to rt_timer_detach
+ * 2006-09-03 Bernard implement rt_thread_detach
+ * 2008-02-16 Bernard fixed the rt_thread_timeout bug
+ * 2010-03-21 Bernard change the errno of rt_thread_delay/sleep to
+ * RT_EOK.
+ * 2010-11-10 Bernard add cleanup callback function in thread exit.
+ * 2011-09-01 Bernard fixed rt_thread_exit issue when the current
+ * thread preempted, which reported by Jiaxing Lee.
+ * 2011-09-08 Bernard fixed the scheduling issue in rt_thread_startup.
+ * 2012-12-29 Bernard fixed compiling warning.
+ * 2016-08-09 ArdaFu add thread suspend and resume hook.
+ * 2017-04-10 armink fixed the rt_thread_delete and rt_thread_detach
+ * bug when thread has not startup.
+ * 2018-11-22 Jesven yield is same to rt_schedule
+ * add support for tasks bound to cpu
+ * 2021-02-24 Meco Man rearrange rt_thread_control() - schedule the thread when close it
+ * 2021-11-15 THEWON Remove duplicate work between idle and _thread_exit
+ * 2021-12-27 Meco Man remove .init_priority
+ * 2022-01-07 Gabriel Moving __on_rt_xxxxx_hook to thread.c
+ * 2022-01-24 THEWON let rt_thread_sleep return thread->error when using signal
+ */
+
+#include
+#include
+#include
+
+#ifndef __on_rt_thread_inited_hook
+ #define __on_rt_thread_inited_hook(thread) __ON_HOOK_ARGS(rt_thread_inited_hook, (thread))
+#endif
+#ifndef __on_rt_thread_suspend_hook
+ #define __on_rt_thread_suspend_hook(thread) __ON_HOOK_ARGS(rt_thread_suspend_hook, (thread))
+#endif
+#ifndef __on_rt_thread_resume_hook
+ #define __on_rt_thread_resume_hook(thread) __ON_HOOK_ARGS(rt_thread_resume_hook, (thread))
+#endif
+
+#if defined(RT_USING_HOOK) && defined(RT_HOOK_USING_FUNC_PTR)
+static void (*rt_thread_suspend_hook)(rt_thread_t thread);
+static void (*rt_thread_resume_hook) (rt_thread_t thread);
+static void (*rt_thread_inited_hook) (rt_thread_t thread);
+
+/**
+ * @brief This function sets a hook function when the system suspend a thread.
+ *
+ * @note The hook function must be simple and never be blocked or suspend.
+ *
+ * @param hook is the specified hook function.
+ */
+void rt_thread_suspend_sethook(void (*hook)(rt_thread_t thread))
+{
+ rt_thread_suspend_hook = hook;
+}
+
+/**
+ * @brief This function sets a hook function when the system resume a thread.
+ *
+ * @note The hook function must be simple and never be blocked or suspend.
+ *
+ * @param hook is the specified hook function.
+ */
+void rt_thread_resume_sethook(void (*hook)(rt_thread_t thread))
+{
+ rt_thread_resume_hook = hook;
+}
+
+/**
+ * @brief This function sets a hook function when a thread is initialized.
+ *
+ * @param hook is the specified hook function.
+ */
+void rt_thread_inited_sethook(void (*hook)(rt_thread_t thread))
+{
+ rt_thread_inited_hook = hook;
+}
+#endif /* defined(RT_USING_HOOK) && defined(RT_HOOK_USING_FUNC_PTR) */
+
+static void _thread_exit(void)
+{
+ struct rt_thread *thread;
+ rt_base_t level;
+
+ /* get current thread */
+ thread = rt_thread_self();
+
+ /* disable interrupt */
+ level = rt_hw_interrupt_disable();
+
+ /* remove from schedule */
+ rt_schedule_remove_thread(thread);
+
+ /* remove it from timer list */
+ rt_timer_detach(&thread->thread_timer);
+
+ /* change stat */
+ thread->stat = RT_THREAD_CLOSE;
+
+ /* insert to defunct thread list */
+ rt_thread_defunct_enqueue(thread);
+
+ /* enable interrupt */
+ rt_hw_interrupt_enable(level);
+
+ /* switch to next task */
+ rt_schedule();
+}
+
+/**
+ * @brief This function is the timeout function for thread, normally which is invoked
+ * when thread is timeout to wait some resource.
+ *
+ * @param parameter is the parameter of thread timeout function
+ */
+static void _thread_timeout(void *parameter)
+{
+ struct rt_thread *thread;
+ rt_base_t level;
+
+ thread = (struct rt_thread *)parameter;
+
+ /* parameter check */
+ RT_ASSERT(thread != RT_NULL);
+ RT_ASSERT((thread->stat & RT_THREAD_STAT_MASK) == RT_THREAD_SUSPEND);
+ RT_ASSERT(rt_object_get_type((rt_object_t)thread) == RT_Object_Class_Thread);
+
+ /* disable interrupt */
+ level = rt_hw_interrupt_disable();
+
+ /* set error number */
+ thread->error = -RT_ETIMEOUT;
+
+ /* remove from suspend list */
+ rt_list_remove(&(thread->tlist));
+
+ /* insert to schedule ready list */
+ rt_schedule_insert_thread(thread);
+
+ /* enable interrupt */
+ rt_hw_interrupt_enable(level);
+
+ /* do schedule */
+ rt_schedule();
+}
+
+static rt_err_t _thread_init(struct rt_thread *thread,
+ const char *name,
+ void (*entry)(void *parameter),
+ void *parameter,
+ void *stack_start,
+ rt_uint32_t stack_size,
+ rt_uint8_t priority,
+ rt_uint32_t tick)
+{
+ /* init thread list */
+ rt_list_init(&(thread->tlist));
+
+ thread->entry = (void *)entry;
+ thread->parameter = parameter;
+
+ /* stack init */
+ thread->stack_addr = stack_start;
+ thread->stack_size = stack_size;
+
+ /* init thread stack */
+ rt_memset(thread->stack_addr, '#', thread->stack_size);
+#ifdef ARCH_CPU_STACK_GROWS_UPWARD
+ thread->sp = (void *)rt_hw_stack_init(thread->entry, thread->parameter,
+ (void *)((char *)thread->stack_addr),
+ (void *)_thread_exit);
+#else
+ thread->sp = (void *)rt_hw_stack_init(thread->entry, thread->parameter,
+ (rt_uint8_t *)((char *)thread->stack_addr + thread->stack_size - sizeof(rt_ubase_t)),
+ (void *)_thread_exit);
+#endif /* ARCH_CPU_STACK_GROWS_UPWARD */
+
+ /* priority init */
+ RT_ASSERT(priority < RT_THREAD_PRIORITY_MAX);
+ thread->current_priority = priority;
+
+ thread->number_mask = 0;
+
+#ifdef RT_USING_EVENT
+ thread->event_set = 0;
+ thread->event_info = 0;
+#endif /* RT_USING_EVENT */
+
+#if RT_THREAD_PRIORITY_MAX > 32
+ thread->number = 0;
+ thread->high_mask = 0;
+#endif /* RT_THREAD_PRIORITY_MAX > 32 */
+
+ /* tick init */
+ thread->init_tick = tick;
+ thread->remaining_tick = tick;
+
+ /* error and flags */
+ thread->error = RT_EOK;
+ thread->stat = RT_THREAD_INIT;
+
+#ifdef RT_USING_SMP
+ /* not bind on any cpu */
+ thread->bind_cpu = RT_CPUS_NR;
+ thread->oncpu = RT_CPU_DETACHED;
+
+ /* lock init */
+ thread->scheduler_lock_nest = 0;
+ thread->cpus_lock_nest = 0;
+ thread->critical_lock_nest = 0;
+#endif /* RT_USING_SMP */
+
+ /* initialize cleanup function and user data */
+ thread->cleanup = 0;
+ thread->user_data = 0;
+
+ /* initialize thread timer */
+ rt_timer_init(&(thread->thread_timer),
+ thread->name,
+ _thread_timeout,
+ thread,
+ 0,
+ RT_TIMER_FLAG_ONE_SHOT);
+
+ /* initialize signal */
+#ifdef RT_USING_SIGNALS
+ thread->sig_mask = 0x00;
+ thread->sig_pending = 0x00;
+
+#ifndef RT_USING_SMP
+ thread->sig_ret = RT_NULL;
+#endif /* RT_USING_SMP */
+ thread->sig_vectors = RT_NULL;
+ thread->si_list = RT_NULL;
+#endif /* RT_USING_SIGNALS */
+
+#ifdef RT_USING_LWP
+ thread->lwp = RT_NULL;
+#endif /* RT_USING_LWP */
+
+#ifdef RT_USING_CPU_USAGE
+ thread->duration_tick = 0;
+#endif /* RT_USING_CPU_USAGE */
+
+#ifdef RT_USING_PTHREADS
+ thread->pthread_data = RT_NULL;
+#endif /* RT_USING_PTHREADS */
+
+#ifdef RT_USING_MODULE
+ thread->module_id = 0;
+#endif /* RT_USING_MODULE */
+
+ RT_OBJECT_HOOK_CALL(rt_thread_inited_hook, (thread));
+
+ return RT_EOK;
+}
+
+/**
+ * @addtogroup Thread
+ */
+
+/**@{*/
+
+/**
+ * @brief This function will initialize a thread. It's used to initialize a
+ * static thread object.
+ *
+ * @param thread is the static thread object.
+ *
+ * @param name is the name of thread, which shall be unique.
+ *
+ * @param entry is the entry function of thread.
+ *
+ * @param parameter is the parameter of thread enter function.
+ *
+ * @param stack_start is the start address of thread stack.
+ *
+ * @param stack_size is the size of thread stack.
+ *
+ * @param priority is the priority of thread.
+ *
+ * @param tick is the time slice if there are same priority thread.
+ *
+ * @return Return the operation status. If the return value is RT_EOK, the function is successfully executed.
+ * If the return value is any other values, it means this operation failed.
+ */
+rt_err_t rt_thread_init(struct rt_thread *thread,
+ const char *name,
+ void (*entry)(void *parameter),
+ void *parameter,
+ void *stack_start,
+ rt_uint32_t stack_size,
+ rt_uint8_t priority,
+ rt_uint32_t tick)
+{
+ /* parameter check */
+ RT_ASSERT(thread != RT_NULL);
+ RT_ASSERT(stack_start != RT_NULL);
+
+ /* initialize thread object */
+ rt_object_init((rt_object_t)thread, RT_Object_Class_Thread, name);
+
+ return _thread_init(thread,
+ name,
+ entry,
+ parameter,
+ stack_start,
+ stack_size,
+ priority,
+ tick);
+}
+RTM_EXPORT(rt_thread_init);
+
+/**
+ * @brief This function will return self thread object.
+ *
+ * @return The self thread object.
+ */
+rt_thread_t rt_thread_self(void)
+{
+#ifdef RT_USING_SMP
+ rt_base_t lock;
+ rt_thread_t self;
+
+ lock = rt_hw_local_irq_disable();
+ self = rt_cpu_self()->current_thread;
+ rt_hw_local_irq_enable(lock);
+ return self;
+#else
+ extern rt_thread_t rt_current_thread;
+
+ return rt_current_thread;
+#endif /* RT_USING_SMP */
+}
+RTM_EXPORT(rt_thread_self);
+
+/**
+ * @brief This function will start a thread and put it to system ready queue.
+ *
+ * @param thread is the thread to be started.
+ *
+ * @return Return the operation status. If the return value is RT_EOK, the function is successfully executed.
+ * If the return value is any other values, it means this operation failed.
+ */
+rt_err_t rt_thread_startup(rt_thread_t thread)
+{
+ /* parameter check */
+ RT_ASSERT(thread != RT_NULL);
+ RT_ASSERT((thread->stat & RT_THREAD_STAT_MASK) == RT_THREAD_INIT);
+ RT_ASSERT(rt_object_get_type((rt_object_t)thread) == RT_Object_Class_Thread);
+
+ /* calculate priority attribute */
+#if RT_THREAD_PRIORITY_MAX > 32
+ thread->number = thread->current_priority >> 3; /* 5bit */
+ thread->number_mask = 1L << thread->number;
+ thread->high_mask = 1L << (thread->current_priority & 0x07); /* 3bit */
+#else
+ thread->number_mask = 1L << thread->current_priority;
+#endif /* RT_THREAD_PRIORITY_MAX > 32 */
+
+ RT_DEBUG_LOG(RT_DEBUG_THREAD, ("startup a thread:%s with priority:%d\n",
+ thread->name, thread->current_priority));
+ /* change thread stat */
+ thread->stat = RT_THREAD_SUSPEND;
+ /* then resume it */
+ rt_thread_resume(thread);
+ if (rt_thread_self() != RT_NULL)
+ {
+ /* do a scheduling */
+ rt_schedule();
+ }
+
+ return RT_EOK;
+}
+RTM_EXPORT(rt_thread_startup);
+
+/**
+ * @brief This function will detach a thread. The thread object will be removed from
+ * thread queue and detached/deleted from the system object management.
+ *
+ * @param thread is the thread to be deleted.
+ *
+ * @return Return the operation status. If the return value is RT_EOK, the function is successfully executed.
+ * If the return value is any other values, it means this operation failed.
+ */
+rt_err_t rt_thread_detach(rt_thread_t thread)
+{
+ rt_base_t level;
+
+ /* parameter check */
+ RT_ASSERT(thread != RT_NULL);
+ RT_ASSERT(rt_object_get_type((rt_object_t)thread) == RT_Object_Class_Thread);
+ RT_ASSERT(rt_object_is_systemobject((rt_object_t)thread));
+
+ if ((thread->stat & RT_THREAD_STAT_MASK) == RT_THREAD_CLOSE)
+ return RT_EOK;
+
+ if ((thread->stat & RT_THREAD_STAT_MASK) != RT_THREAD_INIT)
+ {
+ /* remove from schedule */
+ rt_schedule_remove_thread(thread);
+ }
+
+ /* disable interrupt */
+ level = rt_hw_interrupt_disable();
+
+ /* release thread timer */
+ rt_timer_detach(&(thread->thread_timer));
+
+ /* change stat */
+ thread->stat = RT_THREAD_CLOSE;
+
+ /* insert to defunct thread list */
+ rt_thread_defunct_enqueue(thread);
+
+ /* enable interrupt */
+ rt_hw_interrupt_enable(level);
+
+ return RT_EOK;
+}
+RTM_EXPORT(rt_thread_detach);
+
+#ifdef RT_USING_HEAP
+/**
+ * @brief This function will create a thread object and allocate thread object memory.
+ * and stack.
+ *
+ * @param name is the name of thread, which shall be unique.
+ *
+ * @param entry is the entry function of thread.
+ *
+ * @param parameter is the parameter of thread enter function.
+ *
+ * @param stack_size is the size of thread stack.
+ *
+ * @param priority is the priority of thread.
+ *
+ * @param tick is the time slice if there are same priority thread.
+ *
+ * @return If the return value is a rt_thread structure pointer, the function is successfully executed.
+ * If the return value is RT_NULL, it means this operation failed.
+ */
+rt_thread_t rt_thread_create(const char *name,
+ void (*entry)(void *parameter),
+ void *parameter,
+ rt_uint32_t stack_size,
+ rt_uint8_t priority,
+ rt_uint32_t tick)
+{
+ struct rt_thread *thread;
+ void *stack_start;
+
+ thread = (struct rt_thread *)rt_object_allocate(RT_Object_Class_Thread,
+ name);
+ if (thread == RT_NULL)
+ return RT_NULL;
+
+ stack_start = (void *)RT_KERNEL_MALLOC(stack_size);
+ if (stack_start == RT_NULL)
+ {
+ /* allocate stack failure */
+ rt_object_delete((rt_object_t)thread);
+
+ return RT_NULL;
+ }
+
+ _thread_init(thread,
+ name,
+ entry,
+ parameter,
+ stack_start,
+ stack_size,
+ priority,
+ tick);
+
+ return thread;
+}
+RTM_EXPORT(rt_thread_create);
+
+/**
+ * @brief This function will delete a thread. The thread object will be removed from
+ * thread queue and deleted from system object management in the idle thread.
+ *
+ * @param thread is the thread to be deleted.
+ *
+ * @return Return the operation status. If the return value is RT_EOK, the function is successfully executed.
+ * If the return value is any other values, it means this operation failed.
+ */
+rt_err_t rt_thread_delete(rt_thread_t thread)
+{
+ rt_base_t level;
+
+ /* parameter check */
+ RT_ASSERT(thread != RT_NULL);
+ RT_ASSERT(rt_object_get_type((rt_object_t)thread) == RT_Object_Class_Thread);
+ RT_ASSERT(rt_object_is_systemobject((rt_object_t)thread) == RT_FALSE);
+
+ if ((thread->stat & RT_THREAD_STAT_MASK) == RT_THREAD_CLOSE)
+ return RT_EOK;
+
+ if ((thread->stat & RT_THREAD_STAT_MASK) != RT_THREAD_INIT)
+ {
+ /* remove from schedule */
+ rt_schedule_remove_thread(thread);
+ }
+
+ /* disable interrupt */
+ level = rt_hw_interrupt_disable();
+
+ /* release thread timer */
+ rt_timer_detach(&(thread->thread_timer));
+
+ /* change stat */
+ thread->stat = RT_THREAD_CLOSE;
+
+ /* insert to defunct thread list */
+ rt_thread_defunct_enqueue(thread);
+
+ /* enable interrupt */
+ rt_hw_interrupt_enable(level);
+
+ return RT_EOK;
+}
+RTM_EXPORT(rt_thread_delete);
+#endif /* RT_USING_HEAP */
+
+/**
+ * @brief This function will let current thread yield processor, and scheduler will
+ * choose the highest thread to run. After yield processor, the current thread
+ * is still in READY state.
+ *
+ * @return Return the operation status. If the return value is RT_EOK, the function is successfully executed.
+ * If the return value is any other values, it means this operation failed.
+ */
+rt_err_t rt_thread_yield(void)
+{
+ struct rt_thread *thread;
+ rt_base_t level;
+
+ thread = rt_thread_self();
+ level = rt_hw_interrupt_disable();
+ thread->remaining_tick = thread->init_tick;
+ thread->stat |= RT_THREAD_STAT_YIELD;
+ rt_schedule();
+ rt_hw_interrupt_enable(level);
+
+ return RT_EOK;
+}
+RTM_EXPORT(rt_thread_yield);
+
+/**
+ * @brief This function will let current thread sleep for some ticks. Change current thread state to suspend,
+ * when the thread timer reaches the tick value, scheduler will awaken this thread.
+ *
+ * @param tick is the sleep ticks.
+ *
+ * @return Return the operation status. If the return value is RT_EOK, the function is successfully executed.
+ * If the return value is any other values, it means this operation failed.
+ */
+rt_err_t rt_thread_sleep(rt_tick_t tick)
+{
+ rt_base_t level;
+ struct rt_thread *thread;
+
+ /* set to current thread */
+ thread = rt_thread_self();
+ RT_ASSERT(thread != RT_NULL);
+ RT_ASSERT(rt_object_get_type((rt_object_t)thread) == RT_Object_Class_Thread);
+
+ /* disable interrupt */
+ level = rt_hw_interrupt_disable();
+
+ /* reset thread error */
+ thread->error = RT_EOK;
+
+ /* suspend thread */
+ rt_thread_suspend(thread);
+
+ /* reset the timeout of thread timer and start it */
+ rt_timer_control(&(thread->thread_timer), RT_TIMER_CTRL_SET_TIME, &tick);
+ rt_timer_start(&(thread->thread_timer));
+
+ /* enable interrupt */
+ rt_hw_interrupt_enable(level);
+
+ rt_schedule();
+
+ /* clear error number of this thread to RT_EOK */
+ if (thread->error == -RT_ETIMEOUT)
+ thread->error = RT_EOK;
+
+ return thread->error;
+}
+
+/**
+ * @brief This function will let current thread delay for some ticks.
+ *
+ * @param tick is the delay ticks.
+ *
+ * @return Return the operation status. If the return value is RT_EOK, the function is successfully executed.
+ * If the return value is any other values, it means this operation failed.
+ */
+rt_err_t rt_thread_delay(rt_tick_t tick)
+{
+ return rt_thread_sleep(tick);
+}
+RTM_EXPORT(rt_thread_delay);
+
+/**
+ * @brief This function will let current thread delay until (*tick + inc_tick).
+ *
+ * @param tick is the tick of last wakeup.
+ *
+ * @param inc_tick is the increment tick.
+ *
+ * @return Return the operation status. If the return value is RT_EOK, the function is successfully executed.
+ * If the return value is any other values, it means this operation failed.
+ */
+rt_err_t rt_thread_delay_until(rt_tick_t *tick, rt_tick_t inc_tick)
+{
+ rt_base_t level;
+ struct rt_thread *thread;
+ rt_tick_t cur_tick;
+
+ RT_ASSERT(tick != RT_NULL);
+
+ /* set to current thread */
+ thread = rt_thread_self();
+ RT_ASSERT(thread != RT_NULL);
+ RT_ASSERT(rt_object_get_type((rt_object_t)thread) == RT_Object_Class_Thread);
+
+ /* disable interrupt */
+ level = rt_hw_interrupt_disable();
+
+ /* reset thread error */
+ thread->error = RT_EOK;
+
+ cur_tick = rt_tick_get();
+ if (cur_tick - *tick < inc_tick)
+ {
+ rt_tick_t left_tick;
+
+ *tick += inc_tick;
+ left_tick = *tick - cur_tick;
+
+ /* suspend thread */
+ rt_thread_suspend(thread);
+
+ /* reset the timeout of thread timer and start it */
+ rt_timer_control(&(thread->thread_timer), RT_TIMER_CTRL_SET_TIME, &left_tick);
+ rt_timer_start(&(thread->thread_timer));
+
+ /* enable interrupt */
+ rt_hw_interrupt_enable(level);
+
+ rt_schedule();
+
+ /* clear error number of this thread to RT_EOK */
+ if (thread->error == -RT_ETIMEOUT)
+ {
+ thread->error = RT_EOK;
+ }
+ }
+ else
+ {
+ *tick = cur_tick;
+ rt_hw_interrupt_enable(level);
+ }
+
+ return thread->error;
+}
+RTM_EXPORT(rt_thread_delay_until);
+
+/**
+ * @brief This function will let current thread delay for some milliseconds.
+ *
+ * @param ms is the delay ms time.
+ *
+ * @return Return the operation status. If the return value is RT_EOK, the function is successfully executed.
+ * If the return value is any other values, it means this operation failed.
+ */
+rt_err_t rt_thread_mdelay(rt_int32_t ms)
+{
+ rt_tick_t tick;
+
+ tick = rt_tick_from_millisecond(ms);
+
+ return rt_thread_sleep(tick);
+}
+RTM_EXPORT(rt_thread_mdelay);
+
+/**
+ * @brief This function will control thread behaviors according to control command.
+ *
+ * @param thread is the specified thread to be controlled.
+ *
+ * @param cmd is the control command, which includes.
+ *
+ * RT_THREAD_CTRL_CHANGE_PRIORITY for changing priority level of thread.
+ *
+ * RT_THREAD_CTRL_STARTUP for starting a thread.
+ *
+ * RT_THREAD_CTRL_CLOSE for delete a thread.
+ *
+ * RT_THREAD_CTRL_BIND_CPU for bind the thread to a CPU.
+ *
+ * @param arg is the argument of control command.
+ *
+ * @return Return the operation status. If the return value is RT_EOK, the function is successfully executed.
+ * If the return value is any other values, it means this operation failed.
+ */
+rt_err_t rt_thread_control(rt_thread_t thread, int cmd, void *arg)
+{
+ rt_base_t level;
+
+ /* parameter check */
+ RT_ASSERT(thread != RT_NULL);
+ RT_ASSERT(rt_object_get_type((rt_object_t)thread) == RT_Object_Class_Thread);
+
+ switch (cmd)
+ {
+ case RT_THREAD_CTRL_CHANGE_PRIORITY:
+ {
+ /* disable interrupt */
+ level = rt_hw_interrupt_disable();
+
+ /* for ready thread, change queue */
+ if ((thread->stat & RT_THREAD_STAT_MASK) == RT_THREAD_READY)
+ {
+ /* remove thread from schedule queue first */
+ rt_schedule_remove_thread(thread);
+
+ /* change thread priority */
+ thread->current_priority = *(rt_uint8_t *)arg;
+
+ /* recalculate priority attribute */
+ #if RT_THREAD_PRIORITY_MAX > 32
+ thread->number = thread->current_priority >> 3; /* 5bit */
+ thread->number_mask = 1 << thread->number;
+ thread->high_mask = 1 << (thread->current_priority & 0x07); /* 3bit */
+ #else
+ thread->number_mask = 1 << thread->current_priority;
+ #endif /* RT_THREAD_PRIORITY_MAX > 32 */
+
+ /* insert thread to schedule queue again */
+ rt_schedule_insert_thread(thread);
+ }
+ else
+ {
+ thread->current_priority = *(rt_uint8_t *)arg;
+
+ /* recalculate priority attribute */
+ #if RT_THREAD_PRIORITY_MAX > 32
+ thread->number = thread->current_priority >> 3; /* 5bit */
+ thread->number_mask = 1 << thread->number;
+ thread->high_mask = 1 << (thread->current_priority & 0x07); /* 3bit */
+ #else
+ thread->number_mask = 1 << thread->current_priority;
+ #endif /* RT_THREAD_PRIORITY_MAX > 32 */
+ }
+
+ /* enable interrupt */
+ rt_hw_interrupt_enable(level);
+ break;
+ }
+
+ case RT_THREAD_CTRL_STARTUP:
+ {
+ return rt_thread_startup(thread);
+ }
+
+ case RT_THREAD_CTRL_CLOSE:
+ {
+ rt_err_t rt_err;
+
+ if (rt_object_is_systemobject((rt_object_t)thread) == RT_TRUE)
+ {
+ rt_err = rt_thread_detach(thread);
+ }
+ #ifdef RT_USING_HEAP
+ else
+ {
+ rt_err = rt_thread_delete(thread);
+ }
+ #endif /* RT_USING_HEAP */
+ rt_schedule();
+ return rt_err;
+ }
+
+ #ifdef RT_USING_SMP
+ case RT_THREAD_CTRL_BIND_CPU:
+ {
+ rt_uint8_t cpu;
+
+ if ((thread->stat & RT_THREAD_STAT_MASK) != RT_THREAD_INIT)
+ {
+ /* we only support bind cpu before started phase. */
+ return RT_ERROR;
+ }
+
+ cpu = (rt_uint8_t)(rt_size_t)arg;
+ thread->bind_cpu = cpu > RT_CPUS_NR? RT_CPUS_NR : cpu;
+ break;
+ }
+ #endif /* RT_USING_SMP */
+
+ default:
+ break;
+ }
+
+ return RT_EOK;
+}
+RTM_EXPORT(rt_thread_control);
+
+/**
+ * @brief This function will suspend the specified thread and change it to suspend state.
+ *
+ * @note This function ONLY can suspend current thread itself.
+ * rt_thread_suspend(rt_thread_self());
+ *
+ * Do not use the rt_thread_suspend to suspend other threads. You have no way of knowing what code a
+ * thread is executing when you suspend it. If you suspend a thread while sharing a resouce with
+ * other threads and occupying this resouce, starvation can occur very easily.
+ *
+ * @param thread is the thread to be suspended.
+ *
+ * @return Return the operation status. If the return value is RT_EOK, the function is successfully executed.
+ * If the return value is any other values, it means this operation failed.
+ */
+rt_err_t rt_thread_suspend(rt_thread_t thread)
+{
+ rt_base_t stat;
+ rt_base_t level;
+
+ /* parameter check */
+ RT_ASSERT(thread != RT_NULL);
+ RT_ASSERT(rt_object_get_type((rt_object_t)thread) == RT_Object_Class_Thread);
+ RT_ASSERT(thread == rt_thread_self());
+
+ RT_DEBUG_LOG(RT_DEBUG_THREAD, ("thread suspend: %s\n", thread->name));
+
+ stat = thread->stat & RT_THREAD_STAT_MASK;
+ if ((stat != RT_THREAD_READY) && (stat != RT_THREAD_RUNNING))
+ {
+ RT_DEBUG_LOG(RT_DEBUG_THREAD, ("thread suspend: thread disorder, 0x%2x\n", thread->stat));
+ return -RT_ERROR;
+ }
+
+ /* disable interrupt */
+ level = rt_hw_interrupt_disable();
+
+ /* change thread stat */
+ rt_schedule_remove_thread(thread);
+ thread->stat = RT_THREAD_SUSPEND | (thread->stat & ~RT_THREAD_STAT_MASK);
+
+ /* stop thread timer anyway */
+ rt_timer_stop(&(thread->thread_timer));
+
+ /* enable interrupt */
+ rt_hw_interrupt_enable(level);
+
+ RT_OBJECT_HOOK_CALL(rt_thread_suspend_hook, (thread));
+ return RT_EOK;
+}
+RTM_EXPORT(rt_thread_suspend);
+
+/**
+ * @brief This function will resume a thread and put it to system ready queue.
+ *
+ * @param thread is the thread to be resumed.
+ *
+ * @return Return the operation status. If the return value is RT_EOK, the function is successfully executed.
+ * If the return value is any other values, it means this operation failed.
+ */
+rt_err_t rt_thread_resume(rt_thread_t thread)
+{
+ rt_base_t level;
+
+ /* parameter check */
+ RT_ASSERT(thread != RT_NULL);
+ RT_ASSERT(rt_object_get_type((rt_object_t)thread) == RT_Object_Class_Thread);
+
+ RT_DEBUG_LOG(RT_DEBUG_THREAD, ("thread resume: %s\n", thread->name));
+
+ if ((thread->stat & RT_THREAD_STAT_MASK) != RT_THREAD_SUSPEND)
+ {
+ RT_DEBUG_LOG(RT_DEBUG_THREAD, ("thread resume: thread disorder, %d\n",
+ thread->stat));
+
+ return -RT_ERROR;
+ }
+
+ /* disable interrupt */
+ level = rt_hw_interrupt_disable();
+
+ /* remove from suspend list */
+ rt_list_remove(&(thread->tlist));
+
+ rt_timer_stop(&thread->thread_timer);
+
+ /* insert to schedule ready list */
+ rt_schedule_insert_thread(thread);
+
+ /* enable interrupt */
+ rt_hw_interrupt_enable(level);
+
+ RT_OBJECT_HOOK_CALL(rt_thread_resume_hook, (thread));
+ return RT_EOK;
+}
+RTM_EXPORT(rt_thread_resume);
+
+/**
+ * @brief This function will find the specified thread.
+ *
+ * @note Please don't invoke this function in interrupt status.
+ *
+ * @param name is the name of thread finding.
+ *
+ * @return If the return value is a rt_thread structure pointer, the function is successfully executed.
+ * If the return value is RT_NULL, it means this operation failed.
+ */
+rt_thread_t rt_thread_find(char *name)
+{
+ return (rt_thread_t)rt_object_find(name, RT_Object_Class_Thread);
+}
+
+RTM_EXPORT(rt_thread_find);
+
+/**@}*/
diff --git a/User/system/rt-thread/src/timer.c b/User/system/rt-thread/src/timer.c
new file mode 100644
index 0000000..ce11bf3
--- /dev/null
+++ b/User/system/rt-thread/src/timer.c
@@ -0,0 +1,875 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2006-03-12 Bernard first version
+ * 2006-04-29 Bernard implement thread timer
+ * 2006-06-04 Bernard implement rt_timer_control
+ * 2006-08-10 Bernard fix the periodic timer bug
+ * 2006-09-03 Bernard implement rt_timer_detach
+ * 2009-11-11 LiJin add soft timer
+ * 2010-05-12 Bernard fix the timer check bug.
+ * 2010-11-02 Charlie re-implement tick overflow issue
+ * 2012-12-15 Bernard fix the next timeout issue in soft timer
+ * 2014-07-12 Bernard does not lock scheduler when invoking soft-timer
+ * timeout function.
+ * 2021-08-15 supperthomas add the comment
+ * 2022-01-07 Gabriel Moving __on_rt_xxxxx_hook to timer.c
+ * 2022-04-19 Stanley Correct descriptions
+ */
+
+#include
+#include
+
+/* hard timer list */
+static rt_list_t _timer_list[RT_TIMER_SKIP_LIST_LEVEL];
+
+#ifdef RT_USING_TIMER_SOFT
+
+#define RT_SOFT_TIMER_IDLE 1
+#define RT_SOFT_TIMER_BUSY 0
+
+#ifndef RT_TIMER_THREAD_STACK_SIZE
+#define RT_TIMER_THREAD_STACK_SIZE 512
+#endif /* RT_TIMER_THREAD_STACK_SIZE */
+
+#ifndef RT_TIMER_THREAD_PRIO
+#define RT_TIMER_THREAD_PRIO 0
+#endif /* RT_TIMER_THREAD_PRIO */
+
+/* soft timer status */
+static rt_uint8_t _soft_timer_status = RT_SOFT_TIMER_IDLE;
+/* soft timer list */
+static rt_list_t _soft_timer_list[RT_TIMER_SKIP_LIST_LEVEL];
+static struct rt_thread _timer_thread;
+ALIGN(RT_ALIGN_SIZE)
+static rt_uint8_t _timer_thread_stack[RT_TIMER_THREAD_STACK_SIZE];
+#endif /* RT_USING_TIMER_SOFT */
+
+#ifndef __on_rt_object_take_hook
+ #define __on_rt_object_take_hook(parent) __ON_HOOK_ARGS(rt_object_take_hook, (parent))
+#endif
+#ifndef __on_rt_object_put_hook
+ #define __on_rt_object_put_hook(parent) __ON_HOOK_ARGS(rt_object_put_hook, (parent))
+#endif
+#ifndef __on_rt_timer_enter_hook
+ #define __on_rt_timer_enter_hook(t) __ON_HOOK_ARGS(rt_timer_enter_hook, (t))
+#endif
+#ifndef __on_rt_timer_exit_hook
+ #define __on_rt_timer_exit_hook(t) __ON_HOOK_ARGS(rt_timer_exit_hook, (t))
+#endif
+
+#if defined(RT_USING_HOOK) && defined(RT_HOOK_USING_FUNC_PTR)
+extern void (*rt_object_take_hook)(struct rt_object *object);
+extern void (*rt_object_put_hook)(struct rt_object *object);
+static void (*rt_timer_enter_hook)(struct rt_timer *timer);
+static void (*rt_timer_exit_hook)(struct rt_timer *timer);
+
+/**
+ * @addtogroup Hook
+ */
+
+/**@{*/
+
+/**
+ * @brief This function will set a hook function on timer,
+ * which will be invoked when enter timer timeout callback function.
+ *
+ * @param hook is the function point of timer
+ */
+void rt_timer_enter_sethook(void (*hook)(struct rt_timer *timer))
+{
+ rt_timer_enter_hook = hook;
+}
+
+/**
+ * @brief This function will set a hook function, which will be
+ * invoked when exit timer timeout callback function.
+ *
+ * @param hook is the function point of timer
+ */
+void rt_timer_exit_sethook(void (*hook)(struct rt_timer *timer))
+{
+ rt_timer_exit_hook = hook;
+}
+
+/**@}*/
+#endif /* RT_USING_HOOK */
+
+
+/**
+ * @brief [internal] The init funtion of timer
+ *
+ * The internal called function of rt_timer_init
+ *
+ * @see rt_timer_init
+ *
+ * @param timer is timer object
+ *
+ * @param timeout is the timeout function
+ *
+ * @param parameter is the parameter of timeout function
+ *
+ * @param time is the tick of timer
+ *
+ * @param flag the flag of timer
+ */
+static void _timer_init(rt_timer_t timer,
+ void (*timeout)(void *parameter),
+ void *parameter,
+ rt_tick_t time,
+ rt_uint8_t flag)
+{
+ int i;
+
+ /* set flag */
+ timer->parent.flag = flag;
+
+ /* set deactivated */
+ timer->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
+
+ timer->timeout_func = timeout;
+ timer->parameter = parameter;
+
+ timer->timeout_tick = 0;
+ timer->init_tick = time;
+
+ /* initialize timer list */
+ for (i = 0; i < RT_TIMER_SKIP_LIST_LEVEL; i++)
+ {
+ rt_list_init(&(timer->row[i]));
+ }
+}
+
+/**
+ * @brief Find the next emtpy timer ticks
+ *
+ * @param timer_list is the array of time list
+ *
+ * @param timeout_tick is the next timer's ticks
+ *
+ * @return Return the operation status. If the return value is RT_EOK, the function is successfully executed.
+ * If the return value is any other values, it means this operation failed.
+ */
+static rt_err_t _timer_list_next_timeout(rt_list_t timer_list[], rt_tick_t *timeout_tick)
+{
+ struct rt_timer *timer;
+ rt_base_t level;
+
+ /* disable interrupt */
+ level = rt_hw_interrupt_disable();
+
+ if (!rt_list_isempty(&timer_list[RT_TIMER_SKIP_LIST_LEVEL - 1]))
+ {
+ timer = rt_list_entry(timer_list[RT_TIMER_SKIP_LIST_LEVEL - 1].next,
+ struct rt_timer, row[RT_TIMER_SKIP_LIST_LEVEL - 1]);
+ *timeout_tick = timer->timeout_tick;
+
+ /* enable interrupt */
+ rt_hw_interrupt_enable(level);
+
+ return RT_EOK;
+ }
+
+ /* enable interrupt */
+ rt_hw_interrupt_enable(level);
+
+ return -RT_ERROR;
+}
+
+/**
+ * @brief Remove the timer
+ *
+ * @param timer the point of the timer
+ */
+rt_inline void _timer_remove(rt_timer_t timer)
+{
+ int i;
+
+ for (i = 0; i < RT_TIMER_SKIP_LIST_LEVEL; i++)
+ {
+ rt_list_remove(&timer->row[i]);
+ }
+}
+
+#if RT_DEBUG_TIMER
+/**
+ * @brief The number of timer
+ *
+ * @param timer the head of timer
+ *
+ * @return count of timer
+ */
+static int _timer_count_height(struct rt_timer *timer)
+{
+ int i, cnt = 0;
+
+ for (i = 0; i < RT_TIMER_SKIP_LIST_LEVEL; i++)
+ {
+ if (!rt_list_isempty(&timer->row[i]))
+ cnt++;
+ }
+ return cnt;
+}
+/**
+ * @brief dump the all timer information
+ *
+ * @param timer_heads the head of timer
+ */
+void rt_timer_dump(rt_list_t timer_heads[])
+{
+ rt_list_t *list;
+
+ for (list = timer_heads[RT_TIMER_SKIP_LIST_LEVEL - 1].next;
+ list != &timer_heads[RT_TIMER_SKIP_LIST_LEVEL - 1];
+ list = list->next)
+ {
+ struct rt_timer *timer = rt_list_entry(list,
+ struct rt_timer,
+ row[RT_TIMER_SKIP_LIST_LEVEL - 1]);
+ rt_kprintf("%d", _timer_count_height(timer));
+ }
+ rt_kprintf("\n");
+}
+#endif /* RT_DEBUG_TIMER */
+
+/**
+ * @addtogroup Clock
+ */
+
+/**@{*/
+
+/**
+ * @brief This function will initialize a timer
+ * normally this function is used to initialize a static timer object.
+ *
+ * @param timer is the point of timer
+ *
+ * @param name is a pointer to the name of the timer
+ *
+ * @param timeout is the callback of timer
+ *
+ * @param parameter is the param of the callback
+ *
+ * @param time is timeout ticks of timer
+ *
+ * NOTE: The max timeout tick should be no more than (RT_TICK_MAX/2 - 1).
+ *
+ * @param flag is the flag of timer
+ *
+ */
+void rt_timer_init(rt_timer_t timer,
+ const char *name,
+ void (*timeout)(void *parameter),
+ void *parameter,
+ rt_tick_t time,
+ rt_uint8_t flag)
+{
+ /* parameter check */
+ RT_ASSERT(timer != RT_NULL);
+ RT_ASSERT(timeout != RT_NULL);
+ RT_ASSERT(time < RT_TICK_MAX / 2);
+
+ /* timer object initialization */
+ rt_object_init(&(timer->parent), RT_Object_Class_Timer, name);
+
+ _timer_init(timer, timeout, parameter, time, flag);
+}
+RTM_EXPORT(rt_timer_init);
+
+/**
+ * @brief This function will detach a timer from timer management.
+ *
+ * @param timer is the timer to be detached
+ *
+ * @return the status of detach
+ */
+rt_err_t rt_timer_detach(rt_timer_t timer)
+{
+ rt_base_t level;
+
+ /* parameter check */
+ RT_ASSERT(timer != RT_NULL);
+ RT_ASSERT(rt_object_get_type(&timer->parent) == RT_Object_Class_Timer);
+ RT_ASSERT(rt_object_is_systemobject(&timer->parent));
+
+ /* disable interrupt */
+ level = rt_hw_interrupt_disable();
+
+ _timer_remove(timer);
+ /* stop timer */
+ timer->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
+
+ /* enable interrupt */
+ rt_hw_interrupt_enable(level);
+
+ rt_object_detach(&(timer->parent));
+
+ return RT_EOK;
+}
+RTM_EXPORT(rt_timer_detach);
+
+#ifdef RT_USING_HEAP
+/**
+ * @brief This function will create a timer
+ *
+ * @param name is the name of timer
+ *
+ * @param timeout is the timeout function
+ *
+ * @param parameter is the parameter of timeout function
+ *
+ * @param time is timeout ticks of the timer
+ *
+ * NOTE: The max timeout tick should be no more than (RT_TICK_MAX/2 - 1).
+ *
+ * @param flag is the flag of timer. Timer will invoke the timeout function according to the selected values of flag, if one or more of the following flags is set.
+ *
+ * RT_TIMER_FLAG_ONE_SHOT One shot timing
+ * RT_TIMER_FLAG_PERIODIC Periodic timing
+ *
+ * RT_TIMER_FLAG_HARD_TIMER Hardware timer
+ * RT_TIMER_FLAG_SOFT_TIMER Software timer
+ *
+ * NOTE:
+ * You can use multiple values with "|" logical operator. By default, system will use the RT_TIME_FLAG_HARD_TIMER.
+ *
+ * @return the created timer object
+ */
+rt_timer_t rt_timer_create(const char *name,
+ void (*timeout)(void *parameter),
+ void *parameter,
+ rt_tick_t time,
+ rt_uint8_t flag)
+{
+ struct rt_timer *timer;
+
+ /* parameter check */
+ RT_ASSERT(timeout != RT_NULL);
+ RT_ASSERT(time < RT_TICK_MAX / 2);
+
+ /* allocate a object */
+ timer = (struct rt_timer *)rt_object_allocate(RT_Object_Class_Timer, name);
+ if (timer == RT_NULL)
+ {
+ return RT_NULL;
+ }
+
+ _timer_init(timer, timeout, parameter, time, flag);
+
+ return timer;
+}
+RTM_EXPORT(rt_timer_create);
+
+/**
+ * @brief This function will delete a timer and release timer memory
+ *
+ * @param timer the timer to be deleted
+ *
+ * @return the operation status, RT_EOK on OK; RT_ERROR on error
+ */
+rt_err_t rt_timer_delete(rt_timer_t timer)
+{
+ rt_base_t level;
+
+ /* parameter check */
+ RT_ASSERT(timer != RT_NULL);
+ RT_ASSERT(rt_object_get_type(&timer->parent) == RT_Object_Class_Timer);
+ RT_ASSERT(rt_object_is_systemobject(&timer->parent) == RT_FALSE);
+
+ /* disable interrupt */
+ level = rt_hw_interrupt_disable();
+
+ _timer_remove(timer);
+ /* stop timer */
+ timer->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
+
+ /* enable interrupt */
+ rt_hw_interrupt_enable(level);
+
+ rt_object_delete(&(timer->parent));
+
+ return RT_EOK;
+}
+RTM_EXPORT(rt_timer_delete);
+#endif /* RT_USING_HEAP */
+
+/**
+ * @brief This function will start the timer
+ *
+ * @param timer the timer to be started
+ *
+ * @return the operation status, RT_EOK on OK, -RT_ERROR on error
+ */
+rt_err_t rt_timer_start(rt_timer_t timer)
+{
+ unsigned int row_lvl;
+ rt_list_t *timer_list;
+ rt_base_t level;
+ rt_bool_t need_schedule;
+ rt_list_t *row_head[RT_TIMER_SKIP_LIST_LEVEL];
+ unsigned int tst_nr;
+ static unsigned int random_nr;
+
+ /* parameter check */
+ RT_ASSERT(timer != RT_NULL);
+ RT_ASSERT(rt_object_get_type(&timer->parent) == RT_Object_Class_Timer);
+
+ need_schedule = RT_FALSE;
+
+ /* stop timer firstly */
+ level = rt_hw_interrupt_disable();
+ /* remove timer from list */
+ _timer_remove(timer);
+ /* change status of timer */
+ timer->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
+
+ RT_OBJECT_HOOK_CALL(rt_object_take_hook, (&(timer->parent)));
+
+ timer->timeout_tick = rt_tick_get() + timer->init_tick;
+
+#ifdef RT_USING_TIMER_SOFT
+ if (timer->parent.flag & RT_TIMER_FLAG_SOFT_TIMER)
+ {
+ /* insert timer to soft timer list */
+ timer_list = _soft_timer_list;
+ }
+ else
+#endif /* RT_USING_TIMER_SOFT */
+ {
+ /* insert timer to system timer list */
+ timer_list = _timer_list;
+ }
+
+ row_head[0] = &timer_list[0];
+ for (row_lvl = 0; row_lvl < RT_TIMER_SKIP_LIST_LEVEL; row_lvl++)
+ {
+ for (; row_head[row_lvl] != timer_list[row_lvl].prev;
+ row_head[row_lvl] = row_head[row_lvl]->next)
+ {
+ struct rt_timer *t;
+ rt_list_t *p = row_head[row_lvl]->next;
+
+ /* fix up the entry pointer */
+ t = rt_list_entry(p, struct rt_timer, row[row_lvl]);
+
+ /* If we have two timers that timeout at the same time, it's
+ * preferred that the timer inserted early get called early.
+ * So insert the new timer to the end the the some-timeout timer
+ * list.
+ */
+ if ((t->timeout_tick - timer->timeout_tick) == 0)
+ {
+ continue;
+ }
+ else if ((t->timeout_tick - timer->timeout_tick) < RT_TICK_MAX / 2)
+ {
+ break;
+ }
+ }
+ if (row_lvl != RT_TIMER_SKIP_LIST_LEVEL - 1)
+ row_head[row_lvl + 1] = row_head[row_lvl] + 1;
+ }
+
+ /* Interestingly, this super simple timer insert counter works very very
+ * well on distributing the list height uniformly. By means of "very very
+ * well", I mean it beats the randomness of timer->timeout_tick very easily
+ * (actually, the timeout_tick is not random and easy to be attacked). */
+ random_nr++;
+ tst_nr = random_nr;
+
+ rt_list_insert_after(row_head[RT_TIMER_SKIP_LIST_LEVEL - 1],
+ &(timer->row[RT_TIMER_SKIP_LIST_LEVEL - 1]));
+ for (row_lvl = 2; row_lvl <= RT_TIMER_SKIP_LIST_LEVEL; row_lvl++)
+ {
+ if (!(tst_nr & RT_TIMER_SKIP_LIST_MASK))
+ rt_list_insert_after(row_head[RT_TIMER_SKIP_LIST_LEVEL - row_lvl],
+ &(timer->row[RT_TIMER_SKIP_LIST_LEVEL - row_lvl]));
+ else
+ break;
+ /* Shift over the bits we have tested. Works well with 1 bit and 2
+ * bits. */
+ tst_nr >>= (RT_TIMER_SKIP_LIST_MASK + 1) >> 1;
+ }
+
+ timer->parent.flag |= RT_TIMER_FLAG_ACTIVATED;
+
+#ifdef RT_USING_TIMER_SOFT
+ if (timer->parent.flag & RT_TIMER_FLAG_SOFT_TIMER)
+ {
+ /* check whether timer thread is ready */
+ if ((_soft_timer_status == RT_SOFT_TIMER_IDLE) &&
+ ((_timer_thread.stat & RT_THREAD_STAT_MASK) == RT_THREAD_SUSPEND))
+ {
+ /* resume timer thread to check soft timer */
+ rt_thread_resume(&_timer_thread);
+ need_schedule = RT_TRUE;
+ }
+ }
+#endif /* RT_USING_TIMER_SOFT */
+
+ /* enable interrupt */
+ rt_hw_interrupt_enable(level);
+
+ if (need_schedule)
+ {
+ rt_schedule();
+ }
+
+ return RT_EOK;
+}
+RTM_EXPORT(rt_timer_start);
+
+/**
+ * @brief This function will stop the timer
+ *
+ * @param timer the timer to be stopped
+ *
+ * @return the operation status, RT_EOK on OK, -RT_ERROR on error
+ */
+rt_err_t rt_timer_stop(rt_timer_t timer)
+{
+ rt_base_t level;
+
+ /* parameter check */
+ RT_ASSERT(timer != RT_NULL);
+ RT_ASSERT(rt_object_get_type(&timer->parent) == RT_Object_Class_Timer);
+
+ if (!(timer->parent.flag & RT_TIMER_FLAG_ACTIVATED))
+ return -RT_ERROR;
+
+ RT_OBJECT_HOOK_CALL(rt_object_put_hook, (&(timer->parent)));
+
+ /* disable interrupt */
+ level = rt_hw_interrupt_disable();
+
+ _timer_remove(timer);
+ /* change status */
+ timer->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
+
+ /* enable interrupt */
+ rt_hw_interrupt_enable(level);
+
+ return RT_EOK;
+}
+RTM_EXPORT(rt_timer_stop);
+
+/**
+ * @brief This function will get or set some options of the timer
+ *
+ * @param timer the timer to be get or set
+ * @param cmd the control command
+ * @param arg the argument
+ *
+ * @return the statu of control
+ */
+rt_err_t rt_timer_control(rt_timer_t timer, int cmd, void *arg)
+{
+ rt_base_t level;
+
+ /* parameter check */
+ RT_ASSERT(timer != RT_NULL);
+ RT_ASSERT(rt_object_get_type(&timer->parent) == RT_Object_Class_Timer);
+
+ level = rt_hw_interrupt_disable();
+ switch (cmd)
+ {
+ case RT_TIMER_CTRL_GET_TIME:
+ *(rt_tick_t *)arg = timer->init_tick;
+ break;
+
+ case RT_TIMER_CTRL_SET_TIME:
+ RT_ASSERT((*(rt_tick_t *)arg) < RT_TICK_MAX / 2);
+ timer->init_tick = *(rt_tick_t *)arg;
+ break;
+
+ case RT_TIMER_CTRL_SET_ONESHOT:
+ timer->parent.flag &= ~RT_TIMER_FLAG_PERIODIC;
+ break;
+
+ case RT_TIMER_CTRL_SET_PERIODIC:
+ timer->parent.flag |= RT_TIMER_FLAG_PERIODIC;
+ break;
+
+ case RT_TIMER_CTRL_GET_STATE:
+ if(timer->parent.flag & RT_TIMER_FLAG_ACTIVATED)
+ {
+ /*timer is start and run*/
+ *(rt_uint32_t *)arg = RT_TIMER_FLAG_ACTIVATED;
+ }
+ else
+ {
+ /*timer is stop*/
+ *(rt_uint32_t *)arg = RT_TIMER_FLAG_DEACTIVATED;
+ }
+ break;
+
+ case RT_TIMER_CTRL_GET_REMAIN_TIME:
+ *(rt_tick_t *)arg = timer->timeout_tick;
+ break;
+
+ default:
+ break;
+ }
+ rt_hw_interrupt_enable(level);
+
+ return RT_EOK;
+}
+RTM_EXPORT(rt_timer_control);
+
+/**
+ * @brief This function will check timer list, if a timeout event happens,
+ * the corresponding timeout function will be invoked.
+ *
+ * @note This function shall be invoked in operating system timer interrupt.
+ */
+void rt_timer_check(void)
+{
+ struct rt_timer *t;
+ rt_tick_t current_tick;
+ rt_base_t level;
+ rt_list_t list;
+
+ rt_list_init(&list);
+
+ RT_DEBUG_LOG(RT_DEBUG_TIMER, ("timer check enter\n"));
+
+ current_tick = rt_tick_get();
+
+ /* disable interrupt */
+ level = rt_hw_interrupt_disable();
+
+ while (!rt_list_isempty(&_timer_list[RT_TIMER_SKIP_LIST_LEVEL - 1]))
+ {
+ t = rt_list_entry(_timer_list[RT_TIMER_SKIP_LIST_LEVEL - 1].next,
+ struct rt_timer, row[RT_TIMER_SKIP_LIST_LEVEL - 1]);
+
+ /*
+ * It supposes that the new tick shall less than the half duration of
+ * tick max.
+ */
+ if ((current_tick - t->timeout_tick) < RT_TICK_MAX / 2)
+ {
+ RT_OBJECT_HOOK_CALL(rt_timer_enter_hook, (t));
+
+ /* remove timer from timer list firstly */
+ _timer_remove(t);
+ if (!(t->parent.flag & RT_TIMER_FLAG_PERIODIC))
+ {
+ t->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
+ }
+ /* add timer to temporary list */
+ rt_list_insert_after(&list, &(t->row[RT_TIMER_SKIP_LIST_LEVEL - 1]));
+ /* call timeout function */
+ t->timeout_func(t->parameter);
+
+ /* re-get tick */
+ current_tick = rt_tick_get();
+
+ RT_OBJECT_HOOK_CALL(rt_timer_exit_hook, (t));
+ RT_DEBUG_LOG(RT_DEBUG_TIMER, ("current tick: %d\n", current_tick));
+
+ /* Check whether the timer object is detached or started again */
+ if (rt_list_isempty(&list))
+ {
+ continue;
+ }
+ rt_list_remove(&(t->row[RT_TIMER_SKIP_LIST_LEVEL - 1]));
+ if ((t->parent.flag & RT_TIMER_FLAG_PERIODIC) &&
+ (t->parent.flag & RT_TIMER_FLAG_ACTIVATED))
+ {
+ /* start it */
+ t->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
+ rt_timer_start(t);
+ }
+ }
+ else break;
+ }
+
+ /* enable interrupt */
+ rt_hw_interrupt_enable(level);
+
+ RT_DEBUG_LOG(RT_DEBUG_TIMER, ("timer check leave\n"));
+}
+
+/**
+ * @brief This function will return the next timeout tick in the system.
+ *
+ * @return the next timeout tick in the system
+ */
+rt_tick_t rt_timer_next_timeout_tick(void)
+{
+ rt_tick_t next_timeout = RT_TICK_MAX;
+ _timer_list_next_timeout(_timer_list, &next_timeout);
+ return next_timeout;
+}
+
+#ifdef RT_USING_TIMER_SOFT
+/**
+ * @brief This function will check software-timer list, if a timeout event happens, the
+ * corresponding timeout function will be invoked.
+ */
+void rt_soft_timer_check(void)
+{
+ rt_tick_t current_tick;
+ struct rt_timer *t;
+ rt_base_t level;
+ rt_list_t list;
+
+ rt_list_init(&list);
+
+ RT_DEBUG_LOG(RT_DEBUG_TIMER, ("software timer check enter\n"));
+
+ /* disable interrupt */
+ level = rt_hw_interrupt_disable();
+
+ while (!rt_list_isempty(&_soft_timer_list[RT_TIMER_SKIP_LIST_LEVEL - 1]))
+ {
+ t = rt_list_entry(_soft_timer_list[RT_TIMER_SKIP_LIST_LEVEL - 1].next,
+ struct rt_timer, row[RT_TIMER_SKIP_LIST_LEVEL - 1]);
+
+ current_tick = rt_tick_get();
+
+ /*
+ * It supposes that the new tick shall less than the half duration of
+ * tick max.
+ */
+ if ((current_tick - t->timeout_tick) < RT_TICK_MAX / 2)
+ {
+ RT_OBJECT_HOOK_CALL(rt_timer_enter_hook, (t));
+
+ /* remove timer from timer list firstly */
+ _timer_remove(t);
+ if (!(t->parent.flag & RT_TIMER_FLAG_PERIODIC))
+ {
+ t->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
+ }
+ /* add timer to temporary list */
+ rt_list_insert_after(&list, &(t->row[RT_TIMER_SKIP_LIST_LEVEL - 1]));
+
+ _soft_timer_status = RT_SOFT_TIMER_BUSY;
+ /* enable interrupt */
+ rt_hw_interrupt_enable(level);
+
+ /* call timeout function */
+ t->timeout_func(t->parameter);
+
+ RT_OBJECT_HOOK_CALL(rt_timer_exit_hook, (t));
+ RT_DEBUG_LOG(RT_DEBUG_TIMER, ("current tick: %d\n", current_tick));
+
+ /* disable interrupt */
+ level = rt_hw_interrupt_disable();
+
+ _soft_timer_status = RT_SOFT_TIMER_IDLE;
+ /* Check whether the timer object is detached or started again */
+ if (rt_list_isempty(&list))
+ {
+ continue;
+ }
+ rt_list_remove(&(t->row[RT_TIMER_SKIP_LIST_LEVEL - 1]));
+ if ((t->parent.flag & RT_TIMER_FLAG_PERIODIC) &&
+ (t->parent.flag & RT_TIMER_FLAG_ACTIVATED))
+ {
+ /* start it */
+ t->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
+ rt_timer_start(t);
+ }
+ }
+ else break; /* not check anymore */
+ }
+ /* enable interrupt */
+ rt_hw_interrupt_enable(level);
+
+ RT_DEBUG_LOG(RT_DEBUG_TIMER, ("software timer check leave\n"));
+}
+
+/**
+ * @brief System timer thread entry
+ *
+ * @param parameter is the arg of the thread
+ */
+static void _timer_thread_entry(void *parameter)
+{
+ rt_tick_t next_timeout;
+
+ while (1)
+ {
+ /* get the next timeout tick */
+ if (_timer_list_next_timeout(_soft_timer_list, &next_timeout) != RT_EOK)
+ {
+ /* no software timer exist, suspend self. */
+ rt_thread_suspend(rt_thread_self());
+ rt_schedule();
+ }
+ else
+ {
+ rt_tick_t current_tick;
+
+ /* get current tick */
+ current_tick = rt_tick_get();
+
+ if ((next_timeout - current_tick) < RT_TICK_MAX / 2)
+ {
+ /* get the delta timeout tick */
+ next_timeout = next_timeout - current_tick;
+ rt_thread_delay(next_timeout);
+ }
+ }
+
+ /* check software timer */
+ rt_soft_timer_check();
+ }
+}
+#endif /* RT_USING_TIMER_SOFT */
+
+/**
+ * @ingroup SystemInit
+ *
+ * @brief This function will initialize system timer
+ */
+void rt_system_timer_init(void)
+{
+ rt_size_t i;
+
+ for (i = 0; i < sizeof(_timer_list) / sizeof(_timer_list[0]); i++)
+ {
+ rt_list_init(_timer_list + i);
+ }
+}
+
+/**
+ * @ingroup SystemInit
+ *
+ * @brief This function will initialize system timer thread
+ */
+void rt_system_timer_thread_init(void)
+{
+#ifdef RT_USING_TIMER_SOFT
+ int i;
+
+ for (i = 0;
+ i < sizeof(_soft_timer_list) / sizeof(_soft_timer_list[0]);
+ i++)
+ {
+ rt_list_init(_soft_timer_list + i);
+ }
+
+ /* start software timer thread */
+ rt_thread_init(&_timer_thread,
+ "timer",
+ _timer_thread_entry,
+ RT_NULL,
+ &_timer_thread_stack[0],
+ sizeof(_timer_thread_stack),
+ RT_TIMER_THREAD_PRIO,
+ 10);
+
+ /* startup */
+ rt_thread_startup(&_timer_thread);
+#endif /* RT_USING_TIMER_SOFT */
+}
+
+/**@}*/
diff --git a/User/system/src/btn.c b/User/system/src/btn.c
deleted file mode 100644
index 688f928..0000000
--- a/User/system/src/btn.c
+++ /dev/null
@@ -1,247 +0,0 @@
-/*
- * @Author:
- * @Date: 2023-07-04 08:25:56
- * @LastEditors: xxx
- * @LastEditTime: 2023-08-25 11:13:52
- * @Description:一个小巧简单易用的事件驱动型按键驱动模块,可无限量扩展按键,按键事件的回调异步处理方式可以简化你的程序结构,去除冗余的按键处理硬编码,让你的按键业务逻辑更清晰
- * email:
- * Copyright (c) 2023 by xxx, All Rights Reserved.
- */
-
-#include "../inc/btn.h"
-
-#define EVENT_CB(ev) \
- if (handle->cb[ev]) \
- handle->cb[ev]((Button *)handle)
-
-// button handle list head.
-static struct Button *head_handle = NULL;
-
-/**
- * @brief 初始化按钮结构体句柄。
- * @param handle: 按钮句柄结构体。
- * @param pin_level: 读取按钮连接的HAL GPIOLevel。
- * @param active_level: 按下按钮的GPIOLevel。
- * @param button_id: 按钮ID。
- * @retval 无
- */
-void button_init(struct Button *handle, uint8_t (*pin_level)(uint8_t), active_level_e active_level, uint8_t button_id)
-{
-#ifdef STM32
- osel_memset((uint8_t *)handle, 0, sizeof(struct Button));
-#else
- memset(handle, 0, sizeof(struct Button));
-#endif
-
- handle->event = (uint8_t)NONE_PRESS;
- handle->hal_button_Level = pin_level;
- handle->button_level = handle->hal_button_Level(button_id);
- handle->active_level = (uint8_t)active_level;
- handle->button_id = button_id;
-}
-
-/**
- * @brief 为按钮添加事件回调函数。
- * @param handle: 按钮句柄结构体。
- * @param event: 触发事件类型。
- * @param cb: 回调函数。
- * @retval 无
- */
-void button_attach(struct Button *handle, PressEvent event, BtnCallback cb)
-{
- handle->cb[event] = cb;
-}
-
-/**
- * @brief 查询按钮发生的事件。
- * @param handle: 按钮句柄结构体。
- * @retval 按钮事件。
- */
-PressEvent get_button_event(struct Button *handle)
-{
- return (PressEvent)(handle->event);
-}
-
-/**
- * @brief 按钮驱动核心函数,驱动状态机。
- * @param handle: 按钮句柄结构体。
- * @retval 无
- */
-void button_handler(struct Button *handle)
-{
- uint8_t read_gpio_level = handle->hal_button_Level(handle->button_id);
-
- // ticks counter working..
- if ((handle->state) > 0)
- handle->ticks++;
-
- /*------------button debounce handle---------------*/
- if (read_gpio_level != handle->button_level)
- { // not equal to prev one
- // continue read 3 times same new level change
- if (++(handle->debounce_cnt) >= DEBOUNCE_TICKS)
- {
- handle->button_level = read_gpio_level;
- handle->debounce_cnt = 0;
- }
- }
- else
- { // leved not change ,counter reset.
- handle->debounce_cnt = 0;
- }
-
- /*-----------------State machine-------------------*/
- switch (handle->state)
- {
- case 0:
- if (handle->button_level == handle->active_level)
- { // start press down
- handle->event = (uint8_t)PRESS_DOWN;
- EVENT_CB(PRESS_DOWN);
- handle->ticks = 0;
- handle->repeat = 1;
- handle->state = 1;
- }
- else
- {
- handle->event = (uint8_t)NONE_PRESS;
- }
- break;
-
- case 1:
- if (handle->button_level != handle->active_level)
- { // released press up
- handle->event = (uint8_t)PRESS_UP;
- EVENT_CB(PRESS_UP);
- handle->ticks = 0;
- handle->state = 2;
- }
- else if (handle->ticks > LONG_TICKS)
- {
- handle->event = (uint8_t)LONG_PRESS_START;
- EVENT_CB(LONG_PRESS_START);
- handle->state = 5;
- }
- break;
-
- case 2:
- if (handle->button_level == handle->active_level)
- { // press down again
- handle->event = (uint8_t)PRESS_DOWN;
- EVENT_CB(PRESS_DOWN);
- handle->repeat++;
- EVENT_CB(PRESS_REPEAT); // repeat hit
- handle->ticks = 0;
- handle->state = 3;
- }
- else if (handle->ticks > SHORT_TICKS)
- { // released timeout
- if (handle->repeat == 1)
- {
- handle->event = (uint8_t)SINGLE_CLICK;
- EVENT_CB(SINGLE_CLICK);
- }
- else if (handle->repeat == 2)
- {
- handle->event = (uint8_t)DOUBLE_CLICK;
- EVENT_CB(DOUBLE_CLICK); // repeat hit
- }
- handle->state = 0;
- }
- break;
-
- case 3:
- if (handle->button_level != handle->active_level)
- { // released press up
- handle->event = (uint8_t)PRESS_UP;
- EVENT_CB(PRESS_UP);
- if (handle->ticks < SHORT_TICKS)
- {
- handle->ticks = 0;
- handle->state = 2; // repeat press
- }
- else
- {
- handle->state = 0;
- }
- }
- else if (handle->ticks > SHORT_TICKS)
- { // long press up
- handle->state = 0;
- }
- break;
-
- case 5:
- if (handle->button_level == handle->active_level)
- {
- // continue hold trigger
- handle->event = (uint8_t)LONG_PRESS_HOLD;
- EVENT_CB(LONG_PRESS_HOLD);
- }
- else
- { // releasd
- handle->event = (uint8_t)PRESS_UP;
- EVENT_CB(PRESS_UP);
- handle->state = 0; // reset
- }
- break;
- default:
- handle->state = 0; // reset
- break;
- }
-}
-
-/**
- * @brief 启动按钮工作,将句柄添加到工作队列中。
- * @param handle: 目标句柄结构体。
- * @retval 0: 成功。-1: 已存在。
- */
-int button_start(struct Button *handle)
-{
- struct Button *target = head_handle;
- while (target)
- {
- if (target == handle)
- return -1; // already exist.
- target = target->next;
- }
- handle->next = head_handle;
- head_handle = handle;
- return 0;
-}
-
-/**
- * @brief 停止按钮工作,从工作队列中移除句柄。
- * @param handle: 目标句柄结构体。
- * @retval None
- */
-void button_stop(struct Button *handle)
-{
- struct Button **curr;
- for (curr = &head_handle; *curr;)
- {
- struct Button *entry = *curr;
- if (entry == handle)
- {
- *curr = entry->next;
- // free(entry);
- return;
- }
- else
- curr = &entry->next;
- }
-}
-
-/**
- * @brief 后台计时,定时器重复调用间隔为5ms。
- * @param None.
- * @retval None
- */
-void button_ticks()
-{
- struct Button *target;
- for (target = head_handle; target; target = target->next)
- {
- button_handler(target);
- }
-}
diff --git a/User/system/src/delay.c b/User/system/src/delay.c
deleted file mode 100644
index 1c42a61..0000000
--- a/User/system/src/delay.c
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * @Author:
- * @Date: 2023-04-11 18:31:07
- * @LastEditors: xxx
- * @LastEditTime: 2023-08-25 11:27:12
- * @Description:
- * email:
- * Copyright (c) 2023 by xxx, All Rights Reserved.
- */
-
-#include "delay.h"
-// static uint16_t g_fac_ms = 0; // ms延时倍乘数,在os下,代表每个节拍的ms数
-static uint32_t g_fac_us = 0; /* us延时倍乘数 */
-
-void SysTick_Init(void)
-{
- NVIC_SetPriority(SysTick_IRQn, 3);
- LL_SYSTICK_EnableIT();
-}
-/**
- * @brief 初始化延迟函数
- * @param sysclk: 系统时钟频率, 即CPU频率(rcc_c_ck)
- * @retval 无
- */
-void delay_init(uint16_t sysclk)
-{
-#if SYS_SUPPORT_OS /* 如果需要支持OS */
- uint32_t reload;
-#endif
- // SysTick_Init();
- // LL_SetSystemCoreClock(LL_SYSTICK_CLKSOURCE_HCLK); /* SYSTICK使用内核时钟源,同CPU同频率 */
- g_fac_us = sysclk; /* 不论是否使用OS,g_fac_us都需要使用 */
- // Remove the redundant assignment statement
-#if SYS_SUPPORT_OS /* 如果需要支持OS. */
- reload = sysclk; /* 每秒钟的计数次数 单位为M */
- reload *= 1000000 / configTICK_RATE_HZ; /* 根据delay_ostickspersec设定溢出时间,reload为24位
- * 寄存器,最大值:16777216,在168M下,约合0.099s左右
- */
- g_fac_ms = 1000 / configTICK_RATE_HZ; // 代表OS可以延时的最少单位
- SysTick->CTRL |= SysTick_CTRL_TICKINT_Msk; /* 开启SYSTICK中断 */
- SysTick->LOAD = reload; /* 每1/delay_ostickspersec秒中断一次 */
- SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk; /* 开启SYSTICK */
-#endif
-}
-
-/**
- * @brief 延时nus
- * @param nus: 要延时的us数.
- * @note 注意: nus的值,不要大于34952us(最大值即2^24 / g_fac_us @g_fac_us = 168)
- * @retval 无
- */
-void delay_us(uint32_t nus)
-{
- uint32_t ticks;
- uint32_t told, tnow, tcnt = 0;
- uint32_t reload = SysTick->LOAD; /* LOAD的值 */
- ticks = nus * g_fac_us; /* 需要的节拍数 */
- told = SysTick->VAL; /* 刚进入时的计数器值 */
- while (1)
- {
- tnow = SysTick->VAL;
- if (tnow != told)
- {
- if (tnow < told)
- {
- tcnt += told - tnow; /* 这里注意一下SYSTICK是一个递减的计数器就可以了 */
- }
- else
- {
- tcnt += reload - tnow + told;
- }
- told = tnow;
- if (tcnt >= ticks)
- {
- __NOP();
- break; /* 时间超过/等于要延迟的时间,则退出 */
- }
- }
- }
-}
-
-/**
- * @brief 延时nms
- * @param nms: 要延时的ms数 (0< nms <= 65535)
- * @retval 无
- */
-void delay_ms(uint16_t nms)
-{
- uint32_t repeat = nms / 30; /* 这里用30,是考虑到可能有超频应用 */
- uint32_t remain = nms % 30;
-
- while (repeat)
- {
- delay_us(30 * 1000); /* 利用delay_us 实现 1000ms 延时 */
- repeat--;
- }
-
- if (remain)
- {
- delay_us(remain * 1000); /* 利用delay_us, 把尾数延时(remain ms)给做了 */
- }
-}
-
-/**
- * @brief 延时函数,用于模拟硬件延时。
- * @param {uint32_t} ticks
- * @return {*}
- * @note: 请注意,这个函数仅用于模拟硬件延时,实际应用中可能需要使用其他延时函数,如HAL_Delay或rt_delay。
- */
-void delay_tick(uint32_t ticks)
-{
- while (ticks--)
- {
- __NOP();
- }
-}
diff --git a/User/system/src/sys.c b/User/system/src/sys.c
deleted file mode 100644
index f5ca2ea..0000000
--- a/User/system/src/sys.c
+++ /dev/null
@@ -1,254 +0,0 @@
-/*
- * @Author:
- * @Date: 2023-04-11 18:46:58
- * @LastEditors: xxx
- * @LastEditTime: 2023-08-25 11:31:06
- * @Description:
- * email:
- * Copyright (c) 2023 by xxx, All Rights Reserved.
- */
-
-#include "sys.h"
-clock_config_t original_clock_config; // 原始时钟配置
-__IO uint32_t uwTick;
-__IO uint32_t scheduler_start_time; // 调度器开始时间
-__IO uint32_t scheduler_end_time; // 调度器结束时间
-__IO uint32_t scheduler_occupancy_time = 0; // 调度器占用时间
-/**
- * @brief 设置中断向量表偏移地址
- * @param baseaddr : 基址
- * @param offset : 偏移量
- * @retval 无
- */
-void sys_nvic_set_vector_table(uint32_t baseaddr, uint32_t offset)
-{
- /* 设置NVIC的向量表偏移寄存器,VTOR低9位保留,即[8:0]保留 */
- SCB->VTOR = baseaddr | (offset & (uint32_t)0xFFFFFE00);
-}
-
-/**
- * @brief 执行: WFI指令(执行完该指令进入低功耗状态, 等待中断唤醒)
- * @param 无
- * @retval 无
- */
-void sys_wfi_set(void)
-{
- __ASM __IO("wfi");
-}
-
-/**
- * @brief 关闭所有中断(但是不包括fault和NMI中断)
- * @param 无
- * @retval 无
- */
-void sys_intx_disable(void)
-{
- __ASM __IO("cpsid i");
-}
-
-/**
- * @brief 开启所有中断
- * @param 无
- * @retval 无
- */
-void sys_intx_enable(void)
-{
- __ASM __IO("cpsie i");
-}
-
-/**
- * @brief 设置栈顶地址
- * @note 左侧若有红X, 属于MDK误报, 实际是没问题的
- * @param addr: 栈顶地址
- * @retval 无
- */
-void sys_msr_msp(uint32_t addr)
-{
- __set_MSP(addr); /* 设置栈顶地址 */
-}
-
-/**
- * @brief 进入待机模式
- * @param 无
- * @retval 无
- */
-void sys_standby(void)
-{
- // LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_PWR); /* 使能电源时钟 */
- // SET_BIT(PWR->CR, PWR_CR_PDDS); /* 进入待机模式 */
-}
-
-/**
- * @brief 系统软复位
- * @param 无
- * @retval 无
- */
-void sys_soft_reset(void)
-{
- NVIC_SystemReset();
-}
-
-/**
- * @brief 10ms滴答定时器,需要单独放到定时器中断中执行
- * @param 无
- * @retval 提供给sys_millis()函数使用,之前放在SysTick_Handler中执行影响精度
- */
-__weak void LL_IncTick(void)
-{
- uwTick += 1;
-}
-
-/**
- * @brief 获取系统当前滴答计数
- * @param 无
- * @retval 当前滴答计数
- */
-uint32_t sys_get_tick(void)
-{
- return uwTick;
-}
-
-/**
- * @brief 获取系统当前毫秒级时间戳。
- * @return {uint32_t} 当前毫秒级时间戳
- * @note: 请注意,这个函数仅用于模拟硬件延时,实际应用中可能需要使用其他时钟源,如RTC或外部时钟。
- */
-uint32_t sys_millis(void)
-{
- return uwTick * 10;
-}
-
-/**
- * @brief 系统计时器重新开始
- * @return {*}
- * @note
- */
-void sys_millis_reset(void)
-{
- uwTick = 0;
-}
-
-/**
- * @brief 将系统时间戳转换为秒级时间戳。
- * @param {uint32_t} start_time 开始时间戳
- * @return {uint32_t} 秒级时间戳
- * @note: 请注意,这个函数仅用于模拟硬件延时,实际应用中可能需要使用其他时钟源,如RTC或外部时钟。
- */
-uint32_t sys_to_seconds(uint32_t start_time)
-{
- return (sys_millis() - start_time) / 1000;
-}
-
-/**
- * @brief 记录调度器开始时间
- * @return {*}
- * @note
- */
-void scheduler_time_start(void)
-{
- scheduler_start_time = sys_millis();
-}
-
-/**
- * @brief 返回调度器运行时间
- * @return {*}
- * @note
- */
-uint32_t scheduler_time_stop(void)
-{
- uint32_t scheduler_end_time = sys_millis() - scheduler_start_time;
- scheduler_occupancy_time += scheduler_end_time;
- return scheduler_end_time;
-}
-
-/**
- * @brief 计算任务占用时间百分比
- * @param {uint32_t} run_time 运行时间
- * @return {*} 任务占用时间百分比,单位为%
- * @note
- */
-uint32_t scheduler_time_occupancy_get(uint32_t run_time)
-{
- float32 percent = 0.0f;
- percent = (float32)(scheduler_occupancy_time) / (float32)run_time;
- scheduler_occupancy_time = 0;
- return (uint32_t)(percent * 100);
-}
-
-// 切换到新的时钟配置
-void change_system_clock(clock_config_t *new_config)
-{
-#if CLOCK_CHANGE_ENABLE == TRUE
- // 1. 切换到HSE作为临时时钟源,根据你的硬件配置来调整
- LL_RCC_HSE_Enable();
- while (LL_RCC_HSE_IsReady() != 1)
- {
- }
- LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_HSE);
- while (LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_HSE)
- {
- }
-
- // 2. 关闭PLL
- LL_RCC_PLL_Disable();
- while (LL_RCC_PLL_IsReady() != 0)
- {
- }
-
- // 3. 配置新的PLL参数
- // 注意:这里假设HSE作为PLL的时钟源,你需要根据你的硬件配置来调整
- LL_RCC_PLL_ConfigDomain_SYS(new_config->pll_source, new_config->pll_m, new_config->pll_n, new_config->pll_r);
-
- // 4. 重新启用PLL
- LL_RCC_PLL_EnableDomain_SYS();
- LL_RCC_PLL_Enable();
- while (LL_RCC_PLL_IsReady() != 1)
- {
- }
-
- // 5. 切换回PLL作为系统时钟源
- LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL);
- while (LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_PLL)
- {
- }
-
- // 6. 更新时钟分频器
- LL_RCC_SetAHBPrescaler(new_config->ahb_div);
- LL_RCC_SetAPB1Prescaler(new_config->apb1_div);
- LL_RCC_SetAPB2Prescaler(new_config->apb2_div);
-
- // 7. 更新SystemCoreClock变量
- LL_Init1msTick(new_config->sysclk);
- LL_SetSystemCoreClock(new_config->sysclk);
- original_clock_config.sysclk_change = new_config->sysclk;
-#endif
-}
-
-// 恢复到原始时钟配置
-void restore_system_clock(void)
-{
-#if CLOCK_CHANGE_ENABLE == TRUE
- change_system_clock(&original_clock_config);
-#endif
-}
-
-// 获取原始时钟配置
-clock_config_t *get_original_clock_config(void)
-{
- return &original_clock_config;
-}
-
-// 在系统启动时调用此函数来初始化时钟并保存原始配置
-void system_clock_read(void)
-{
- // 保存原始时钟配置
- original_clock_config.pll_source = LL_RCC_PLL_GetMainSource();
- original_clock_config.pll_m = LL_RCC_PLL_GetDivider();
- original_clock_config.pll_n = LL_RCC_PLL_GetN();
- original_clock_config.pll_r = LL_RCC_PLL_GetR();
-
- original_clock_config.ahb_div = LL_RCC_GetAHBPrescaler();
- original_clock_config.apb1_div = LL_RCC_GetAPB1Prescaler();
- original_clock_config.apb2_div = LL_RCC_GetAPB2Prescaler();
- original_clock_config.sysclk = SystemCoreClock;
-}
diff --git a/controller-v2.ioc b/controller.ioc
similarity index 66%
rename from controller-v2.ioc
rename to controller.ioc
index f4ebcdb..b1958b8 100644
--- a/controller-v2.ioc
+++ b/controller.ioc
@@ -1,7 +1,8 @@
#MicroXplorer Configuration settings - do not modify
ADC1.Channel-1\#ChannelRegularConversion=ADC_CHANNEL_5
-ADC1.Channel-10\#ChannelRegularConversion=ADC_CHANNEL_VREFINT
+ADC1.Channel-10\#ChannelRegularConversion=ADC_CHANNEL_16
ADC1.Channel-11\#ChannelRegularConversion=ADC_CHANNEL_TEMPSENSOR
+ADC1.Channel-12\#ChannelRegularConversion=ADC_CHANNEL_VREFINT
ADC1.Channel-2\#ChannelRegularConversion=ADC_CHANNEL_6
ADC1.Channel-3\#ChannelRegularConversion=ADC_CHANNEL_7
ADC1.Channel-4\#ChannelRegularConversion=ADC_CHANNEL_8
@@ -10,16 +11,17 @@ ADC1.Channel-6\#ChannelRegularConversion=ADC_CHANNEL_11
ADC1.Channel-7\#ChannelRegularConversion=ADC_CHANNEL_12
ADC1.Channel-8\#ChannelRegularConversion=ADC_CHANNEL_13
ADC1.Channel-9\#ChannelRegularConversion=ADC_CHANNEL_14
-ADC1.ClockPrescaler=ADC_CLOCK_ASYNC_DIV64
+ADC1.ClockPrescaler=ADC_CLOCK_ASYNC_DIV16
ADC1.CommonPathInternal=ADC_CHANNEL_VREFINT|ADC_CHANNEL_TEMPSENSOR|null|null
ADC1.ContinuousConvMode=ENABLE
ADC1.DMAContinuousRequests=ENABLE
-ADC1.IPParameters=Rank-1\#ChannelRegularConversion,Channel-1\#ChannelRegularConversion,SamplingTime-1\#ChannelRegularConversion,OffsetNumber-1\#ChannelRegularConversion,NbrOfConversionFlag,Rank-2\#ChannelRegularConversion,Channel-2\#ChannelRegularConversion,SamplingTime-2\#ChannelRegularConversion,OffsetNumber-2\#ChannelRegularConversion,Rank-3\#ChannelRegularConversion,Channel-3\#ChannelRegularConversion,SamplingTime-3\#ChannelRegularConversion,OffsetNumber-3\#ChannelRegularConversion,NbrOfConversion,Rank-4\#ChannelRegularConversion,Channel-4\#ChannelRegularConversion,SamplingTime-4\#ChannelRegularConversion,OffsetNumber-4\#ChannelRegularConversion,ContinuousConvMode,DMAContinuousRequests,Rank-5\#ChannelRegularConversion,Channel-5\#ChannelRegularConversion,SamplingTime-5\#ChannelRegularConversion,OffsetNumber-5\#ChannelRegularConversion,Rank-6\#ChannelRegularConversion,Channel-6\#ChannelRegularConversion,SamplingTime-6\#ChannelRegularConversion,OffsetNumber-6\#ChannelRegularConversion,Rank-7\#ChannelRegularConversion,Channel-7\#ChannelRegularConversion,SamplingTime-7\#ChannelRegularConversion,OffsetNumber-7\#ChannelRegularConversion,Rank-8\#ChannelRegularConversion,Channel-8\#ChannelRegularConversion,SamplingTime-8\#ChannelRegularConversion,OffsetNumber-8\#ChannelRegularConversion,Rank-9\#ChannelRegularConversion,Channel-9\#ChannelRegularConversion,SamplingTime-9\#ChannelRegularConversion,OffsetNumber-9\#ChannelRegularConversion,Rank-10\#ChannelRegularConversion,Channel-10\#ChannelRegularConversion,SamplingTime-10\#ChannelRegularConversion,OffsetNumber-10\#ChannelRegularConversion,Rank-11\#ChannelRegularConversion,Channel-11\#ChannelRegularConversion,SamplingTime-11\#ChannelRegularConversion,OffsetNumber-11\#ChannelRegularConversion,ClockPrescaler,Overrun,master,CommonPathInternal
-ADC1.NbrOfConversion=11
+ADC1.IPParameters=Rank-1\#ChannelRegularConversion,Channel-1\#ChannelRegularConversion,SamplingTime-1\#ChannelRegularConversion,OffsetNumber-1\#ChannelRegularConversion,NbrOfConversionFlag,Rank-2\#ChannelRegularConversion,Channel-2\#ChannelRegularConversion,SamplingTime-2\#ChannelRegularConversion,OffsetNumber-2\#ChannelRegularConversion,Rank-3\#ChannelRegularConversion,Channel-3\#ChannelRegularConversion,SamplingTime-3\#ChannelRegularConversion,OffsetNumber-3\#ChannelRegularConversion,NbrOfConversion,Rank-4\#ChannelRegularConversion,Channel-4\#ChannelRegularConversion,SamplingTime-4\#ChannelRegularConversion,OffsetNumber-4\#ChannelRegularConversion,ContinuousConvMode,DMAContinuousRequests,Rank-5\#ChannelRegularConversion,Channel-5\#ChannelRegularConversion,SamplingTime-5\#ChannelRegularConversion,OffsetNumber-5\#ChannelRegularConversion,Rank-6\#ChannelRegularConversion,Channel-6\#ChannelRegularConversion,SamplingTime-6\#ChannelRegularConversion,OffsetNumber-6\#ChannelRegularConversion,Rank-7\#ChannelRegularConversion,Channel-7\#ChannelRegularConversion,SamplingTime-7\#ChannelRegularConversion,OffsetNumber-7\#ChannelRegularConversion,Rank-8\#ChannelRegularConversion,Channel-8\#ChannelRegularConversion,SamplingTime-8\#ChannelRegularConversion,OffsetNumber-8\#ChannelRegularConversion,Rank-9\#ChannelRegularConversion,Channel-9\#ChannelRegularConversion,SamplingTime-9\#ChannelRegularConversion,OffsetNumber-9\#ChannelRegularConversion,Rank-10\#ChannelRegularConversion,Channel-10\#ChannelRegularConversion,SamplingTime-10\#ChannelRegularConversion,OffsetNumber-10\#ChannelRegularConversion,Rank-11\#ChannelRegularConversion,Channel-11\#ChannelRegularConversion,SamplingTime-11\#ChannelRegularConversion,OffsetNumber-11\#ChannelRegularConversion,ClockPrescaler,Overrun,Resolution,Rank-12\#ChannelRegularConversion,Channel-12\#ChannelRegularConversion,SamplingTime-12\#ChannelRegularConversion,OffsetNumber-12\#ChannelRegularConversion,master,CommonPathInternal
+ADC1.NbrOfConversion=12
ADC1.NbrOfConversionFlag=1
ADC1.OffsetNumber-1\#ChannelRegularConversion=ADC_OFFSET_NONE
ADC1.OffsetNumber-10\#ChannelRegularConversion=ADC_OFFSET_NONE
ADC1.OffsetNumber-11\#ChannelRegularConversion=ADC_OFFSET_NONE
+ADC1.OffsetNumber-12\#ChannelRegularConversion=ADC_OFFSET_NONE
ADC1.OffsetNumber-2\#ChannelRegularConversion=ADC_OFFSET_NONE
ADC1.OffsetNumber-3\#ChannelRegularConversion=ADC_OFFSET_NONE
ADC1.OffsetNumber-4\#ChannelRegularConversion=ADC_OFFSET_NONE
@@ -32,6 +34,7 @@ ADC1.Overrun=ADC_OVR_DATA_PRESERVED
ADC1.Rank-1\#ChannelRegularConversion=1
ADC1.Rank-10\#ChannelRegularConversion=10
ADC1.Rank-11\#ChannelRegularConversion=11
+ADC1.Rank-12\#ChannelRegularConversion=12
ADC1.Rank-2\#ChannelRegularConversion=2
ADC1.Rank-3\#ChannelRegularConversion=3
ADC1.Rank-4\#ChannelRegularConversion=4
@@ -40,33 +43,20 @@ ADC1.Rank-6\#ChannelRegularConversion=6
ADC1.Rank-7\#ChannelRegularConversion=7
ADC1.Rank-8\#ChannelRegularConversion=8
ADC1.Rank-9\#ChannelRegularConversion=9
-ADC1.SamplingTime-1\#ChannelRegularConversion=ADC_SAMPLETIME_640CYCLES_5
-ADC1.SamplingTime-10\#ChannelRegularConversion=ADC_SAMPLETIME_640CYCLES_5
-ADC1.SamplingTime-11\#ChannelRegularConversion=ADC_SAMPLETIME_640CYCLES_5
-ADC1.SamplingTime-2\#ChannelRegularConversion=ADC_SAMPLETIME_47CYCLES_5
-ADC1.SamplingTime-3\#ChannelRegularConversion=ADC_SAMPLETIME_47CYCLES_5
-ADC1.SamplingTime-4\#ChannelRegularConversion=ADC_SAMPLETIME_47CYCLES_5
-ADC1.SamplingTime-5\#ChannelRegularConversion=ADC_SAMPLETIME_640CYCLES_5
-ADC1.SamplingTime-6\#ChannelRegularConversion=ADC_SAMPLETIME_640CYCLES_5
-ADC1.SamplingTime-7\#ChannelRegularConversion=ADC_SAMPLETIME_640CYCLES_5
-ADC1.SamplingTime-8\#ChannelRegularConversion=ADC_SAMPLETIME_47CYCLES_5
-ADC1.SamplingTime-9\#ChannelRegularConversion=ADC_SAMPLETIME_47CYCLES_5
+ADC1.Resolution=ADC_RESOLUTION_12B
+ADC1.SamplingTime-1\#ChannelRegularConversion=ADC_SAMPLETIME_12CYCLES_5
+ADC1.SamplingTime-10\#ChannelRegularConversion=ADC_SAMPLETIME_12CYCLES_5
+ADC1.SamplingTime-11\#ChannelRegularConversion=ADC_SAMPLETIME_12CYCLES_5
+ADC1.SamplingTime-12\#ChannelRegularConversion=ADC_SAMPLETIME_12CYCLES_5
+ADC1.SamplingTime-2\#ChannelRegularConversion=ADC_SAMPLETIME_12CYCLES_5
+ADC1.SamplingTime-3\#ChannelRegularConversion=ADC_SAMPLETIME_12CYCLES_5
+ADC1.SamplingTime-4\#ChannelRegularConversion=ADC_SAMPLETIME_12CYCLES_5
+ADC1.SamplingTime-5\#ChannelRegularConversion=ADC_SAMPLETIME_12CYCLES_5
+ADC1.SamplingTime-6\#ChannelRegularConversion=ADC_SAMPLETIME_12CYCLES_5
+ADC1.SamplingTime-7\#ChannelRegularConversion=ADC_SAMPLETIME_12CYCLES_5
+ADC1.SamplingTime-8\#ChannelRegularConversion=ADC_SAMPLETIME_12CYCLES_5
+ADC1.SamplingTime-9\#ChannelRegularConversion=ADC_SAMPLETIME_12CYCLES_5
ADC1.master=1
-ADC2.Channel-0\#ChannelRegularConversion=ADC_CHANNEL_5
-ADC2.Channel-1\#ChannelRegularConversion=ADC_CHANNEL_6
-ADC2.ClockPrescaler=ADC_CLOCK_ASYNC_DIV64
-ADC2.CommonPathInternal=null|null|null|null
-ADC2.ContinuousConvMode=ENABLE
-ADC2.DMAContinuousRequests=ENABLE
-ADC2.IPParameters=Rank-0\#ChannelRegularConversion,ClockPrescaler,Channel-0\#ChannelRegularConversion,SamplingTime-0\#ChannelRegularConversion,OffsetNumber-0\#ChannelRegularConversion,NbrOfConversionFlag,ContinuousConvMode,DMAContinuousRequests,Rank-1\#ChannelRegularConversion,Channel-1\#ChannelRegularConversion,SamplingTime-1\#ChannelRegularConversion,OffsetNumber-1\#ChannelRegularConversion,NbrOfConversion,CommonPathInternal
-ADC2.NbrOfConversion=2
-ADC2.NbrOfConversionFlag=1
-ADC2.OffsetNumber-0\#ChannelRegularConversion=ADC_OFFSET_NONE
-ADC2.OffsetNumber-1\#ChannelRegularConversion=ADC_OFFSET_NONE
-ADC2.Rank-0\#ChannelRegularConversion=1
-ADC2.Rank-1\#ChannelRegularConversion=2
-ADC2.SamplingTime-0\#ChannelRegularConversion=ADC_SAMPLETIME_640CYCLES_5
-ADC2.SamplingTime-1\#ChannelRegularConversion=ADC_SAMPLETIME_640CYCLES_5
CAD.formats=[]
CAD.pinconfig=Project naming
CAD.provider=
@@ -82,43 +72,13 @@ Dma.ADC1.0.PeriphDataAlignment=DMA_PDATAALIGN_HALFWORD
Dma.ADC1.0.PeriphInc=DMA_PINC_DISABLE
Dma.ADC1.0.Priority=DMA_PRIORITY_LOW
Dma.ADC1.0.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlignment,MemDataAlignment,Mode,Priority
-Dma.ADC2.8.Direction=DMA_PERIPH_TO_MEMORY
-Dma.ADC2.8.Instance=DMA1_Channel2
-Dma.ADC2.8.MemDataAlignment=DMA_MDATAALIGN_HALFWORD
-Dma.ADC2.8.MemInc=DMA_MINC_ENABLE
-Dma.ADC2.8.Mode=DMA_CIRCULAR
-Dma.ADC2.8.PeriphDataAlignment=DMA_PDATAALIGN_HALFWORD
-Dma.ADC2.8.PeriphInc=DMA_PINC_DISABLE
-Dma.ADC2.8.Priority=DMA_PRIORITY_LOW
-Dma.ADC2.8.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlignment,MemDataAlignment,Mode,Priority
-Dma.I2C1_RX.6.Direction=DMA_PERIPH_TO_MEMORY
-Dma.I2C1_RX.6.Instance=DMA1_Channel7
-Dma.I2C1_RX.6.MemDataAlignment=DMA_MDATAALIGN_BYTE
-Dma.I2C1_RX.6.MemInc=DMA_MINC_ENABLE
-Dma.I2C1_RX.6.Mode=DMA_NORMAL
-Dma.I2C1_RX.6.PeriphDataAlignment=DMA_PDATAALIGN_BYTE
-Dma.I2C1_RX.6.PeriphInc=DMA_PINC_DISABLE
-Dma.I2C1_RX.6.Priority=DMA_PRIORITY_LOW
-Dma.I2C1_RX.6.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlignment,MemDataAlignment,Mode,Priority
-Dma.I2C1_TX.7.Direction=DMA_MEMORY_TO_PERIPH
-Dma.I2C1_TX.7.Instance=DMA1_Channel6
-Dma.I2C1_TX.7.MemDataAlignment=DMA_MDATAALIGN_BYTE
-Dma.I2C1_TX.7.MemInc=DMA_MINC_ENABLE
-Dma.I2C1_TX.7.Mode=DMA_NORMAL
-Dma.I2C1_TX.7.PeriphDataAlignment=DMA_PDATAALIGN_BYTE
-Dma.I2C1_TX.7.PeriphInc=DMA_PINC_DISABLE
-Dma.I2C1_TX.7.Priority=DMA_PRIORITY_LOW
-Dma.I2C1_TX.7.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlignment,MemDataAlignment,Mode,Priority
Dma.Request0=ADC1
Dma.Request1=UART5_RX
Dma.Request2=UART5_TX
Dma.Request3=SPI2_TX
Dma.Request4=USART1_RX
Dma.Request5=USART1_TX
-Dma.Request6=I2C1_RX
-Dma.Request7=I2C1_TX
-Dma.Request8=ADC2
-Dma.RequestsNb=9
+Dma.RequestsNb=6
Dma.SPI2_TX.3.Direction=DMA_MEMORY_TO_PERIPH
Dma.SPI2_TX.3.Instance=DMA1_Channel5
Dma.SPI2_TX.3.MemDataAlignment=DMA_MDATAALIGN_BYTE
@@ -166,135 +126,134 @@ Dma.USART1_TX.5.Priority=DMA_PRIORITY_LOW
Dma.USART1_TX.5.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlignment,MemDataAlignment,Mode,Priority
File.Version=6
GPIO.groupedBy=Group By Peripherals
-I2C1.I2C_Fall_Time=0
-I2C1.I2C_Rise_Time=0
-I2C1.I2C_Speed_Mode=I2C_Standard
-I2C1.IPParameters=Speed,I2C_Speed_Mode,I2C_Rise_Time,I2C_Fall_Time
-I2C1.Speed=100
KeepUserPlacement=false
Mcu.CPN=STM32L476VGT6
Mcu.Family=STM32L4
Mcu.IP0=ADC1
-Mcu.IP1=ADC2
-Mcu.IP10=TIM2
-Mcu.IP11=TIM3
-Mcu.IP12=TIM6
-Mcu.IP13=TIM7
+Mcu.IP1=DAC1
+Mcu.IP10=TIM6
+Mcu.IP11=TIM7
+Mcu.IP12=TIM16
+Mcu.IP13=TIM17
Mcu.IP14=UART5
Mcu.IP15=USART1
-Mcu.IP2=DAC1
-Mcu.IP3=DMA
-Mcu.IP4=I2C1
-Mcu.IP5=NVIC
-Mcu.IP6=RCC
-Mcu.IP7=SPI1
-Mcu.IP8=SPI2
-Mcu.IP9=SYS
+Mcu.IP2=DMA
+Mcu.IP3=NVIC
+Mcu.IP4=RCC
+Mcu.IP5=SPI1
+Mcu.IP6=SPI2
+Mcu.IP7=SYS
+Mcu.IP8=TIM2
+Mcu.IP9=TIM3
Mcu.IPNb=16
Mcu.Name=STM32L476V(C-E-G)Tx
Mcu.Package=LQFP100
-Mcu.Pin0=PE5
-Mcu.Pin1=PH0-OSC_IN (PH0)
-Mcu.Pin10=PA3
-Mcu.Pin11=PA4
-Mcu.Pin12=PA5
-Mcu.Pin13=PA6
-Mcu.Pin14=PA7
-Mcu.Pin15=PC4
-Mcu.Pin16=PC5
-Mcu.Pin17=PB0
-Mcu.Pin18=PB1
-Mcu.Pin19=PB2
-Mcu.Pin2=PH1-OSC_OUT (PH1)
-Mcu.Pin20=PE7
-Mcu.Pin21=PE8
-Mcu.Pin22=PE9
-Mcu.Pin23=PE15
-Mcu.Pin24=PB10
-Mcu.Pin25=PB11
-Mcu.Pin26=PB12
-Mcu.Pin27=PB13
-Mcu.Pin28=PB15
-Mcu.Pin29=PD8
-Mcu.Pin3=PC0
-Mcu.Pin30=PD9
-Mcu.Pin31=PD10
-Mcu.Pin32=PD11
-Mcu.Pin33=PD12
-Mcu.Pin34=PD13
-Mcu.Pin35=PD14
-Mcu.Pin36=PD15
-Mcu.Pin37=PC6
-Mcu.Pin38=PC7
-Mcu.Pin39=PC8
-Mcu.Pin4=PC1
-Mcu.Pin40=PC9
-Mcu.Pin41=PA12
-Mcu.Pin42=PA13 (JTMS-SWDIO)
-Mcu.Pin43=PA14 (JTCK-SWCLK)
-Mcu.Pin44=PA15 (JTDI)
-Mcu.Pin45=PC10
-Mcu.Pin46=PC12
-Mcu.Pin47=PD0
-Mcu.Pin48=PD2
-Mcu.Pin49=PD5
-Mcu.Pin5=PC2
-Mcu.Pin50=PD6
-Mcu.Pin51=PD7
-Mcu.Pin52=PB3 (JTDO-TRACESWO)
-Mcu.Pin53=PB4 (NJTRST)
-Mcu.Pin54=PB5
-Mcu.Pin55=PB6
-Mcu.Pin56=PB7
-Mcu.Pin57=PB8
-Mcu.Pin58=PB9
-Mcu.Pin59=PE0
-Mcu.Pin6=PC3
-Mcu.Pin60=PE1
-Mcu.Pin61=VP_ADC1_TempSens_Input
-Mcu.Pin62=VP_ADC1_Vref_Input
-Mcu.Pin63=VP_SYS_VS_Systick
-Mcu.Pin64=VP_TIM2_VS_ClockSourceINT
-Mcu.Pin65=VP_TIM3_VS_ClockSourceINT
-Mcu.Pin66=VP_TIM6_VS_ClockSourceINT
-Mcu.Pin67=VP_TIM7_VS_ClockSourceINT
-Mcu.Pin68=VP_STMicroelectronics.X-CUBE-ALGOBUILD_VS_DSPOoLibraryJjLibrary_1.3.0_1.3.0
-Mcu.Pin7=PA0
-Mcu.Pin8=PA1
-Mcu.Pin9=PA2
-Mcu.PinsNb=69
+Mcu.Pin0=PE4
+Mcu.Pin1=PE5
+Mcu.Pin10=PA2
+Mcu.Pin11=PA3
+Mcu.Pin12=PA4
+Mcu.Pin13=PA5
+Mcu.Pin14=PA6
+Mcu.Pin15=PA7
+Mcu.Pin16=PC4
+Mcu.Pin17=PC5
+Mcu.Pin18=PB0
+Mcu.Pin19=PB1
+Mcu.Pin2=PH0-OSC_IN (PH0)
+Mcu.Pin20=PB2
+Mcu.Pin21=PE7
+Mcu.Pin22=PE8
+Mcu.Pin23=PE9
+Mcu.Pin24=PE15
+Mcu.Pin25=PB10
+Mcu.Pin26=PB11
+Mcu.Pin27=PB12
+Mcu.Pin28=PB13
+Mcu.Pin29=PB14
+Mcu.Pin3=PH1-OSC_OUT (PH1)
+Mcu.Pin30=PB15
+Mcu.Pin31=PD8
+Mcu.Pin32=PD9
+Mcu.Pin33=PD10
+Mcu.Pin34=PD11
+Mcu.Pin35=PD12
+Mcu.Pin36=PD13
+Mcu.Pin37=PD14
+Mcu.Pin38=PD15
+Mcu.Pin39=PC6
+Mcu.Pin4=PC0
+Mcu.Pin40=PC7
+Mcu.Pin41=PC8
+Mcu.Pin42=PC9
+Mcu.Pin43=PA12
+Mcu.Pin44=PA13 (JTMS-SWDIO)
+Mcu.Pin45=PA14 (JTCK-SWCLK)
+Mcu.Pin46=PA15 (JTDI)
+Mcu.Pin47=PC10
+Mcu.Pin48=PC12
+Mcu.Pin49=PD0
+Mcu.Pin5=PC1
+Mcu.Pin50=PD2
+Mcu.Pin51=PD4
+Mcu.Pin52=PD5
+Mcu.Pin53=PD6
+Mcu.Pin54=PD7
+Mcu.Pin55=PB3 (JTDO-TRACESWO)
+Mcu.Pin56=PB4 (NJTRST)
+Mcu.Pin57=PB5
+Mcu.Pin58=PB6
+Mcu.Pin59=PB7
+Mcu.Pin6=PC2
+Mcu.Pin60=PB8
+Mcu.Pin61=PB9
+Mcu.Pin62=VP_ADC1_TempSens_Input
+Mcu.Pin63=VP_ADC1_Vref_Input
+Mcu.Pin64=VP_SYS_VS_Systick
+Mcu.Pin65=VP_TIM2_VS_ClockSourceINT
+Mcu.Pin66=VP_TIM3_VS_ClockSourceINT
+Mcu.Pin67=VP_TIM6_VS_ClockSourceINT
+Mcu.Pin68=VP_TIM7_VS_ClockSourceINT
+Mcu.Pin69=VP_TIM16_VS_ClockSourceINT
+Mcu.Pin7=PC3
+Mcu.Pin70=VP_TIM17_VS_ClockSourceINT
+Mcu.Pin71=VP_STMicroelectronics.X-CUBE-ALGOBUILD_VS_DSPOoLibraryJjLibrary_1.3.0_1.3.0
+Mcu.Pin8=PA0
+Mcu.Pin9=PA1
+Mcu.PinsNb=72
Mcu.ThirdParty0=STMicroelectronics.X-CUBE-ALGOBUILD.1.3.0
Mcu.ThirdPartyNb=1
Mcu.UserConstants=
Mcu.UserName=STM32L476VGTx
-MxCube.Version=6.10.0
-MxDb.Version=DB.6.0.100
-NVIC.ADC1_2_IRQn=true\:14\:0\:true\:false\:true\:true\:true\:true
+MxCube.Version=6.9.2
+MxDb.Version=DB.6.0.92
+NVIC.ADC1_2_IRQn=true\:5\:0\:true\:false\:true\:true\:true\:true
NVIC.BusFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
-NVIC.DMA1_Channel1_IRQn=true\:14\:0\:true\:false\:true\:false\:true\:true
-NVIC.DMA1_Channel2_IRQn=true\:0\:0\:false\:false\:true\:false\:true\:true
-NVIC.DMA1_Channel5_IRQn=true\:14\:0\:true\:false\:true\:false\:true\:true
-NVIC.DMA1_Channel6_IRQn=true\:0\:0\:false\:false\:true\:false\:true\:true
-NVIC.DMA1_Channel7_IRQn=true\:0\:0\:false\:false\:true\:false\:true\:true
-NVIC.DMA2_Channel1_IRQn=true\:0\:0\:false\:false\:true\:false\:true\:true
-NVIC.DMA2_Channel2_IRQn=true\:0\:0\:false\:false\:true\:false\:true\:true
-NVIC.DMA2_Channel6_IRQn=true\:0\:0\:false\:false\:true\:false\:true\:true
-NVIC.DMA2_Channel7_IRQn=true\:0\:0\:false\:false\:true\:false\:true\:true
+NVIC.DMA1_Channel1_IRQn=true\:5\:0\:true\:false\:true\:false\:true\:true
+NVIC.DMA1_Channel5_IRQn=true\:5\:0\:true\:false\:true\:false\:true\:true
+NVIC.DMA2_Channel1_IRQn=true\:5\:0\:true\:false\:true\:false\:true\:true
+NVIC.DMA2_Channel2_IRQn=true\:5\:0\:true\:false\:true\:false\:true\:true
+NVIC.DMA2_Channel6_IRQn=true\:5\:0\:true\:false\:true\:false\:true\:true
+NVIC.DMA2_Channel7_IRQn=true\:5\:0\:true\:false\:true\:false\:true\:true
NVIC.DebugMonitor_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
+NVIC.EXTI0_IRQn=true\:0\:0\:false\:false\:true\:true\:true\:true
NVIC.ForceEnableDMAVector=true
NVIC.HardFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
-NVIC.I2C1_EV_IRQn=true\:0\:0\:false\:false\:true\:true\:true\:true
NVIC.MemoryManagement_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
NVIC.NonMaskableInt_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
NVIC.PendSV_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
NVIC.PriorityGroup=NVIC_PRIORITYGROUP_4
NVIC.SVCall_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
NVIC.SysTick_IRQn=true\:15\:0\:true\:false\:true\:false\:true\:false
+NVIC.TIM1_TRG_COM_TIM17_IRQn=true\:5\:0\:true\:false\:true\:true\:true\:true
+NVIC.TIM1_UP_TIM16_IRQn=true\:15\:0\:true\:false\:true\:true\:true\:true
NVIC.TIM6_DAC_IRQn=true\:6\:0\:true\:false\:true\:true\:true\:true
NVIC.TIM7_IRQn=true\:1\:0\:true\:false\:true\:true\:true\:true
-NVIC.UART5_IRQn=true\:0\:0\:true\:false\:true\:true\:true\:true
+NVIC.UART5_IRQn=true\:3\:0\:true\:false\:true\:true\:true\:true
NVIC.USART1_IRQn=true\:0\:0\:true\:false\:true\:true\:true\:true
NVIC.UsageFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
+PA0.GPIOParameters=GPIO_Label
+PA0.GPIO_Label=ADC_LOOP_CHANNEL
PA0.Signal=ADCx_IN5
PA1.GPIOParameters=GPIO_Label
PA1.GPIO_Label=ADC_PSB_CHANNEL
@@ -333,10 +292,9 @@ PB0.GPIOParameters=GPIO_PuPd,GPIO_Label
PB0.GPIO_Label=HART_PWR
PB0.GPIO_PuPd=GPIO_PULLUP
PB0.Signal=GPIO_Output
-PB1.GPIOParameters=GPIO_PuPd,GPIO_Label
-PB1.GPIO_Label=IP_PWR
-PB1.GPIO_PuPd=GPIO_PULLUP
-PB1.Signal=GPIO_Output
+PB1.GPIOParameters=GPIO_Label
+PB1.GPIO_Label=ADC_VDD_CHANNEL
+PB1.Signal=ADCx_IN16
PB10.GPIOParameters=GPIO_PuPd,GPIO_Label,GPIO_ModeDefaultOutputPP
PB10.GPIO_Label=LCD_PWR
PB10.GPIO_ModeDefaultOutputPP=GPIO_MODE_OUTPUT_PP
@@ -355,6 +313,10 @@ PB13.GPIO_Label=LCD_SCK
PB13.GPIO_PuPd=GPIO_PULLUP
PB13.Mode=TX_Only_Simplex_Unidirect_Master
PB13.Signal=SPI2_SCK
+PB14.GPIOParameters=GPIO_PuPd,GPIO_Label
+PB14.GPIO_Label=LCD_EXTCOMIN
+PB14.GPIO_PuPd=GPIO_PULLUP
+PB14.Signal=GPIO_Input
PB15.GPIOParameters=GPIO_PuPd,GPIO_Label
PB15.GPIO_Label=LCD_MOSI
PB15.GPIO_PuPd=GPIO_PULLUP
@@ -383,14 +345,16 @@ PB7.GPIOParameters=GPIO_Label
PB7.GPIO_Label=HART_RX
PB7.Mode=Asynchronous
PB7.Signal=USART1_RX
-PB8.GPIOParameters=GPIO_Label
+PB8.GPIOParameters=GPIO_PuPd,GPIO_Label,GPIO_ModeDefaultOutputPP
PB8.GPIO_Label=I2C1_SCL
-PB8.Mode=I2C
-PB8.Signal=I2C1_SCL
-PB9.GPIOParameters=GPIO_Label
+PB8.GPIO_ModeDefaultOutputPP=GPIO_MODE_OUTPUT_OD
+PB8.GPIO_PuPd=GPIO_NOPULL
+PB8.Signal=GPIO_Output
+PB9.GPIOParameters=GPIO_PuPd,GPIO_Label,GPIO_ModeDefaultOutputPP
PB9.GPIO_Label=I2C1_SDA
-PB9.Mode=I2C
-PB9.Signal=I2C1_SDA
+PB9.GPIO_ModeDefaultOutputPP=GPIO_MODE_OUTPUT_OD
+PB9.GPIO_PuPd=GPIO_NOPULL
+PB9.Signal=GPIO_Output
PC0.GPIOParameters=GPIO_PuPd,GPIO_Label,GPIO_ModeDefaultOutputPP
PC0.GPIO_Label=RTC_SCL
PC0.GPIO_ModeDefaultOutputPP=GPIO_MODE_OUTPUT_OD
@@ -423,26 +387,26 @@ PC5.GPIO_Label=ADC_BPB_CHANNEL
PC5.Signal=ADCx_IN14
PC6.GPIOParameters=GPIO_PuPd,GPIO_Label
PC6.GPIO_Label=KEY4
-PC6.GPIO_PuPd=GPIO_NOPULL
+PC6.GPIO_PuPd=GPIO_PULLUP
PC6.Signal=GPIO_Input
PC7.GPIOParameters=GPIO_PuPd,GPIO_Label
PC7.GPIO_Label=KEY3
-PC7.GPIO_PuPd=GPIO_NOPULL
+PC7.GPIO_PuPd=GPIO_PULLUP
PC7.Signal=GPIO_Input
PC8.GPIOParameters=GPIO_PuPd,GPIO_Label
PC8.GPIO_Label=KEY2
-PC8.GPIO_PuPd=GPIO_NOPULL
+PC8.GPIO_PuPd=GPIO_PULLUP
PC8.Signal=GPIO_Input
PC9.GPIOParameters=GPIO_PuPd,GPIO_Label
PC9.GPIO_Label=KEY1
-PC9.GPIO_PuPd=GPIO_NOPULL
+PC9.GPIO_PuPd=GPIO_PULLUP
PC9.Signal=GPIO_Input
PCC.Checker=true
PCC.Line=STM32L4x6
PCC.MCU=STM32L476V(C-E-G)Tx
PCC.PartNumber=STM32L476VGTx
PCC.Seq0=2
-PCC.Seq0.Step0.Average_Current=799.6 \u00B5A
+PCC.Seq0.Step0.Average_Current=801.4 \u00B5A
PCC.Seq0.Step0.CPU_Frequency=4 MHz
PCC.Seq0.Step0.Category=In DS Table
PCC.Seq0.Step0.DMIPS=5.0
@@ -451,7 +415,7 @@ PCC.Seq0.Step0.Frequency=4 MHz
PCC.Seq0.Step0.Memory=FLASH/ART/Cache
PCC.Seq0.Step0.Mode=RUN
PCC.Seq0.Step0.Oscillator=HSE
-PCC.Seq0.Step0.Peripherals=ADC1\:fs_10_ksps AHB_APB1_Bridge AHB_APB2_Bridge DAC1\:OUT2-Buffer_OFF-Middle_code GPIOA GPIOB GPIOC GPIOD GPIOE GPIOH I2C1 SPI1 SPI2 TIM2 TIM3 TIM6 TIM7 UART5 USART1
+PCC.Seq0.Step0.Peripherals=ADC1\:fs_10_ksps AHB_APB1_Bridge AHB_APB2_Bridge GPIOA GPIOB GPIOC GPIOD GPIOE GPIOH I2C1 SPI1 SPI2 TIM2 TIM3 TIM6 TIM7 TIM17 UART5 USART1
PCC.Seq0.Step0.TaMax=104.9
PCC.Seq0.Step0.User's_Consumption=0 mA
PCC.Seq0.Step0.Vcore=Range2-Medium
@@ -475,37 +439,46 @@ PCC.Seq0.Step1.Voltage_Source=Battery
PCC.Series=STM32L4
PCC.Temperature=25
PCC.Vdd=3.0
-PD0.GPIOParameters=GPIO_Label
+PD0.GPIOParameters=GPIO_PuPd,GPIO_Label,GPIO_ModeDefaultEXTI
PD0.GPIO_Label=HART_CD
-PD0.Signal=GPIO_Input
-PD10.GPIOParameters=PinState,GPIO_Label
+PD0.GPIO_ModeDefaultEXTI=GPIO_MODE_IT_FALLING
+PD0.GPIO_PuPd=GPIO_PULLUP
+PD0.Signal=GPXTI0
+PD10.GPIOParameters=PinState,GPIO_PuPd,GPIO_Label
PD10.GPIO_Label=LED2
+PD10.GPIO_PuPd=GPIO_PULLUP
PD10.PinState=GPIO_PIN_SET
PD10.Signal=GPIO_Output
-PD11.GPIOParameters=PinState,GPIO_Label
+PD11.GPIOParameters=PinState,GPIO_PuPd,GPIO_Label
PD11.GPIO_Label=LED3
+PD11.GPIO_PuPd=GPIO_PULLUP
PD11.PinState=GPIO_PIN_SET
PD11.Signal=GPIO_Output
-PD12.GPIOParameters=PinState,GPIO_Label
+PD12.GPIOParameters=PinState,GPIO_PuPd,GPIO_Label
PD12.GPIO_Label=LED4
+PD12.GPIO_PuPd=GPIO_PULLUP
PD12.PinState=GPIO_PIN_SET
PD12.Signal=GPIO_Output
-PD13.GPIOParameters=PinState,GPIO_Label
+PD13.GPIOParameters=PinState,GPIO_PuPd,GPIO_Label
PD13.GPIO_Label=LED5
+PD13.GPIO_PuPd=GPIO_PULLUP
PD13.PinState=GPIO_PIN_SET
PD13.Signal=GPIO_Output
PD14.GPIOParameters=GPIO_PuPd,GPIO_Label
PD14.GPIO_Label=KEY6
-PD14.GPIO_PuPd=GPIO_NOPULL
+PD14.GPIO_PuPd=GPIO_PULLUP
PD14.Signal=GPIO_Input
PD15.GPIOParameters=GPIO_PuPd,GPIO_Label
PD15.GPIO_Label=KEY5
-PD15.GPIO_PuPd=GPIO_NOPULL
+PD15.GPIO_PuPd=GPIO_PULLUP
PD15.Signal=GPIO_Input
PD2.GPIOParameters=GPIO_Label
PD2.GPIO_Label=BLE_RX
PD2.Mode=Asynchronous
PD2.Signal=UART5_RX
+PD4.GPIOParameters=GPIO_Label
+PD4.GPIO_Label=EE3_CS
+PD4.Signal=GPIO_Output
PD5.GPIOParameters=GPIO_PuPd,GPIO_Label
PD5.GPIO_Label=EE2_CS
PD5.GPIO_PuPd=GPIO_NOPULL
@@ -522,27 +495,20 @@ PD8.GPIO_Label=LCD_DISP
PD8.GPIO_PuPd=GPIO_NOPULL
PD8.PinState=GPIO_PIN_RESET
PD8.Signal=GPIO_Output
-PD9.GPIOParameters=PinState,GPIO_Label
+PD9.GPIOParameters=PinState,GPIO_PuPd,GPIO_Label
PD9.GPIO_Label=LED1
+PD9.GPIO_PuPd=GPIO_PULLUP
PD9.PinState=GPIO_PIN_SET
PD9.Signal=GPIO_Output
-PE0.GPIOParameters=GPIO_PuPd,GPIO_Label,GPIO_ModeDefaultOutputPP
-PE0.GPIO_Label=I2C2_SCL
-PE0.GPIO_ModeDefaultOutputPP=GPIO_MODE_OUTPUT_OD
-PE0.GPIO_PuPd=GPIO_NOPULL
-PE0.Signal=GPIO_Output
-PE1.GPIOParameters=GPIO_PuPd,GPIO_Label,GPIO_ModeDefaultOutputPP
-PE1.GPIO_Label=I2C2_SDA
-PE1.GPIO_ModeDefaultOutputPP=GPIO_MODE_OUTPUT_OD
-PE1.GPIO_PuPd=GPIO_NOPULL
-PE1.Signal=GPIO_Output
PE15.GPIOParameters=GPIO_PuPd,GPIO_Label
PE15.GPIO_Label=KEY_AUTO
-PE15.GPIO_PuPd=GPIO_NOPULL
+PE15.GPIO_PuPd=GPIO_PULLUP
PE15.Signal=GPIO_Input
-PE5.GPIOParameters=GPIO_Label
-PE5.GPIO_Label=PWM_OUT
-PE5.Signal=S_TIM3_CH3
+PE4.Signal=S_TIM3_CH2
+PE5.GPIOParameters=GPIO_PuPd,GPIO_Label
+PE5.GPIO_Label=DAC161P997
+PE5.GPIO_PuPd=GPIO_PULLDOWN
+PE5.Signal=GPIO_Output
PE7.GPIOParameters=GPIO_Label
PE7.GPIO_Label=BP_A_PWR
PE7.Signal=GPIO_Output
@@ -569,81 +535,84 @@ ProjectManager.DeviceId=STM32L476VGTx
ProjectManager.FirmwarePackage=STM32Cube FW_L4 V1.18.0
ProjectManager.FreePins=true
ProjectManager.HalAssertFull=false
-ProjectManager.HeapSize=0x800
+ProjectManager.HeapSize=0x200
ProjectManager.KeepUserCode=true
-ProjectManager.LastFirmware=true
+ProjectManager.LastFirmware=false
ProjectManager.LibraryCopy=1
ProjectManager.MainLocation=Core/Src
ProjectManager.NoMain=false
ProjectManager.PreviousToolchain=
ProjectManager.ProjectBuild=false
-ProjectManager.ProjectFileName=controller-v2.ioc
-ProjectManager.ProjectName=controller-v2
+ProjectManager.ProjectFileName=controller.ioc
+ProjectManager.ProjectName=controller
ProjectManager.ProjectStructure=
ProjectManager.RegisterCallBack=
-ProjectManager.StackSize=0x1000
+ProjectManager.StackSize=0x1200
ProjectManager.TargetToolchain=MDK-ARM V5.32
ProjectManager.ToolChainLocation=
ProjectManager.UAScriptAfterPath=
ProjectManager.UAScriptBeforePath=
ProjectManager.UnderRoot=false
-ProjectManager.functionlistsort=1-SystemClock_Config-RCC-false-LL-false,2-MX_GPIO_Init-GPIO-false-LL-true,3-MX_DMA_Init-DMA-false-LL-true,4-MX_ADC1_Init-ADC1-false-LL-true,5-MX_TIM3_Init-TIM3-false-LL-true,6-MX_DAC1_Init-DAC1-false-LL-true,7-MX_SPI2_Init-SPI2-false-LL-true,8-MX_SPI1_Init-SPI1-false-LL-true,9-MX_TIM2_Init-TIM2-false-LL-true,10-MX_UART5_Init-UART5-false-LL-true,11-MX_USART1_UART_Init-USART1-false-LL-true,12-MX_TIM6_Init-TIM6-false-LL-true,13-MX_TIM7_Init-TIM7-false-LL-true,14-MX_I2C1_Init-I2C1-false-LL-true,15-MX_ADC2_Init-ADC2-false-LL-true
-RCC.ADCFreq_Value=32000000
-RCC.AHBCLKDivider=RCC_SYSCLK_DIV8
-RCC.AHBFreq_Value=4000000
-RCC.APB1Freq_Value=4000000
-RCC.APB1TimFreq_Value=4000000
-RCC.APB2Freq_Value=4000000
-RCC.APB2TimFreq_Value=4000000
-RCC.CortexFreq_Value=4000000
-RCC.DFSDMFreq_Value=4000000
-RCC.FCLKCortexFreq_Value=4000000
+ProjectManager.functionlistsort=1-SystemClock_Config-RCC-false-LL-false,2-MX_GPIO_Init-GPIO-false-LL-true,3-MX_DMA_Init-DMA-false-LL-true,4-MX_ADC1_Init-ADC1-false-LL-true,5-MX_TIM3_Init-TIM3-false-LL-true,6-MX_DAC1_Init-DAC1-false-LL-true,7-MX_SPI2_Init-SPI2-false-LL-true,8-MX_SPI1_Init-SPI1-false-LL-true,9-MX_TIM2_Init-TIM2-false-LL-true,10-MX_UART5_Init-UART5-false-LL-true,11-MX_USART1_UART_Init-USART1-false-LL-true,12-MX_TIM6_Init-TIM6-false-LL-true,13-MX_TIM7_Init-TIM7-false-LL-true,14-MX_TIM17_Init-TIM17-false-LL-true,15-MX_TIM16_Init-TIM16-false-LL-true
+RCC.ADCFreq_Value=8294400
+RCC.AHBCLKDivider=RCC_SYSCLK_DIV2
+RCC.AHBFreq_Value=5529600
+RCC.APB1Freq_Value=5529600
+RCC.APB1TimFreq_Value=5529600
+RCC.APB2Freq_Value=5529600
+RCC.APB2TimFreq_Value=5529600
+RCC.CortexFreq_Value=5529600
+RCC.DFSDMFreq_Value=5529600
+RCC.FCLKCortexFreq_Value=5529600
RCC.FamilyName=M
-RCC.HCLKFreq_Value=4000000
-RCC.HSE_VALUE=8000000
+RCC.HCLKFreq_Value=5529600
+RCC.HSE_VALUE=11059200
RCC.HSI_VALUE=16000000
-RCC.I2C1Freq_Value=4000000
-RCC.I2C2Freq_Value=4000000
-RCC.I2C3Freq_Value=4000000
-RCC.IPParameters=ADCFreq_Value,AHBCLKDivider,AHBFreq_Value,APB1Freq_Value,APB1TimFreq_Value,APB2Freq_Value,APB2TimFreq_Value,CortexFreq_Value,DFSDMFreq_Value,FCLKCortexFreq_Value,FamilyName,HCLKFreq_Value,HSE_VALUE,HSI_VALUE,I2C1Freq_Value,I2C2Freq_Value,I2C3Freq_Value,LPTIM1Freq_Value,LPTIM2Freq_Value,LPUART1Freq_Value,LSCOPinFreq_Value,LSE_VALUE,LSI_VALUE,MCO1PinFreq_Value,MSIClockRange,MSI_VALUE,PLLPoutputFreq_Value,PLLQoutputFreq_Value,PLLRCLKFreq_Value,PLLSAI1PoutputFreq_Value,PLLSAI1QoutputFreq_Value,PLLSAI1RoutputFreq_Value,PLLSAI2PoutputFreq_Value,PLLSAI2RoutputFreq_Value,PLLSourceVirtual,PREFETCH_ENABLE,PWRFreq_Value,PWR_Regulator_Voltage_Scale,RNGFreq_Value,SAI1Freq_Value,SAI2Freq_Value,SDMMCFreq_Value,SWPMI1Freq_Value,SYSCLKFreq_VALUE,SYSCLKSource,UART4Freq_Value,UART5Freq_Value,USART1Freq_Value,USART2Freq_Value,USART3Freq_Value,USBFreq_Value,VCOInputFreq_Value,VCOOutputFreq_Value,VCOSAI1OutputFreq_Value,VCOSAI2OutputFreq_Value
-RCC.LPTIM1Freq_Value=4000000
-RCC.LPTIM2Freq_Value=4000000
-RCC.LPUART1Freq_Value=4000000
+RCC.I2C1Freq_Value=5529600
+RCC.I2C2Freq_Value=5529600
+RCC.I2C3Freq_Value=5529600
+RCC.IPParameters=ADCFreq_Value,AHBCLKDivider,AHBFreq_Value,APB1Freq_Value,APB1TimFreq_Value,APB2Freq_Value,APB2TimFreq_Value,CortexFreq_Value,DFSDMFreq_Value,FCLKCortexFreq_Value,FamilyName,HCLKFreq_Value,HSE_VALUE,HSI_VALUE,I2C1Freq_Value,I2C2Freq_Value,I2C3Freq_Value,LPTIM1Freq_Value,LPTIM2Freq_Value,LPUART1Freq_Value,LSCOPinFreq_Value,LSE_VALUE,LSI_VALUE,MCO1PinFreq_Value,MSIClockRange,MSI_VALUE,PLLM,PLLN,PLLPoutputFreq_Value,PLLQoutputFreq_Value,PLLR,PLLRCLKFreq_Value,PLLSAI1N,PLLSAI1PoutputFreq_Value,PLLSAI1QoutputFreq_Value,PLLSAI1R,PLLSAI1RoutputFreq_Value,PLLSAI2PoutputFreq_Value,PLLSAI2RoutputFreq_Value,PLLSourceVirtual,PWRFreq_Value,RNGFreq_Value,SAI1Freq_Value,SAI2Freq_Value,SDMMCFreq_Value,SWPMI1Freq_Value,SYSCLKFreq_VALUE,SYSCLKSource,UART4Freq_Value,UART5Freq_Value,USART1Freq_Value,USART2Freq_Value,USART3Freq_Value,USBFreq_Value,VCOInputFreq_Value,VCOOutputFreq_Value,VCOSAI1OutputFreq_Value,VCOSAI2OutputFreq_Value
+RCC.LPTIM1Freq_Value=5529600
+RCC.LPTIM2Freq_Value=5529600
+RCC.LPUART1Freq_Value=5529600
RCC.LSCOPinFreq_Value=32000
RCC.LSE_VALUE=32768
RCC.LSI_VALUE=32000
-RCC.MCO1PinFreq_Value=32000000
+RCC.MCO1PinFreq_Value=11059200
RCC.MSIClockRange=RCC_MSIRANGE_8
RCC.MSI_VALUE=16000000
-RCC.PLLPoutputFreq_Value=9142857.142857144
-RCC.PLLQoutputFreq_Value=32000000
-RCC.PLLRCLKFreq_Value=32000000
-RCC.PLLSAI1PoutputFreq_Value=9142857.142857144
-RCC.PLLSAI1QoutputFreq_Value=32000000
-RCC.PLLSAI1RoutputFreq_Value=32000000
-RCC.PLLSAI2PoutputFreq_Value=9142857.142857144
-RCC.PLLSAI2RoutputFreq_Value=32000000
+RCC.PLLM=2
+RCC.PLLN=12
+RCC.PLLPoutputFreq_Value=9479314.285714285
+RCC.PLLQoutputFreq_Value=33177600
+RCC.PLLR=RCC_PLLR_DIV6
+RCC.PLLRCLKFreq_Value=11059200
+RCC.PLLSAI1N=12
+RCC.PLLSAI1PoutputFreq_Value=9479314.285714285
+RCC.PLLSAI1QoutputFreq_Value=33177600
+RCC.PLLSAI1R=RCC_PLLR_DIV8
+RCC.PLLSAI1RoutputFreq_Value=8294400
+RCC.PLLSAI2PoutputFreq_Value=6319542.857142857
+RCC.PLLSAI2RoutputFreq_Value=22118400
RCC.PLLSourceVirtual=RCC_PLLSOURCE_HSE
-RCC.PREFETCH_ENABLE=1
-RCC.PWRFreq_Value=32000000
-RCC.PWR_Regulator_Voltage_Scale=PWR_REGULATOR_VOLTAGE_SCALE1
-RCC.RNGFreq_Value=32000000
-RCC.SAI1Freq_Value=9142857.142857144
-RCC.SAI2Freq_Value=9142857.142857144
-RCC.SDMMCFreq_Value=32000000
-RCC.SWPMI1Freq_Value=4000000
-RCC.SYSCLKFreq_VALUE=32000000
+RCC.PWRFreq_Value=11059200
+RCC.RNGFreq_Value=33177600
+RCC.SAI1Freq_Value=9479314.285714285
+RCC.SAI2Freq_Value=9479314.285714285
+RCC.SDMMCFreq_Value=33177600
+RCC.SWPMI1Freq_Value=5529600
+RCC.SYSCLKFreq_VALUE=11059200
RCC.SYSCLKSource=RCC_SYSCLKSOURCE_PLLCLK
-RCC.UART4Freq_Value=4000000
-RCC.UART5Freq_Value=4000000
-RCC.USART1Freq_Value=4000000
-RCC.USART2Freq_Value=4000000
-RCC.USART3Freq_Value=4000000
-RCC.USBFreq_Value=32000000
-RCC.VCOInputFreq_Value=8000000
-RCC.VCOOutputFreq_Value=64000000
-RCC.VCOSAI1OutputFreq_Value=64000000
-RCC.VCOSAI2OutputFreq_Value=64000000
+RCC.UART4Freq_Value=5529600
+RCC.UART5Freq_Value=5529600
+RCC.USART1Freq_Value=5529600
+RCC.USART2Freq_Value=5529600
+RCC.USART3Freq_Value=5529600
+RCC.USBFreq_Value=33177600
+RCC.VCOInputFreq_Value=5529600
+RCC.VCOOutputFreq_Value=66355200
+RCC.VCOSAI1OutputFreq_Value=66355200
+RCC.VCOSAI2OutputFreq_Value=44236800
SH.ADCx_IN11.0=ADC1_IN11,IN11-Single-Ended
SH.ADCx_IN11.ConfNb=1
SH.ADCx_IN12.0=ADC1_IN12,IN12-Single-Ended
@@ -652,12 +621,12 @@ SH.ADCx_IN13.0=ADC1_IN13,IN13-Single-Ended
SH.ADCx_IN13.ConfNb=1
SH.ADCx_IN14.0=ADC1_IN14,IN14-Single-Ended
SH.ADCx_IN14.ConfNb=1
+SH.ADCx_IN16.0=ADC1_IN16,IN16-Single-Ended
+SH.ADCx_IN16.ConfNb=1
SH.ADCx_IN5.0=ADC1_IN5,IN5-Single-Ended
-SH.ADCx_IN5.1=ADC2_IN5,IN5-Single-Ended
-SH.ADCx_IN5.ConfNb=2
+SH.ADCx_IN5.ConfNb=1
SH.ADCx_IN6.0=ADC1_IN6,IN6-Single-Ended
-SH.ADCx_IN6.1=ADC2_IN6,IN6-Single-Ended
-SH.ADCx_IN6.ConfNb=2
+SH.ADCx_IN6.ConfNb=1
SH.ADCx_IN7.0=ADC1_IN7,IN7-Single-Ended
SH.ADCx_IN7.ConfNb=1
SH.ADCx_IN8.0=ADC1_IN8,IN8-Single-Ended
@@ -666,21 +635,24 @@ SH.ADCx_IN9.0=ADC1_IN9,IN9-Single-Ended
SH.ADCx_IN9.ConfNb=1
SH.COMP_DAC12_group.0=DAC1_OUT2,DAC_OUT2
SH.COMP_DAC12_group.ConfNb=1
+SH.GPXTI0.0=GPIO_EXTI0
+SH.GPXTI0.ConfNb=1
SH.S_TIM2_CH4.0=TIM2_CH4,PWM Generation4 CH4
SH.S_TIM2_CH4.ConfNb=1
-SH.S_TIM3_CH3.0=TIM3_CH3,PWM Generation3 CH3
-SH.S_TIM3_CH3.ConfNb=1
+SH.S_TIM3_CH2.0=TIM3_CH2,PWM Generation2 CH2
+SH.S_TIM3_CH2.ConfNb=1
+SPI1.BaudRatePrescaler=SPI_BAUDRATEPRESCALER_2
SPI1.CLKPhase=SPI_PHASE_2EDGE
SPI1.CLKPolarity=SPI_POLARITY_HIGH
-SPI1.CalculateBaudRate=2.0 MBits/s
+SPI1.CalculateBaudRate=2.7648 MBits/s
SPI1.DataSize=SPI_DATASIZE_8BIT
SPI1.Direction=SPI_DIRECTION_2LINES
-SPI1.IPParameters=VirtualType,Mode,Direction,CalculateBaudRate,DataSize,CLKPolarity,CLKPhase
+SPI1.IPParameters=VirtualType,Mode,Direction,CalculateBaudRate,DataSize,CLKPolarity,CLKPhase,BaudRatePrescaler
SPI1.Mode=SPI_MODE_MASTER
SPI1.VirtualType=VM_MASTER
-SPI2.BaudRatePrescaler=SPI_BAUDRATEPRESCALER_2
+SPI2.BaudRatePrescaler=SPI_BAUDRATEPRESCALER_4
SPI2.CLKPolarity=SPI_POLARITY_LOW
-SPI2.CalculateBaudRate=2.0 MBits/s
+SPI2.CalculateBaudRate=1.3824 MBits/s
SPI2.DataSize=SPI_DATASIZE_8BIT
SPI2.Direction=SPI_DIRECTION_2LINES
SPI2.FirstBit=SPI_FIRSTBIT_LSB
@@ -692,27 +664,39 @@ STMicroelectronics.X-CUBE-ALGOBUILD.1.3.0.DSPOoLibraryJjLibrary_Checked=true
STMicroelectronics.X-CUBE-ALGOBUILD.1.3.0.IPParameters=LibraryCcDSPOoLibraryJjDSPOoLibrary
STMicroelectronics.X-CUBE-ALGOBUILD.1.3.0.LibraryCcDSPOoLibraryJjDSPOoLibrary=true
STMicroelectronics.X-CUBE-ALGOBUILD.1.3.0_SwParameter=LibraryCcDSPOoLibraryJjDSPOoLibrary\:true;
+TIM16.AutoReloadPreload=TIM_AUTORELOAD_PRELOAD_ENABLE
+TIM16.IPParameters=Prescaler,Period,AutoReloadPreload
+TIM16.Period=24
+TIM16.Prescaler=552
+TIM17.AutoReloadPreload=TIM_AUTORELOAD_PRELOAD_ENABLE
+TIM17.IPParameters=Prescaler,Period,AutoReloadPreload
+TIM17.Period=999
+TIM17.Prescaler=552
TIM2.AutoReloadPreload=TIM_AUTORELOAD_PRELOAD_ENABLE
TIM2.Channel-PWM\ Generation4\ CH4=TIM_CHANNEL_4
TIM2.ClearChannel4=TIM_CHANNEL_4
TIM2.ClearInputSource=TIM_CLEARINPUTSOURCE_NONE
-TIM2.IPParameters=Channel-PWM Generation4 CH4,Period,AutoReloadPreload,ClearInputSource,ClearChannel4,Prescaler
-TIM2.Period=3999
+TIM2.CounterMode=TIM_COUNTERMODE_UP
+TIM2.IPParameters=Channel-PWM Generation4 CH4,Period,AutoReloadPreload,ClearInputSource,ClearChannel4,Prescaler,OCPolarity_4,CounterMode,OCFastMode_PWM-PWM Generation4 CH4
+TIM2.OCFastMode_PWM-PWM\ Generation4\ CH4=TIM_OCFAST_ENABLE
+TIM2.OCPolarity_4=TIM_OCPOLARITY_HIGH
+TIM2.Period=5529
TIM2.Prescaler=0
TIM3.AutoReloadPreload=TIM_AUTORELOAD_PRELOAD_ENABLE
-TIM3.Channel-PWM\ Generation3\ CH3=TIM_CHANNEL_3
-TIM3.IPParameters=Channel-PWM Generation3 CH3,Period,AutoReloadPreload,Prescaler
-TIM3.Period=3999
+TIM3.Channel-PWM\ Generation2\ CH2=TIM_CHANNEL_2
+TIM3.IPParameters=Period,AutoReloadPreload,Prescaler,Channel-PWM Generation2 CH2,Pulse-PWM Generation2 CH2
+TIM3.Period=11
TIM3.Prescaler=0
+TIM3.Pulse-PWM\ Generation2\ CH2=0
TIM6.AutoReloadPreload=TIM_AUTORELOAD_PRELOAD_ENABLE
TIM6.IPParameters=Prescaler,Period,AutoReloadPreload
TIM6.Period=99
-TIM6.Prescaler=399
+TIM6.Prescaler=552
TIM7.AutoReloadPreload=TIM_AUTORELOAD_PRELOAD_ENABLE
TIM7.IPParameters=Prescaler,Period,AutoReloadPreload
-TIM7.Period=499
-TIM7.Prescaler=399
-UART5.BaudRate=9600
+TIM7.Period=249
+TIM7.Prescaler=552
+UART5.BaudRate=115200
UART5.IPParameters=BaudRate
USART1.BaudRate=1200
USART1.IPParameters=VirtualMode-Asynchronous,BaudRate,WordLength,Parity
@@ -727,6 +711,10 @@ VP_STMicroelectronics.X-CUBE-ALGOBUILD_VS_DSPOoLibraryJjLibrary_1.3.0_1.3.0.Mode
VP_STMicroelectronics.X-CUBE-ALGOBUILD_VS_DSPOoLibraryJjLibrary_1.3.0_1.3.0.Signal=STMicroelectronics.X-CUBE-ALGOBUILD_VS_DSPOoLibraryJjLibrary_1.3.0_1.3.0
VP_SYS_VS_Systick.Mode=SysTick
VP_SYS_VS_Systick.Signal=SYS_VS_Systick
+VP_TIM16_VS_ClockSourceINT.Mode=Enable_Timer
+VP_TIM16_VS_ClockSourceINT.Signal=TIM16_VS_ClockSourceINT
+VP_TIM17_VS_ClockSourceINT.Mode=Enable_Timer
+VP_TIM17_VS_ClockSourceINT.Signal=TIM17_VS_ClockSourceINT
VP_TIM2_VS_ClockSourceINT.Mode=Internal
VP_TIM2_VS_ClockSourceINT.Signal=TIM2_VS_ClockSourceINT
VP_TIM3_VS_ClockSourceINT.Mode=Internal
diff --git a/keilkill.bat b/keilkill.bat
index 91ed224..33f622c 100644
--- a/keilkill.bat
+++ b/keilkill.bat
@@ -22,9 +22,22 @@ del JLinkLog.txt /s
del *.iex /s
del *.htm /s
-del *.sct /s
+@REM del *.sct /s
del *.map /s
del *.dbgconf /s
del *.uvguix.* /s
+
+
+del User\system\src\*.c /s
+del User\system\bsp\*.c /s
+del User\lib\src\*.c /s
+del User\lib\examples\*.c /s
+del User\lib\bootload\*.c /s
+del User\board\src\*.c /s
+del User\application\menus\*.c /s
+for %%i in (User\application\mode\*.c) do (
+ if not "%%~nxi"=="mode.c" if not "%%~nxi"=="mode_pwmp_hd.c" del "%%i"
+)
+
exit