This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
我将通读 CC26xx 驱动程序库文档、其中 interrupt.h 文档中提供了以下静态配置中断矢量表的内容:
通过编辑应用程序启动代码中的中断处理程序表、可实现中断处理程序的静态注册。 德州仪器(TI)为每个受支持的编译器()提供启动文件startup_<compiler>.c
,这些启动文件包括默认静态中断矢量表。 除 ResetISRextern
之外的所有条目都声明为具有对默认中断处理程序的弱分配。 这允许用户声明和定义与向量表中的条目的名称相同的函数(在用户代码中)。 在编译时、链接器会将指向矢量表中默认中断处理程序的指针替换为指向用户定义的中断处理程序的指针。
静态配置中断表可提供最快的中断响应时间、因为堆栈操作(对数据总线上的 SRAM 执行写操作)与中断处理程序表提取(对指令总线上的闪存执行读操作)以及中断处理程序的预取并行执行 (假设它也在闪存中)。
我想处理 SVCalls、根据文档中的这段、我必须定义一个与向量表中的条目同名的函数。 但是、当我查看 ti/simplelink_cc13x2_26x2_sdk_3_40_00_02/sources/ti/devices/cc13x2_c26x2/startup_files 中的 startup_ccs.c 文件时、我看不到任何名称。
我确实看到一个 IntDefaultHandler 条目、在它说"//11 Supervisor Call (SVCall)"之后添加了注释、但大多数其他中断也使用 IntDefaultHandler。 那么、如果文档中的那条语句意味着我必须定义我自己的 IntDefaultHandler 函数、那么我也不会处理所有其他中断吗? 此外,该文档指出,这些条目被声明为 extern,但在文件中,我看到 IntDefaultHandler 被声明为“static void IntDefaultHandler( void );",因此不是 extern。
如何静态地将我自己的 SVCall 处理程序添加到此矢量表中? 还是只能动态地执行此操作?
下面的代码显示了 startup_ccs.c 文件的内容。
// // //检查编译器是否为 CCS // /********* #if!(defined (__TI_Compiler_version__) )#error "startup_ccs.c:不支持的编译器!" #endif #include "../inc/hw_types.h #include "../driverlib/setup.h // ********* // //! 复位 ISR 和默认故障处理程序的转发声明。 //// ***************** 无效 ResetISR( void ); static void NmiSR( void ); static void FaultISR( void ); static void IntDefaultHandler( void ); extern int main(void); //********* // //! 应用启动代码和器件调整 fxn 的入口点。 //// ***************** extern void _c_int00 (void); //********* // // CCS:标记栈顶的链接器变量。 //// ***************** extern unsigned long __stack_end; //! 矢量表。 请注意 、必须将正确的构造放置在这里、以便//! 确保它最终位于物理地址0x0000.0000或 //开始! 该程序位于0以外的起始地址。 //// ***************** #pragma DATA_SECTION (g_pfnVectors、".intvecs") void (* const g_pfnVectors [])(void)= { (void (*)(void)((unsigned long)&_stack_end)、 // 0初始堆栈指针 ResetISR、 // 1复位处理程序 NmiSR、 // 2 NMI 处理程序 FaultISR、 // 3硬故障处理程序 IntDefaultHandler、 // 4内存管理(MemManage)故障 IntDefaultHandler、 // 5总线故障处理程序 IntDefaultHandler、 // 6用法故障处理程序 0、 // 7保留 0、 // 8保留 0、 // 9保留 0、 //保留10 IntDefaultHandler、 // 11个主管呼叫(SVCall) IntDefaultHandler、 // 12调试监视器处理程序 0、 // 13保留 IntDefaultHandler、 // 14 PendSV 处理程序 IntDefaultHandler、 // 15 SysTick 处理程序 //--外部中断-- IntDefaultHandler、 // 16 AON 边沿检测 IntDefaultHandler、 // 17个 I2C IntDefaultHandler、 // 18个射频内核命令和数据包引擎1. IntDefaultHandler、 // 19 PKA 中断事件 IntDefaultHandler、 // 20 AON RTC IntDefaultHandler、 // 21 UART0 Rx 和 Tx IntDefaultHandler、 // 22 AUX 软件事件0 IntDefaultHandler、 // 23个 SSI0 Rx 和 Tx IntDefaultHandler、 // 24 SSI1 Rx 和 Tx IntDefaultHandler、 // 25射频内核命令和数据包引擎0 IntDefaultHandler、 // 26个射频内核硬件 IntDefaultHandler、 // 27射频内核命令确认 IntDefaultHandler、 // 28 I2S IntDefaultHandler、 // 29 AUX 软件事件1 IntDefaultHandler、 // 30个看门狗计时器 IntDefaultHandler、 // 31定时器0子定时器 A IntDefaultHandler、 // 32 Timer 0子定时器 B IntDefaultHandler、 // 33定时器1子定时器 A IntDefaultHandler、 // 34定时器1子定时器 B IntDefaultHandler、 // 35计时器2子计时器 A IntDefaultHandler、 // 36定时器2子定时器 B IntDefaultHandler、 // 37 Timer 3子计时器 A IntDefaultHandler、 // 38定时器3子定时器 B IntDefaultHandler、 //提供39加密核心结果 IntDefaultHandler、 // 40 uDMA 软件 IntDefaultHandler、 // 41 uDMA 错误 IntDefaultHandler、 // 42闪存控制器 IntDefaultHandler、 // 43软件事件0 IntDefaultHandler、 // 44 AUX 组合事件 IntDefaultHandler、 // 45 AON 可编程0 IntDefaultHandler、 // 46动态可编程中断 //源(默认值:PRCM) IntDefaultHandler、 // 47 AUX 比较器 A IntDefaultHandler、 // 48个 AUX ADC 新采样或 ADC DMA //完成、ADC 下溢、ADC 溢出 IntDefaultHandler、 // 49 TRNG 事件 IntDefaultHandler、 //来自振荡器控制的50个组合事件 IntDefaultHandler、 // 51 AUX Timer2事件0 IntDefaultHandler、 // 52个 UART1组合中断 IntDefaultHandler //电池监控器的53个组合事件 }; //********* // //! 这是处理器首次开始执行时调用 的代码//! 发生复位事件后。 仅执行绝对必要的设置、 //! 之后调用应用程序提供的 entry()例程。 任何花哨 //! 操作(例如根据复位原因寄存器做出决策、和 //! 将该寄存器中的位复位)仅保留在 //! 应用。 //// ***************** void ResetISR (void) { // //器件的最终修整 // SetupTrimDevice(); // //跳转到 CCS C 初始化例程。 // _asm (".global _c_int00\n" " _c_int00"); // //如果我们返回信号错误 // FaultISR (); } //********* // //! 这是当处理器接收到 NMI 时被调用的代码。 此 //! 只需进入无限循环、保持系统状态以供检查 //! 进行调试。 //// ***************** 静态空 NmiSR (void) { // //输入无限循环。 // while (1) { } } //********* // //! 这是处理器收到故障 时调用的代码//! 中断。 这只是进入一个无限循环、保持系统状态 //! 以供调试器检查。 //// ***************** 静态空 FaultISR (空) { // //输入无限循环。 // while (1) { } } //********* // //! 这是处理器收到意外 //!时调用的代码 中断。 这只是进入一个无限循环、保持系统状态 //! 以供调试器检查。 //// ***************** 静态空 IntDefaultHandler (void) { // //进入无限循环。 // while (1) { } }
您好!
也许启动文件的这种设置(过去成功)有助于: (这是"TM4C123 (其他) MCU"应用程序的摘录。)
请注意颜色编码-它努力显示声明和矢量表之间的链接。 为了紧凑/简单-只显示了2个此类联系。
//
//
//应用程序使用的中断处理程序的外部声明。
//
//
extern void IntDefaultHandler (void);
extern void ADC0IntHandler (void);//正常 PGM opn。
extern void GPIOBIntHandler (void);//霍尔感应
extern void FaultISR (void);
extern void NmiSR (void);
extern void PWM0IntHandler (void);// PWM 发生器
extern void SysTickIntHandler (void);// Switch、SPD Pot
extern void WTimer2BIntHandler (void);//失速检测(2秒)
extern void WatchdogIntHandler (void);
//矢量表。 请注意、必须将适当的构造放置在到上
//确保它最终位于物理地址0x0000.0000。
//
//
__root const uVectorEntry __vector_table[]@".intvec"=
{
{.ulPtr =(无符号长整型) pulStack + sizeof (pulStack)}、
//初始堆栈指针
ResetISR、//复位处理程序
NmiSR、// NMI 处理程序
FaultISR、//硬故障处理程序
IntDefaultHandler、// MPU 故障处理程序
IntDefaultHandler、//总线故障处理程序
IntDefaultHandler、//用法故障处理程序
0、//保留
0、//保留
0、//保留
0、//保留
IntDefaultHandler、// SVCall 处理程序
IntDefaultHandler、//调试监视器处理程序
0、//保留
IntDefaultHandler、// PendSV 处理程序
SysTickIntHandler、// SysTick 处理程序
IntDefaultHandler、// GPIO 端口 A
GPIOBIntHandler、// GPIO 端口 B
IntDefaultHandler、// GPIO 端口 C
请注意、我们在此处将"IntDefaultHandler"编辑为"更具描述性的 ISR 名称"两次。
但该文件位于 C:\ti\simplelink_cc13x2_26x2_sdk_3_40_00_02\source\ti\devices\cc13x2_cc26x2\startup_files 中、因此我不能只正确更改它?
因为当我移动到另一台计算机时、或者当我的同事想要使用必须再次更改此文件的项目时。
我的团队对 您的 CC26xx 器件没有相当近期的经验。
我们向您展示了"IAR 启动文件"的内容、其中揭示了指定的"ISR"是如何呈现(同时呈现)静态和外部的。 对于(高级) IAR IDE -所有此类文件均已正确链接-并且很容易"被他人共享"。
实际上、一旦修改(如我所示)、启动文件就证明是"特定项目!"所独有的。 原始启动文件-在 IAR 下(我们假设 CCS)保持"不变/不变"。 (并且"不再"成为此特定项目的一部分、也不包括在该项目中!)
您是如何在 IAR 中实现它的?
在 CCS 中、我创建了一个文件副本、并将其移动到我自己的项目中、我进行了一些更改并添加了我自己的 SVCHandler。 我更改了项目设置中链接器的包含选项和文件搜索路径选项、以便在编译期间可以找到我的文件。 但当我运行程序时、它仍会从另一个文件进入旧的 IntDefaultHandler。
[引用 user="Vincent Kenbeek"]您是如何在 IAR 中做到这一点的?
在"Pro IDE" IAR 下感受您的痛苦-该过程(完全)是自动化的! 我们只需更改"提供的启动文件"(它是基本启动文件的"副本")。 正如我的"简要代码提取"所揭示的那样-我们将每个(新命名的) ISR 都放入了相应的项目文件中。 (我们的项目包含大约15个文件。)
再说一次-在 IAR 下(我也希望在 CCS 下)、不应该(仅)那些包含在指定项目中的程序文件使其运行? 当我们启动一个"新项目"时、IDE 非常聪明、能够(始终)包含(副本)基本启动文件(可以理解)几乎总是"根据我们的计划要求进行修改!"
“基本启动文件”是“不受(不需要)修改的安全”... 它的"副本"是我们项目中的内容、然后"被操纵以符合我们的目标!"
您可以使用中断 API 为 SVCALL 注册 IRQ。
#include #include DeviceFamily_constructPath (inc/hw_ints.h) //对于 INT_SVCALL #include DeviceFamily_constructPath (driverlib/interrupt.h)//对于 INT_API void svcall_IRQ (void){// impl */} ... IntRegister (INT_SVCALL、svcall_IRQ);
但是、这不是一个中断的动态注册、而是一个静态注册?
即使如此、我认为我也必须使用这个、因为除了驱动程序文档中的一段、我找不到任何关于如何静态执行它的其他信息。
我现在已经尝试在我自己的项目中制作启动文件的副本、但它仍然使用另一个文件。 然后、我尝试将其移动到工程中的 startup_files 目录、并将该目录添加到工程的 include 选项和文件搜索路径中、但它继续使用另一个文件。
是的、但为什么这很重要? 静态 NVIC 表始终由中断 API 获取所有权、而不管您放置在何处、因为这是 TI-RTOS (或用于此 Matter 的 NoRTOS)实现方式的组成部分。
根据文档、根据这一行、中断的静态注册将会稍微快一些。
静态配置中断表可提供最快的中断响应时间、因为堆栈操作(对数据总线上的 SRAM 执行写操作)与中断处理程序表提取(对指令总线上的闪存执行读操作)以及中断处理程序的预取并行执行 (假设它也在闪存中)
现在、拥有最快的选择并不是非常重要、但知道如何在最快的速度下实现这一点非常有用。 所以我希望现在能获得有关如何静态地执行它的信息、这样我就可以对它进行实验了。
与其它与 IRQ 处理程序相关的运行时开销相比、动态注册 SVCall IRQ 的运行时"损失"可以忽略不计。 我看不到任何需要静态注册 SVCall IRQ 的情况、因此如果情况如此、请随时告诉我。
您是否正在使用任何特定的堆栈? BLE 堆栈?
可能会问:"你认为什么(价值方面)可以证明可以忽略不计?" 由于 MCU 手册努力识别这一问题(罚分/弱点)-事实上、我们的团队多次认为这可能(超出)可以忽略不计。
此外-我们获悉、这种"动态注册"比"静态"更容易受到干扰。 我们感谢您(供应商/内部人员)在这方面的意见。 (本@的 TI 技术展会-几年前...)
感谢您的时间和关注-两个都很感谢。
[编辑/添加]: 是否不应额外注意此类中断(可能)以多个序列发生? (我公司的大多数程序代码都扩展到10个以上的中断-尽管我们努力限制该数量。) 现在-这些中断中的每一个都会受到"影响"(由于使用中断注册)、级联效应几乎肯定会超出"可忽略不计!"
而且-"可忽略不计"的确定通常/习惯上最好由客户/用户确定-仅他/她知道其应用程序的需求...
注意:Emptor
我想我们有不同的运行时成本定义、可以忽略不计。 因此、请随时告诉我您可以接受和不可接受的运行时间成本。
如果您使用的是 TI-RTOS 或任何 TI 驱动程序、您已经在支付将 NVIC 表重新放置到 RAM 的运行时成本、这意味着在运行时注册 SVCall ISR 在某种意义上已经"付钱"了。
在运行时注册 ISR 实际上没有任何其他"惩罚"或"弱点"、唯一的缺点是、您第一次注册 ISR 时需要将 NVIC 重新定位到 RAM。 请注意、API 已经处理了这一问题。
与静态配置相比、在运行时注册 ISR 意味着"更容易受到干扰"? 这毫无意义。 负责此操作的 API 可确保对 NVIC 所做的任何修改(即重新定位或注册 ISR)都在关键段中完成、因此、在这种操作期间、HWI 不会触发。 如果您想仔细检查、您可以自己查看实现情况。
现在、如果您担心在能够注册 SVCall ISR 之前缺少任何"SVC"指令、那么我只能建议您在应用程序开始时、无论是在启动中、还是在 main.c 中的首次调用中、注册 SVCall ISR
现在、我想问您一个问题:为什么使用 SVCall? 我想这必须与您的代码库相关、因为 TI 代码根本不使用 SVCall 指令。
感谢您-尽管我们必须"同意不同意"-您的回答非常感谢。
Severin Suveren 说:因此,请随时告诉我您可以接受和不可接受的运行时成本。
这是根据请求的"可忽略"规范进行的务虚会-它不是吗? 如 上所述-级联延迟对代码执行循环的影响是(或应该是)"客户端-用户的省份"。
[引用 user="Severin Suveren">与静态配置相比、在运行时注册 ISR "更容易受到中断的影响"意味着什么? 这毫无意义。 [/报价]
您是否以某种方式错过了 TI 编程人员/讲师在 TI 提供的"转发/报告"这一事实 技术研讨会? 这一明确事实的"遗漏"是否是一个更好的模式,"没有太大意义?"
[引用 user="Severin Suveren"]现在,如果您担心在注册 SVCall ISR 之前缺少任何"Svc"指令,那么我只能建议在应用程序开始时(启动时或 main.c.的首次调用中)注册 SVCall ISR。
这里-我们完全同意。 (好极了!) 但是、对于"采用"中断注册"而不是"静态中断"、没有提供任何情况。 ("更改"即时"注册的内容的可能能力是我的团队能够(再次可能)识别的所有内容。)
[引述 USER="Severin Suveren">现在、我想问您一个问题:为什么使用 SVCall? 我想这必须与您的代码库相关、因为 TI 代码根本不使用 SVCall 指令。
您是否不应将此问题直接发送到原始海报、而不是我的小组、正如此主题的"正确阅读"所揭示的那样? 仅他就雇用了 SVCall。 我们的目标是提供相关的"静态中断技术对此海报的输入"(通过我们长期成功地使用静态中断)、我们对此进行了详细介绍...