- 启动序列从 app_main.c 拆进 main/bringup.{h,c},宿主机可测:
bringup_devices()(§10.9 第 1~4 步)→ 起 t_safety → bringup_power_restore()(第 5~6 步)
- 六片 INA226 写 Config/Calibration(之前没做,电流恒 0);输入侧 0x43 登记对调接
- 按「意图」逐路上电、错开 100 ms、每路等 PG 500 ms,等不到关回去并记 LOG_EV_PG_TIMEOUT(17)
- 意图只由 power 命令改(cmd_env_t.intent → NVS phonerail/rail_want)
- §10.10 逐行降级:INA/DAC/PCA9555/mux/PRSNT#/CH224A;mux 失联时不碰主干
- BOOT 事件 arg = 复位原因;HUB_RST# 仍只在上电复位时脉冲
- rail_volt_init() 一片失败不再放弃另一片;CH224A 主干 / 通道 5 两处都找
- sim:sim_gpio_rise_us / sim_gpio_set_hook,sim_gpio_drive 可在配置前调
- test_bringup.c 24 例 + test_cmd 意图 1 例,共 425 例全绿;版本 0.1.0-a15
- rack:事件表加 17 PG_TIMEOUT(已部署)
Co-Authored-By: Claude Opus 5.5 <[email protected]>
129 行
4.0 KiB
C
129 行
4.0 KiB
C
/* 五路输出电压的换算与设定。与硬件无关,宿主机与 ESP32-S3 上编的是同一份。 */
|
||
#include "rail.h"
|
||
|
||
#include <assert.h>
|
||
#include <stddef.h>
|
||
|
||
#include "dac63204.h"
|
||
#include "phonerail.h"
|
||
|
||
/* 五路数与 DAC 侧的映射表必须是同一个数 —— 分家的那天就是错一路的那天。 */
|
||
_Static_assert(PHONERAIL_RAIL_COUNT == DAC63204_RAIL_COUNT, "五路数对不上");
|
||
|
||
bool rail_mv_in_range(int mv)
|
||
{
|
||
return mv >= RAIL_MV_MIN && mv <= RAIL_MV_MAX;
|
||
}
|
||
|
||
uint16_t rail_mv_to_code(int mv)
|
||
{
|
||
assert(rail_mv_in_range(mv)); /* 越界要在 rail_set_mv() 里被拒掉,不该走到这儿 */
|
||
|
||
/* code = (Vout0 − Vout) / 486416 µV × 4096,四舍五入。
|
||
**减法在这里**:Vout 越低,差越大,码越大 —— 反向关系只此一处。 */
|
||
int64_t diff_uv = (int64_t)RAIL_VOUT0_UV - (int64_t)mv * 1000;
|
||
int64_t code = (diff_uv * DAC63204_CODE_SPAN + RAIL_DAC_SPAN_UV / 2) / RAIL_DAC_SPAN_UV;
|
||
|
||
if (code < 0) {
|
||
code = 0;
|
||
}
|
||
if (code > DAC63204_CODE_MAX) {
|
||
code = DAC63204_CODE_MAX;
|
||
}
|
||
return (uint16_t)code;
|
||
}
|
||
|
||
int rail_code_to_mv(uint16_t code)
|
||
{
|
||
int64_t drop_uv = ((int64_t)code * RAIL_DAC_SPAN_UV + DAC63204_CODE_SPAN / 2)
|
||
/ DAC63204_CODE_SPAN;
|
||
int64_t uv = (int64_t)RAIL_VOUT0_UV - drop_uv;
|
||
return (int)((uv + 500) / 1000);
|
||
}
|
||
|
||
int32_t rail_code_to_vd_uv(uint16_t code)
|
||
{
|
||
return dac63204_code_to_uv(code);
|
||
}
|
||
|
||
hal_err_t rail_volt_init_one(uint8_t addr)
|
||
{
|
||
hal_err_t err = dac63204_probe(addr);
|
||
if (err != HAL_OK) {
|
||
return err;
|
||
}
|
||
/* init 自己就把用到的通道写成 safe 了(上电之前写,见 dac63204_init 的 ③)。 */
|
||
return dac63204_init(addr, rail_mv_to_code(RAIL_MV_SAFE));
|
||
}
|
||
|
||
hal_err_t rail_volt_init(void)
|
||
{
|
||
/* ⚠️ 一片失败**不放弃另一片**(A15):U6 不应答时 U7 那两路照样该被初始化,
|
||
而不是也停在 NVM 默认值上 —— 那样一片坏件就「降级」了五路。 */
|
||
hal_err_t first = HAL_OK;
|
||
for (int i = 0; i < DAC63204_COUNT; i++) {
|
||
const hal_err_t err = rail_volt_init_one(dac63204_all_addr[i]);
|
||
if (err != HAL_OK && first == HAL_OK) {
|
||
first = err;
|
||
}
|
||
}
|
||
return first;
|
||
}
|
||
|
||
/* 五路设定值的影子(契约见 rail.h)。初值就是 DAC 的 NVM 出厂默认,
|
||
所以 `rail_volt_init()` 跑之前它也说的是实话。 */
|
||
static int s_set_mv[PHONERAIL_RAIL_COUNT] = {
|
||
RAIL_MV_SAFE, RAIL_MV_SAFE, RAIL_MV_SAFE, RAIL_MV_SAFE, RAIL_MV_SAFE,
|
||
};
|
||
|
||
_Static_assert(PHONERAIL_RAIL_COUNT == 5, "s_set_mv 的初值列表要跟着改");
|
||
|
||
int rail_setpoint_mv(int rail)
|
||
{
|
||
if (rail < 1 || rail > PHONERAIL_RAIL_COUNT) {
|
||
return RAIL_MV_SAFE;
|
||
}
|
||
return s_set_mv[rail - 1];
|
||
}
|
||
|
||
void rail_setpoint_reset(void)
|
||
{
|
||
for (int i = 0; i < PHONERAIL_RAIL_COUNT; i++) {
|
||
s_set_mv[i] = RAIL_MV_SAFE;
|
||
}
|
||
}
|
||
|
||
hal_err_t rail_set_mv(int rail, int mv)
|
||
{
|
||
if (rail < 1 || rail > PHONERAIL_RAIL_COUNT) {
|
||
return HAL_ERR_ARG;
|
||
}
|
||
if (!rail_mv_in_range(mv)) {
|
||
return HAL_ERR_ARG; /* SR-13。TODO(A11):这里要记一条事件 */
|
||
}
|
||
const hal_err_t err = dac63204_write_code(dac63204_rail_addr(rail),
|
||
dac63204_rail_ch(rail),
|
||
rail_mv_to_code(mv));
|
||
if (err == HAL_OK) {
|
||
/* 记的是**请求的 mV**,不是 `rail_code_to_mv(码)` —— 两者差不到一个码
|
||
(118.75 µV),但 A10 的判据是拿它当「设定值」用的,回读换算会让
|
||
「设成 3900」在判据眼里变成 3899,白白吃掉 1 mV 的余量。 */
|
||
s_set_mv[rail - 1] = mv;
|
||
}
|
||
return err;
|
||
}
|
||
|
||
hal_err_t rail_get_mv(int rail, int *mv)
|
||
{
|
||
if (rail < 1 || rail > PHONERAIL_RAIL_COUNT || mv == NULL) {
|
||
return HAL_ERR_ARG;
|
||
}
|
||
uint16_t code = 0;
|
||
hal_err_t err = dac63204_read_code(dac63204_rail_addr(rail), dac63204_rail_ch(rail), &code);
|
||
if (err != HAL_OK) {
|
||
return err;
|
||
}
|
||
*mv = rail_code_to_mv(code);
|
||
return HAL_OK;
|
||
}
|