工具/软件:TI C/C++编译器
我已经阅读了 C5535的 CPU 手册和编译器手册以及相关的 C 编译器。 第一部分告诉我 CPU 是如何处理中断的、这一点很清楚。 第二个示例告诉我如何写入和声明中断、这是明确的。 但我不知道如何告诉 C 编译器特定的中断函数、例如。 计时器或 UART 中断。 我本来希望有一个 pragma 来执行它、或者有一种方法可以通过链接器脚本执行它、但我无法确定它。 是否有一种简单的方法将中断函数与其矢量相关联?
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.
工具/软件:TI C/C++编译器
我已经阅读了 C5535的 CPU 手册和编译器手册以及相关的 C 编译器。 第一部分告诉我 CPU 是如何处理中断的、这一点很清楚。 第二个示例告诉我如何写入和声明中断、这是明确的。 但我不知道如何告诉 C 编译器特定的中断函数、例如。 计时器或 UART 中断。 我本来希望有一个 pragma 来执行它、或者有一种方法可以通过链接器脚本执行它、但我无法确定它。 是否有一种简单的方法将中断函数与其矢量相关联?
[引用 user="Jason Heeris82">谢谢您的参考、我没有看到过它。 如果我理解正确、我需要在汇编语言中实现中断矢量表、并使用链接器脚本确保将其放置在正确的位置?
也许这只是 TI 的工作方式、但与例如相比、这似乎是一个复杂的过程。 ARM (其中存在命名约定、链接器负责命名约定)或 Microchip (您可以使用编译器扩展对函数进行注释)。 可能在芯片支持库中或其他地方、是否有我可以修改的完全填充的链接器或汇编文件?
[/报价]
您好、无需进行任何装配。 最简单的方法(并且由于您将不得不进行一些设置)是设置 DSP/BIOS (或更好地称为 SYS/BIOS)、这是 MSC320 DSP 的 O/S。 您必须已经使用 Code Composer、如果 Platinum 版的 gona 为版本3、3则最后一个版本已重新发布(仅适用于 Windows XP、或者最新版本6指出了一些内容。 O/S 具有图形配置界面、可让您根据需要设置 O/S、包括 DMA、GPIO、计时器、存储器、 任务等、尤其容易中断。 设置和工作后、您将永远不会回头、甚至不会提到"汇编"一词。 如果您更喜欢使用矢量表的方式、则可能必须仔细研究它、但 O/S 的方式在长期内更有用。
祝你好运、
毫米
下面是我要做的工作:
在我的 CCS 项目中、我有 main.c、interrupts.asm 和 C5515.cmd。
我的 main.c 包含设置代码和函数"_interrupt void GPIO_ISR (void)"。
我的 interrupts.asm 如下所示:
.ref _GPIO_ISR .ref _c_int00 .def RST .sect "向量" .align 256 RST: ivec _c_int00、use_RETA;复位/软件中断#0 NMI: ivec no_isr ;不可屏蔽中断 INT0: ivec no_isr ;外部用户中断#0 INT1: ivec no_isr ;外部用户中断#1 提示: ivec no_isr ;定时器#0/软件中断#4 PROG0: ivec no_isr ;可编程0中断 UART: ivec no_isr ; IIS #1接收中断 程序 G1: ivec no_isr ;可编程1中断 DMA: ivec no_isr ;DMA 中断 PROG2: ivec no_isr ;可编程2中断 COPROCFFT:.ivec NO_ISR ;协处理器 FFT 模块中断 程序3: ivec no_isr ;可编程3中断 LCD: ivec no_isr ;LCD 中断 SARADC: ivec no_isr ;SAR ADC 中断 XMT2: ivec no_isr ;I2S2 Tx 中断 RCV2: ivec no_isr ;I2S2 Rx 中断 XMT3: ivec no_isr ;I2S3 Tx 中断 RCV3: ivec no_isr ;I2S3 Rx 中断 RTC: ivec no_isr ;RTC 中断 SPI: ivec no_isr ;SPI 接收中断 USB: ivec no_isr ;USB 发送中断 GPIO: ivec _GPIO_ISR ;GPIO 中断 EMIF: ivec no_isr ;EMIF 错误中断 I2C: ivec no_isr ; IIC 中断 BERR: ivec no_isr ;总线错误中断 DLOG: ivec no_isr ;仿真中断- DLOG RTOS: ivec no_isr ;仿真中断- RTOS RTDXRCV:.ivec NO_ISR ;仿真中断- RTDX 接收 RTDXXMT:.ivec NO_ISR ;仿真中断- RTDX 发送 EMUINT: ivec no_isr ;仿真监视器模式中断 SINT30: ivec no_isr ;软件中断#30 SINT31: ivec no_isr ;软件中断#31 .text NO_ISR:b NO_ISR
请注意、只有 GPIO 中断执行任何操作。
根据汇编语言工具用户指南、.ivec 指令的标签应分配一个字节(而非字)地址、.ivec 应将 SPC 与8字节边界对齐。 那么、所有这些应该是32个中断* 8字节= 256字节、对吧? 或0x100。
链接器脚本如下所示(除了我已放入"..."以将其压缩一段时间外):
内存 { MMR: O = 0x000000 l = 0x0000c0 /* 192B 存储器映射寄存器*/ DARAM0:O = 0x0000C0 l = 0x001F40 /* 8kB 双存取 RAM 0 */ ... DARAM7:O = 0x00E000 l = 0x002000 // 8kB 双存取 RAM 7 * SARAM0:O = 0x010000 l = 0x002000 // 8kB 单访问 RAM 0 */ ... SARAM31:O = 0x04E000 l = 0x002000 // 8kB 单访问 RAM 31 * CS0: O = 0x050000 l = 0x7B0000 /* 8MB CS0外部存储器空间*/... CS5: O = 0xF00000 l = 0x0E0000 /* 1MB CS5外部存储器空间*/ ROM: O = 0xFE0000 l = 0x01FF00 // 128KB ROM (MPNMC=0)或 CS5 (MPNMC=1)*/ VECS:O = 0xFFFFFF00 l = 0x000100 //复位矢量*/ } SECTIONS { 矢量 >VECS 对齐= 256 .cinit > DARAM0 .text > DARAM1 堆栈 > DARAM0 .sysstack > DARAM0 sysmem > DARAM4 .data > DARAM4 .cio > DARAM0 .bss > DARAM5 .const >DARAM0 }
当我编译并链接它时、我会得到以下错误:
"./C5515.cmd"、第72行:错误#10099-D:程序将无法放入可用 内存中。 对于"矢量"大小 为0x200页0的段、对齐/分块放置失败。 可用存储器范围: VECS 大小:0x100未使用:0x100最大空洞:0x100
为什么它是0x200 (512字节)而不是0x100 (256字节)? 我是否还在正确的轨道上?
[引用用户="Jason Heeris82"]
…
…
链接器脚本如下所示(除了我已放入"..."以将其压缩一段时间外):
内存 { MMR: O = 0x000000 l = 0x0000c0 /* 192B 存储器映射寄存器*/ DARAM0:O = 0x0000C0 l = 0x001F40 /* 8kB 双存取 RAM 0 */ ... DARAM7:O = 0x00E000 l = 0x002000 // 8kB 双存取 RAM 7 * SARAM0:O = 0x010000 l = 0x002000 // 8kB 单访问 RAM 0 */ ... SARAM31:O = 0x04E000 l = 0x002000 // 8kB 单访问 RAM 31 * CS0: O = 0x050000 l = 0x7B0000 /* 8MB CS0外部存储器空间*/... CS5: O = 0xF00000 l = 0x0E0000 /* 1MB CS5外部存储器空间*/ ROM: O = 0xFE0000 l = 0x01FF00 // 128KB ROM (MPNMC=0)或 CS5 (MPNMC=1)*/ VECS:O = 0xFFFFFF00 l = 0x000100 //复位矢量*/ } SECTIONS { 矢量 >VECS 对齐= 256 .cinit > DARAM0 .text > DARAM1 堆栈 > DARAM0 .sysstack > DARAM0 sysmem > DARAM4 .data > DARAM4 .cio > DARAM0 .bss > DARAM5 .const >DARAM0 }
当我编译并链接它时、我会得到以下错误:
"./C5515.cmd"、第72行:错误#10099-D:程序将无法放入可用 内存中。 对于"矢量"大小 为0x200页0的段、对齐/分块放置失败。 可用存储器范围: VECS 大小:0x100未使用:0x100最大空洞:0x100
为什么它是0x200 (512字节)而不是0x100 (256字节)? 我是否还在正确的轨道上?
[/报价]
由于某种原因、我的 C5515平台上具有此功能:
VECT: origin = 0x0000、len = 0x100
您可能想检查与您相关的引导程序表的来源...
谢谢、MM
查看 CPU 参考指南(P2-24)、我看到:
两个16位中断矢量指针 IVPD 和 IVPH (请参阅图2−11)指向程序空间中多达32个中断矢量。 IVPD 指向中断矢量0–15和24–31的256字节程序页面。 IVPH 指向中断矢量16–23的256字节程序页面。
如果 IVPD 和 IVPH 的值相同、则所有中断向量都位于相同的256字节程序页面中。 DSP 硬件复位用 FFFFh 加载两个 IVP。 IVP 不受软件复位指令的影响。
下一页的表显示了 IVPH 给出了中断矢量地址、即0xFFFFFF00的24-8位。 我将对此进行拍摄、但似乎这会将矢量放入 DARAM7中。
好的、问题似乎是这个芯片 rts55x.lib 的运行时库(由 CCS 选择)已经包含一个矢量部分。 我找不到有关其功能的文档。 有一个文件 RTS_4_4_1_Manifest.pdf 包含以下行:
Vectors.asm TI BSD Texas Instruments、Inc.
但我唯一能找到的 vectors.asm 位于芯片支持库中、这是我开发的一个。
运行时支持库实际上会保留中断矢量空间、我必须对此进行回写
在 TI、我不会在这里将自己称为嵌入式编程的大师、但我已经为中断驱动的设计使用了各种芯片。 您使中断变得远远比它们更难。 如果您不打算记录这一点、您能否至少向我提供几个线索?
[引用 user="Jason Heeris82"]哦,将“运行时支持库”设置为“ "中的"CCS 仍会使项目与 rts55x.lib 链接。 那么、即使我想禁用它、我也无法禁用它、看起来是这样吗?
[/报价]
事实上 、Build > C5500 Linker > File Search Path > Disable automatic RTS selection (构建> C5500链接器>文件搜索路径>禁用需要检查的自动 RTS 选择)下有一个额外的选项。 为什么会有一个" ”但不提这一点的选择不在我的范围之内。 当然、如果我删除它、我没有_c_int00、因此没有入口点。 所以... 据我所知、TI C5515在没有大量工作的情况下无法独立运行。
还有另一件事:C5515有一个单存取 ROM 段映射到 中断所在的存储器范围。
[引述]
零等待状态 ROM 位于 CPU 字节地址范围 FE 0000h - FF FFFFh。 是的
由四个16K 字块组成、总共128K 字节的 ROM。 每个 ROM 块可以执行一个
每个周期的访问次数(一次读取或一次写入)。 可通过内部程序或数据总线访问 ROM、
而不是 DMA 总线。 ROM 地址空间可由软件映射到外部存储器或
通过 ST3状态寄存器中的 MPNMC 位写入内部 ROM。
标准器件包括驻留在 ROM 中的引导加载程序、引导加载程序代码为
硬件复位后立即执行。 当 ST3状态寄存器的 MPNMC 位域被置位时
通过软件、片上 ROM 被禁用并且不存在于存储器映射和字节地址中
范围 FE 0000h - FF FFFFh 未映射。 硬件复位会始终清除 MPNMC 位、因此不会清除
可在硬件复位时禁用 ROM。 但是、软件复位指令不影响
MPNMC 位。 ROM 可由程序和数据总线访问。 每个 SAROM 块都可以执行
每个周期一个字读取访问。
[/报价]
如果我读得对、可能不对、那么就不可能对中断进行静态配置。 因为我甚至不能 通过 CCS 或其他方式写入该存储器、而不设置该 MPNMC 位、我只能通过软件执行该操作?
C55xx:加载程序:程序的一个或多个部分属于不可写的存储器区域。 这些区域实际上不会写入目标。 检查链接器配置和/或存储器映射。
这个芯片开始比我最初想象的要耗时和昂贵得多。
我将"interrupts.asm"转换为如下所示:
.ref _GPIO_ISR .ref _c_int00 .sect "向量" .align 256 .def _Reset .if __TMS320C55x_plus_Byte__ _Reset:.ivec _c_int00,STK_linear| RET_FAST | DATA_PTR_BYTE .else _Reset:.ivec _c_int00、use_RETA .endif NMI: ivec no_isr ;不可屏蔽中断 INT0: ivec no_isr ;外部用户中断#0 INT1: ivec no_isr ;外部用户中断#1 提示: ivec no_isr ;定时器#0/软件中断#4 PROG0: ivec no_isr ;可编程0中断 UART: ivec no_isr ; IIS #1接收中断 程序 G1: ivec no_isr ;可编程1中断 DMA: ivec no_isr ;DMA 中断 PROG2: ivec no_isr ;可编程2中断 COPROCFFT:.ivec NO_ISR ;协处理器 FFT 模块中断 程序3: ivec no_isr ;可编程3中断 LCD: ivec no_isr ;LCD 中断 SARADC: ivec no_isr ;SAR ADC 中断 XMT2: ivec no_isr ;I2S2 Tx 中断 RCV2: ivec no_isr ;I2S2 Rx 中断 XMT3: ivec no_isr ;I2S3 Tx 中断 RCV3: ivec no_isr ;I2S3 Rx 中断 RTC: ivec no_isr ;RTC 中断 SPI: ivec no_isr ;SPI 接收中断 USB: ivec no_isr ;USB 发送中断 GPIO: ivec _GPIO_ISR ;GPIO 中断 EMIF: ivec no_isr ;EMIF 错误中断 I2C: ivec no_isr ; IIC 中断 BERR: ivec no_isr ;总线错误中断 DLOG: ivec no_isr ;仿真中断- DLOG RTOS: ivec no_isr ;仿真中断- RTOS RTDXRCV:.ivec NO_ISR ;仿真中断- RTDX 接收 RTDXXMT:.ivec NO_ISR ;仿真中断- RTDX 发送 EMUINT: ivec no_isr ;仿真监视器模式中断 SINT30: ivec no_isr ;软件中断#30 SINT31: ivec no_isr ;软件中断#31 .text NO_ISR:b NO_ISR
当然、这解决了两个中断表竞争"矢量"部分的问题。
但是、它实际上仍然不是在写入表。 调试时、我在编程阶段看到这一点:
C55xx:加载程序:程序的一个或多个部分属于不可写的存储器区域。 这些区域实际上不会写入目标。 检查链接器配置和/或存储器映射。
在中断触发时、CPU 的 PC 以0xFFF061结束、看起来像一个直线循环:
FFF061:4a7e b #0xffffff061
同时、在 GPIO 中断地址0xFFFFA8处进行反汇编如下所示:
GPIO: ffffa8:eafff0 MOV HI (AC3 <<#0xfffff0)、* AR7 (short (#7)) ffab:615e BCC #0xffffff,AR6 >=#0 ffffad: 805f80 MOV dbl (* AR2 (T0))、dbl (* AR7)
为了使其更加混乱、IVPD 寄存器包含0x027F。
我不明白这里发生了什么。
IVPD 寄存器似乎由 eZdsp C5515电路板的默认 GEL 文件设置。 GEL 文件包含的内容
#define IVPD 0x0049
然后是...
Peripheral_Reset ()
{
int i;
*(short *) PSRCR@IO = 0x0020;
*(short *) PRCR@IO = 0x00BB;
for (i=0;i<0xff;i++);
*(short *) IVPD@data = 0x027F;//加载中断向量指针
GEL_TextOut ("重置外设已完成。\n");
}
????
GEL 文件 C5515_MapInit()中还有一个函数,它多次调用函数 GEL_MapAdd() ,这里有以下注释:
/*基于 MP/MC 值的内存映射(假设 MP/MC = 0)。 *
扼要重述一下、我的问题是:
出于我自己的好奇、还有另外一个问题:将 ISR 表的默认位置映射到与片上引导 ROM 相同的存储器范围内的原因是什么?
因此、我最终使我的中断正常工作、但我不得不忘记将它们放在存储器的末尾。 我认为不使用 C5515存储器空间的最后256个字节? 我最终所做的是将它们放在 DARAM 的末尾、如下所示:
内存
{...
DARAM7:O = 0x00E000 l = 0x001F00 /* 8kB 双存取 RAM 7 *
VECS:O = 0x00FF00 l = 0x000100 //中断矢量表*/
SARAM0:O = 0x010000 l = 0x002000 /* 8kB 单访问 RAM 0 */
...
}
在我的设置中更改 IPVD/H:
#define INTERRUPT_BASE (0x00FF) ... CSL_CPU_REGS->IVPD = INTERRUPT_BASE; CSL_CPU_REGS->IVPH = INTERRUPT_BASE;
我现在可以使用中断。
太容易了。