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;
配置字段面向硬件:
| 字段 | 含义 |
|---|---|
instance | CAN0 或 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_clock | true 时回读频率必须精确等于 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 同时使能时
执行实际打印。