TC275调试日志——中断系统2:STM0比较中断

今天我们继续上贴的中断系统进行说明,上贴已经说明了中断系统的工作方式以及中断仲裁。今天我们来说明中断的应用。

上贴说过,中断控制单元ICU会对中断节点的中断进行处理,将仲裁胜出的中断对应的信息(包括优先级SRPN、校验ECC、中断节点号SRN index)发送到中断服务者(CPU或者DMA)。相应的中断服务者接受中断后会返还这些信息,这些信息的承载以及中断服务是通过中断服务者的接口来完成的。

那么中断服务者是怎么根据这些信息就可以判断中断类型,并进行相应的中断服务呢?我们知道在51中,每个中断都有相应的地址,触发中断后以该地址为入口进行相应的中断处理。275也是相同的,我们说过在CPU初始化中要初始化中断向量表,该表其实就是中断的入口地址。实际的中断处理,就是将中断处理成中断向量,然后查表都得到中断入口地址进行中断处理。

首先来说明中断服务,我们来看一下中断服务函数的构成:

IFX_INTERRUPT(isr, vectabNum, prio)

该函数是在编译器的C文件中定义的,全都是汇编,大家有空可以研究一下:

我们只关注,该函数的三个参数:ISR表示中断所在的地址:

 

如图为STM0中断对应的地址空间;vectabNum为向量表号,也就是cpu内核,275有3个内核所以该参数为0、1、2,通常取0即可;prio为优先级,0-255共有256个优先级,可以根据需要自行定义。

我们来看一个中断处理函数:

IFX_INTERRUPT( Ifx_STM0_Isr,  0  ,  IFX_CFG_ISR_PRIORITY_STM0_COMPARE0)

{

uint32 stmTicks;

stmTicks= (uint32)(stm0CompareValue * 1);

IfxStm_updateCompare(&MODULE_STM0,IfxStm_Comparator_0,IfxStm_getCompare(&MODULE_STM0, IfxStm_Comparator_0) + stmTicks);//更新比较值

timeMicSec[0]++;//记录定时数目

__enable ();//立即使能中断

}

这便是我之前提到过的STM比较中断,三个参数为STM0的中断地址空间、CPU0、以及优先级,这里定义为102.

在回头看一下中断的配置,中断的配置无非是配置SRC寄存器,包括中断优先级、中断服务者选择以及中断使能。其具体流程为:

(1)写入中断优先级,SRC.SRPN;

(2)写入中断服务选择,SRC.TOS;

(3)清除中断标志位,SRC.CLRR=1;

(4)中断使能,SRC.SRE=1;

下面是STM0比较中断的例子:

 

在该函数的划线部分,完成了中断配置,两个函数的展开如下:

 

流程和我们说的一致,大家在今后的中断配置可以参考这种方式。今天的内容就先到这里,下一贴我们试试对外部中断进行配置。

### ACM32芯片 `printf` 函数重定向方法 在嵌入式开发中,通常需要将标准库函数(如 `printf`)的输出重定向到特定设备(如串口),以便于调试和监控程序运行状态。以下是针对ACM32芯片实现 `printf` 重定向的具体方法。 #### 实现思路 为了使 `printf` 输出能够通过串口显示,需完成以下两步: 1. **初始化串口通信**:配置串口参数(波特率、数据位、停止位等),并启用中断或轮询方式接收/发送数据。 2. **重写 `_write` 函数**:标准 C 库依赖底层 `_write` 函数来处理字符流输出。因此可以通过自定义该函数,将其指向已初始化好的串口驱动[^1]。 --- #### 步骤详解 ##### 1. 初始化串口 假设使用USART外设作为调试端口,则需要先对其进行初始化。下面是一个典型的 STM32 平台下的 USART 配置代码片段: ```c #include "acm32fxx_hal.h" void MX_USART1_UART_Init(void) { huart1.Instance = USART1; huart1.Init.BaudRate = 115200; // 设置波特率为115200bps huart1.Init.WordLength = UART_WORDLENGTH_8B; // 数据长度为8bit huart1.Init.StopBits = UART_STOPBITS_1; // 停止位数为1 huart1.Init.Parity = UART_PARITY_NONE; // 无奇偶校验 huart1.Init.Mode = UART_MODE_TX_RX; // 启用收发功能 huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE; // 不使用硬件流控 HAL_UART_Init(&huart1); } ``` 上述代码展示了如何初始化一个UART实例用于后续的数据传输操作[^5]。 ##### 2. 自定义 `_write` 函数 重新定义 `_write` 是关键所在。此函数会被链接器绑定至 stdio 的内部调用链路之中。当执行 `printf` 或其他类似的 I/O 操作时,最终都会落到这个位置上来完成实际的数据推送工作。 下面是适用于 ARM Cortex-M 架构处理器的一个通用版本实现方案: ```c int _write(int file, char *ptr, int len) { (void)file; for (int i = 0; i < len; ++i) { while (LL_USART_IsActiveFlag_TC(USART1) == RESET); // 等待前一次发送结束 LL_USART_TransmitData8(USART1, ptr[i]); // 发送当前字节 } return len; // 返回成功写入的数量 } ``` 注意这里的逻辑仅适配单一通道情况;如果项目涉及多路复用场景,则可能还需要额外增加文件描述符判断分支。 另外值得注意的一点是,在某些特殊场合下(比如低功耗设计需求强烈的应用领域里),可以考虑采用 DMA 技术进一步优化性能表现——即让 CPU 脱离繁忙等待循环而专注于更重要的计算任务上去[^3]。 --- #### 注意事项 - 如果目标平台支持 USB CDC 类型虚拟 COM 设备的话,也可以尝试改造成基于 USB 接口形式的日志记录机制[^4]; - 对于 ESP32 这样的 SoC 来说,默认已经集成了丰富的外围资源以及成熟的 SDK 支持框架,所以相对来说更加容易达成目的[^2]。 --- ### 总结 综上所述,通过对 ACM32 芯片上的 `printf` 功能实施定制化改造之后,不仅可以让开发者获得更为直观便捷的信息反馈途径,同时也为进一步提升整个系统的可维护性和扩展性奠定了坚实的基础。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值