API GUIDE / CAN / HAL

G32S10 CAN HAL 接口

HAL 层接口:先调用 hal_can_config_struct_init() 初始化配置,再填写控制器实例、请求的模块 时钟和已经编码的位时序字段:

1. HAL 配置

先调用 hal_can_config_struct_init() 初始化配置,再填写控制器实例、请求的模块 时钟和已经编码的位时序字段:

hal_can_config_t config;

hal_can_config_struct_init(&config);
config.instance = CAN0;
config.module_clock_hz = 24000000U;
config.timing.nominal.tseg1 = 14U;
config.timing.nominal.tseg2 = 7U;
config.timing.nominal.sjw = 3U;
config.timing.nominal.divider = 0U;
config.timing.data = config.timing.nominal;
config.fd_enable = true;

配置字段面向硬件:

字段含义
instanceCAN0 或 CAN1
module_clock_hz请求的 CAN 模块时钟,单位 Hz
timing原始仲裁域/数据域位时序寄存器字段
fd_enable使能 CAN FD 帧格式
fd_tolerant使能 FD-tolerant 接收
protocol_exception使能 protocol-exception 处理
auto_recovery使能控制器 bus-off 自动恢复
self_test使能控制器自测试模式
listen_only使能只听模式
error_warning_limit错误警告阈值寄存器值
module_clock_parent请求的 CAN 模块时钟父时钟;HAL_CPM_ID_CLK_NONE 表示使用实例默认父时钟(当前为 HAL_CPM_ID_CLK_SCLK_A)
require_exact_module_clocktrue 时回读频率必须精确等于 module_clock_hz

hal_can_init() 会使能对应实例的 CPM 模块时钟,使控制器进入 reset,应用 mode 和 timing 字段,初始化 acceptance filter,并将 handle 标记为已初始化。该函数 不会退出 reset;完成全部配置后应调用 hal_can_enable()。hal_can_enable() 会 释放 RSTM,并等待 reset 状态清除和控制器进入 normal-ready 状态。

hal_can_disable() 使控制器进入 reset,但不会销毁 handle。timing、filter、 错误状态复位和 CAN 侧 DMA request 只能在控制器处于 reset 时修改。该函数不会 替上层停止 DMA 通道,也不会无条件执行 CTB/RRB。hal_can_deinit() 会关闭控制器资源并使 handle 失效。

2. HAL 接口分组

2.1 生命周期与配置

hal_can_config_struct_init();
hal_can_init();
hal_can_enable();
hal_can_disable();
hal_can_deinit();
hal_can_set_timing();
hal_can_set_selfloop();
hal_can_is_selfloop_enabled();
hal_can_self_rx_request();

hal_can_set_selfloop() 用于在 reset 状态下进入或退出内部回环模式:使能时由 HAL 依次完成 SL key 解锁、强制 TX 输出高电平、打开 self-loop 和自测模式,使发出的帧被控制器自身接收, 并且不依赖总线上其他节点的应答;关闭时恢复 TX 输出,并把自测模式还原成hal_can_config_t::self_test 中的配置值。该接口写完寄存器后会回读确认,未生效时返回IM_ERR_IO。hal_can_is_selfloop_enabled() 返回 self-loop、TX-off、self-test 三个寄存器 位的组合状态;hal_can_self_rx_request() 请求一次“发送并同时接收”,需在hal_can_tx_image_write() 之后、轮询状态之前调用。内部回环的典型顺序为:

hal_can_disable(&handle);
hal_can_set_selfloop(&handle, true);
hal_can_enable(&handle);
/* ... hal_can_tx_image_write(); hal_can_self_rx_request(); ... */
hal_can_disable(&handle);
hal_can_set_selfloop(&handle, false);
hal_can_enable(&handle);

2.2 帧访问

hal_can_tx_frame_info_encode();
hal_can_rx_frame_info_decode();
hal_can_rx_id_decode();
hal_can_tx_image_write();
hal_can_tx_header_get();
hal_can_tx_request();
hal_can_tx_abort();
hal_can_overload_frame_request();
hal_can_rx_image_read();
hal_can_rx_release();

hal_can_tx_frame_info_encode() 把逻辑 TX 帧字段编码为 G32S10 TFIR 值。 输入的 dlc 必须位于 0..15;filter_match 和 esi 不参与 TX 编码。hal_can_rx_frame_info_decode() 把 G32S10 RFIR 值解码到同一逻辑结构,其中filter_match 和 esi 反映接收状态。hal_can_rx_id_decode() 从原始 RXID 中提取 有效 CAN 标识符。寄存器 bit 位置和原始 ID mask 因此由 HAL 统一维护,不需要 middleware 直接引用 CAN 寄存器位域宏。

hal_can_overload_frame_request() 请求控制器发送一个过载帧,用于验证过载中断 通路;控制器处于 reset 或 bus-off 状态时返回 IM_ERR_NOT_READY。

2.3 状态、错误与 Filter

hal_can_status_get();
hal_can_status_clear();
hal_can_error_get();
hal_can_error_clear();
hal_can_error_state_reset();
hal_can_error_counters_get();
hal_can_error_counters_set();
hal_can_filter_struct_init();
hal_can_filter_config();
hal_can_filter_enable();
hal_can_filter_disable();

hal_can_status_get() 返回逻辑 HAL_CAN_STATUS_* bit。hal_can_error_get()返回的错误 bit 是 HAL IRQ handler 记录的 sticky 历史;hal_can_error_clear()清除该软件历史,但不会直接复位控制器协议错误计数器。需要复位控制器错误状态时, 应在 reset 状态下调用 hal_can_error_state_reset()。

hal_can_error_counters_get() 返回 TEC/REC 原始计数;hal_can_error_counters_set()写入 TEC/REC,仅允许在 reset 状态下调用,计数值上限为HAL_CAN_ERROR_COUNTER_MAX,越界返回 IM_ERR_INVALID_PARAM。测试用例可以借助 这两个接口构造错误主动/被动/总线关闭状态,而不必直接访问寄存器位域。

2.4 中断与 Callback

hal_can_irq_config();
hal_can_irq_events_read_and_clear();
hal_can_callback_register();
hal_can_user_data_set();
hal_can_irq_handler();

hal_can_irq_config() 只控制 CAN 外设中断源 bit,不负责申请、使能或释放 SoC IRQ line。平台层或更高层必须将 SoC IRQ 入口连接到 hal_can_irq_handler()。

hal_can_irq_events_read_and_clear() 将已使能的 pending event 作为HAL_CAN_IRQ_* bit 返回,并确认 read-to-clear 外设标志。需要观测新 TX event 的 polling owner 也通过该 HAL 边界读取事件。

使用 hal_can_callback_register() 的 HAL_CAN_CALLBACK_* slot 注册 RX-ready、 TX-complete、TX-free、CAN 侧 DMA、wakeup、error 和 overload callback。 callback 可能在中断上下文执行,因此不能阻塞。callback 私有上下文通过hal_can_user_data_set() 设置。

2.5 调试辅助接口

hal_can_regs_dump();

该接口用于打印 MODE、STAT、BTR、FLT、ERR、TFIR 和 SL 等寄存器快照。由于读取 CANINT 会清除 read-to-clear pending 标志,dump 不读取 CANINT。该接口只在CONFIG_SDK_ENABLE_DEBUG_HELPERS 和 CONFIG_CAN_ENABLE_DEBUG_HELPERS 同时使能时 执行实际打印。