/** * @file ocpp_mv_offline_flash_impl.h * @brief OCPP 离线 MeterValues:仿 `fault_flash_impl` — SPI Flash 线性池 + FRAM 流水号→序号映射 * * **为何更简单** * - Flash 侧为「定长记录数组」:每条在 **该枪半区** 内逻辑序号与物理槽一一对应(`seq` → 地址由宏公式算出)。 * - FRAM 侧存:**每枪下一单调序号** `u32_next_seq[2]`、以及若干行「流水号(tx)+枪号 ↔ 起始序号 + 条数」; * 上送时 `u8_ocpp_mv_offline_map_get(gun, tx...)` 得 `seq_start,count`,再 * `for (k=0;k= 201112L _Static_assert(sizeof(S_OCPP_MV_OFFLINE_MV) == OCPP_MV_OFFLINE_PAYLOAD_BYTES, "MV payload 32B"); _Static_assert(sizeof(S_OCPP_MV_OFFLINE_FRAM_MNG) == 128u, "FRAM mng 128B"); _Static_assert(sizeof(S_OCPP_MV_OFFLINE_FRAM_MNG) <= EEPROM_OCPP_MV_OFFLINE_CTRL_SIZE, "FRAM fit"); #else /* ARMCC v5 不支持 _Static_assert,使用编译期断言替代 */ typedef int __ocpp_mv_size_check_1[(sizeof(S_OCPP_MV_OFFLINE_MV) == OCPP_MV_OFFLINE_PAYLOAD_BYTES) ? 1 : -1]; typedef int __ocpp_mv_size_check_2[(sizeof(S_OCPP_MV_OFFLINE_FRAM_MNG) == 128u) ? 1 : -1]; typedef int __ocpp_mv_size_check_3[(sizeof(S_OCPP_MV_OFFLINE_FRAM_MNG) <= EEPROM_OCPP_MV_OFFLINE_CTRL_SIZE) ? 1 : -1]; #endif /** @brief 上电:从 FRAM 恢复管理块 RAM 镜像,非法则默认并写回 */ void v_ocpp_mv_offline_init(void); /** * @brief 保存一条离线 MV:分配该枪单调序号、写 Flash、更新/追加映射行 * @param u8_gun_no 枪号:0=前半区(枪1),1=后半区(枪2) * @param tx_sn_lo 会话键:当前为 `xDate2Seconds(StartChargeTime)`(单路 U32) * @param tx_sn_hi 当前恒 0(与 `u32_tx_sn_hi` 一致;接口双参仅为与 FRAM 行字段对齐) * @param out_seq 输出本次在该枪下的单调序号 * @return 0 成功;1 参数非法(含枪号越界);2 映射表满;3 Flash 失败;4 FRAM 失败; * 5 流水号已存在但本次序号不连续(调用顺序错误) */ U8_T u8_ocpp_mv_offline_mv_save(U8_T u8_gun_no, U32_T tx_sn_lo, U32_T tx_sn_hi, const S_OCPP_MV_OFFLINE_MV *mv, U32_T *out_seq); /** * @brief 按该枪单调序号读一条 MV(物理槽:`seq % POOL_MAX_PER_GUN`,落在该枪半区) * @return 0 成功;1 参数非法;2 校验/帧头失败 */ U8_T u8_ocpp_mv_offline_mv_read_by_seq(U8_T u8_gun_no, U32_T seq, S_OCPP_MV_OFFLINE_MV *out); /** @brief 判断负载是否为当前版本有效数据 */ U8_T u8_ocpp_mv_offline_mv_is_valid(const S_OCPP_MV_OFFLINE_MV *mv); /** * @brief 查询指定枪上会话键(`tx_sn_lo` + `tx_sn_hi`,当前 hi 恒 0)对应的序号区间(用于上送循环) * @return 0 找到;1 空指针;2 未找到 */ U8_T u8_ocpp_mv_offline_map_get(U8_T u8_gun_no, U32_T tx_sn_lo, U32_T tx_sn_hi, U32_T *seq_start, U16_T *count); /** * @brief 上送完成后删除该枪上映射行(不擦整池 Flash;若需整池清空在 `ocpp_mv_offline_flash_impl.c` 内维护调用) * @return 0 成功;1 未找到;2 FRAM 写失败 */ U8_T u8_ocpp_mv_offline_map_remove(U8_T u8_gun_no, U32_T tx_sn_lo, U32_T tx_sn_hi); /** * @brief 新一笔充电开始前:清除该枪在 FRAM 中的全部 MV 映射行(释放 map 槽位;不擦 SPI Flash 池) * @param[in] u8_gun_no 枪索引 * @return 0 成功;1 枪号非法;2 FRAM 写失败 * @see u8_ocpp_mv_offline_mv_save(映射满时按枪淘汰最旧一行) */ U8_T u8_ocpp_mv_offline_map_clear_gun(U8_T u8_gun_no); /* 整池擦除、FRAM 读写默认块、池容量查询等为模块内部实现,无对外声明。 */ #ifdef __cplusplus } #endif #endif /* OCPP_MV_OFFLINE_FLASH_IMPL_H */