4.常见问题解答

4.1.CLA 是否独立于 C28x CPU?

是。一旦 CLA 由主 CPU 配置,它就可以独立执行算法。CLA 有自己的总线结构、寄存器组、流水线和处理单元。此外,CLA 可以直接访问大量外设寄存器,因此适合处理对时间要求严格的控制循环以及过滤或数学算法。

4.2.C28x 和 CLA 可以同步吗?

同步是通过启动 CLA 执行(无论是通过外设中断还是写入特定寄存器)来完成的。此外,CLA 可以中断主 CPU。

4.3.可以对 CLA 进行编程吗?

是。CLA 硬件中没有内置算法。可以使用 C 语言或汇编语言对 CLA 进行完整编程。

4.4.有适用于 CLA 的 C 编译器吗?

有。TMS320C28x 代码生成工具可为编译 CLA 的 C 代码提供支持。但鉴于 CLA 架构和编程环境的局限性,对编译 CLA 的 C 语言提供的支持有一些限制。TMS320C28x 优化 C/C++ 编译器用户指南中的“CLA 编译器”一章对此进行了说明。

4.5.CLA 和 C28x 之间如何共享数据?

C2000Ware 中的示例演示了 C28x 和 CLA 之间的数据交换。这是通过两个 CPU 都可以直接访问的 RAM 块完成的。由于 CLA 和 C28x 代码位于同一个工程中,可以使用以下步骤共享数据:

  1. 创建一个包含常见常量和变量的共用头文件。将此文件包含在 C28x C 和 CLA 代码中。
  2. 使用数据段 pragma 语句和链接器文件将变量放置在合适的 RAM 中。
  3. 在 C28x .c 代码中定义共享变量。C28x 和 CLA 共享全局变量必须在 C28x .c 代码(而非 CLA 代码)中定义。数据页在每个器件上的工作方式不匹配,在 C28x 上受到的限制更多。因此,在 C28x 端定义的数据可以在 CLA 端访问,但反之则不行。
  4. 在 CPU 至 CLA 消息 RAM 中,用主 CPU 初始化变量。
  5. 在 CLA 至 CPU 消息 RAM 中,用 CLA 任务初始化变量。这个初始化任务可由主 C28x 软件启动。

4.6.C28x 和 CLA 上的数据类型有何不同?

另请参见

C28x 和 CLA 数据类型记录在特定版本的编译器用户指南中。(编译器和汇编工具

为了避免在 CLA 和 C28x 之间共享数据时出现歧义,强烈建议您使用包含大小信息的类型声明。例如,请勿使用 int。使用 int32_tuint16_t(在 stdint.h 中针对 C28x 和 CLA 进行定义)。

例如:

1 2 3 4 5 6 7 8 9 10 11 12 13 14
// // in the shared header file and main .c file // Does not indicate the size of the variable // An unsigned int on C28x is 16-bit and an unsigned int on CLA is 32-bits // unsigned int t0; unsigned int t1; // // Instead use C99 data types with size information // #include <stdint.h> uint16_t t0; uint16_t t1;

整数:

  • 对于 CLA,int 是 32 位
  • 对于 C28x,int 是 16 位

指针:

指针在 C28x 和 CLA 上的解释不同。C28x 将指针视为 32 位数据类型(地址总线大小为 22 位宽,只能适合 32 位数据类型),而 CLA 仅有 16 位的地址总线大小。

假设以下结构在共享头文件(即 C28 和 CLA 共用)中声明,并定义和分配给 .c 文件中的存储器段:

列表 4.1 指针大小问题
 /******************************************************************** shared.h C28x and CLA Shared Header File ********************************************************************/ typedef struct{ float a; float *b; float *c; }foo; /******************************************************************** main.c Main C28x C-code Source File ********************************************************************/ #pragma(X,"CpuToCla1MsgRam") // Assign X to section CpuToCla1MsgRam foo X; /******************************************************************** test.cla CLA C-code Source File ********************************************************************/ __interrupt void Cla1Task1 ( void ) { float f1,f2; f1 = *(X.b); f2 = *(X.c); //Pointer incorrectly dereferenced //Tries to access location 0x1503 instead //of 0x1504 }

假设 C28x 编译器将在 CpuToCla1MsgRam 段的顶部为 X 分配空间,如下所示:

元素 说明 C28x 地址
X.a a 是地址中的一个 32 位浮点数 0x1500-0x1501
X.b b 是地址中的一个 32 位指针 0x1502-0x1503
X.c b 是地址中的一个 32 位指针 0x1504-0x1505

CLA 将以不同的方式解释此结构。CLA 将指针“b”和“c”视为 16 位宽,因此错误地取消引用指针 c。

元素 说明 CLA 地址
X.a a 是地址中的一个 32 位浮点 0x1500-0x1501
X.b b 是地址中的一个 16 位指针 0x1502
X.c c 是地址中的一个 16 位指针 0x1503

解决方案是声明一个新指针,如下所示:

创建一个新指针“CLA_FPTR”,它是一个 32 位整数和一个浮点指针的联合体。CLA 编译器识别两个元素中较大的一个(32 位整数)的大小,因此将指针与低 16 位对齐。现在指针“b”和“c”都将占用 32 位内存空间,任何试图取消引用指针 c 的指令都将访问正确的地址 0x1504。

列表 4.2 指针大小解决方案
 /******************************************************************** shared.h C28x and CLA Shared Header File ********************************************************************/ typedef union{ float *ptr; //Aligned to lower 16-bits Uint32 pad; //32-bits }CLA_FPTR; typedef struct{ float a; CLA_FPTR b; CLA_FPTR c; }foo; /******************************************************************** main.c Main C28x C-code Source File ********************************************************************/ #pragma(X,"CpuToCla1MsgRam") //Assign X to section CpuToCla1MsgRam foo X; /******************************************************************** test.cla CLA C-code Source File ********************************************************************/ __interrupt void Cla1Task1 ( void ) { float f1,f2; f1 = *(X.b.ptr); f2 = *(X.c.ptr); //Correct Access }

4.7.什么可以触发任务(也称为 ISR)?

以下来源可以启动(触发)任务:

  1. 外设中断
  2. 软件触发
  3. 另一个 CLA 任务
  4. 在某些器件上,可以将特定任务指定为后台任务。请参阅识别器件特定 CLA 功能以了解详细信息。

C28x 配置 CLA。在配置过程中,指定哪些器件资源触发哪些任务。通常有两个寄存器用于配置任务的触发条件。

  • 较旧的器件使用 MPISRCSEL1 寄存器(即 2803x、2805x、2806x)。
  • 较新的器件使用系统寄存器 CLA1TASKSRCSELx(2837xD/S、F28004x...)。

另请参见

触发源可以是中断,也可以是通过软件实现的 C28x CPU。务必记住,触发源只是启动任务的机制。触发源不限制任务内容或任务访问什么寄存器。

  • 主 C28x CPU

    可以使用 IACK #16bit 指令启动任务。例如,IACK 0x003 将标记中断 1 和中断 2。这与设置强制寄存器 (MIFRC) 中的位相同

  • 另一个 CLA 任务:

    在某些器件上,CLA 无权直接强制标记另一个任务。下面是几个选项:

    • 中断 C28x 并强制该任务作为中断服务例程的一部分。
    • 写入 ePWM 寄存器以强制中断,进而强制标记任务。

4.8.是否支持嵌套任务?

CLA 有自己的获取机制,可以独立于 CPU 运行和执行任务。一次只处理一个任务 - 除非启用后台任务,否则没有将任务嵌套。在具有 CLA 类型 2 支持后台任务的器件上,可以进行一级嵌套。请参阅 CLA 类型

4.9.任务的代码大小是否受限制?

比如有一个任务是中断操作。它是一种在 CLA 接收到中断时执行的算法。任务的大小仅受可用程序内存和 CLA 程序计数器的限制。

任务的起始地址是可配置的。每个任务具有一个相关中断矢量(MVECT1 至 MVECT8)。对于 0 类 CLA(CLA 类型),此向量会保存任务的起始地址(作为第一个程序位置的偏移量)。对于所有其他类型,此向量会保存任务的整个 16 位地址。

  • CLA 0 类:

    程序空间限制为 12 位或 4096 个字。所有 CLA 指令都是 32 位的,所以在 4k x 16 的程序空间内,您可以拥有大约 2k 的 CLA 指令。

  • CLA 1 类及以上:

    程序空间为 16 位宽,剩余的低 64K 字空间可用作程序空间。有关如何为 CLA 配置/分配存储器空间的信息,请参阅器件特定文档。

MSTOP 指令指示任务结束。任务开始后,CLA 将执行指令,直到遇到“MSTOP”指令。

4.10.CLA 可以直接访问哪些外设寄存器?

警告

请参阅器件特定数据表。如果器件上有多个 CLA,它们可能无法连接到所有相同的外设。(器件特定功能

答案取决于 C2000 MCU 系列。一般来说,近期发布的器件系列支持 CLA 访问更多外设。下面的列表指示了查看数据表的哪些部分:

  1. 器件方框图:指示哪些外设连接到 CLA 总线。
  2. 器件级存储器映射:哪些内存块可以配置为 CLA 访问
  3. 外部接口 (EMIF) 存储器映射:指示 CLA 可以访问的任何存储器区域
  4. 外设寄存器存储器映射:CLA 可以访问哪些特定外设寄存器

一些示例:

  • 2803x:直接访问 ADC 结果、ePWM+HRPWM 和比较器寄存器。
  • 2806x:直接访问 ADC 结果、ePWM+HRPWM、eCAP、eQEP 和比较器寄存器。
  • 2807x:直接访问 ADC 模块(包括结果)、ePWM+HRPWM、eCAP、eQEP、比较器子系统、DAC 子系统、SPI、McBSP、uPP、EMIF、GPIO
  • 2837x:直接访问 ADC 模块(包括结果)、ePWM+HRPWM、eCAP、eQEP、比较器子系统、DAC 子系统、SPI、McBSP、uPP、EMIF、GPIO

4.11.CLA 可以向 C28x 发送中断吗?

待办事项

检查 F28004x 上是否存在新机制

是。CLA 可以向 C28x 发送中断,如下所示:

  • 任务结束:

    CLA 将向 PIE(外设中断扩展块)发送中断,让主 CPU (C28x) 知道任务已完成。每个任务在 PIE 中都有一个相关矢量。这个中断在相关矢量完成时自动触发。例如,当任务 1 完成时,PIE 中的 CLA1_INIT 将被标记。如果此中断未启用,则 C28x 将忽略它。

  • 强制中断:

    这适用于 CLA 类型 1 及更高级别。(注意:启用此选项时,它会自动禁用任务结束中断。)CLA 具有软件中断功能,其中任务可以启用和强制中断主 CPU。例如,任务 1 可以通过写入 CLA1SOFTINTEN 寄存器的 TASK2 位来启用任务 2 的软件中断,然后通过写入 CLA1SOFTINTFRC 寄存器的 TASK2 位来强制中断。

  • 溢出和下溢:

    C28x PIE 中有用于 CLA 浮点上溢和下溢条件的专用中断。

4.12.CLA 是否有权访问所有存储器块?

否,可供 CLA 使用的存储器块取决于器件系列。

另请参见

器件特定数据表中的存储器映射指示 CLA 可以访问哪些块。(器件特定功能

  • 主 CPU 可以为 CLA 分配特定存储器块
  • 内存映射指示可以为使用 CLA 配置哪些存储器块。
  • 在某些器件中,存储器的使用(程序或数据)是固定的。而在其他器件中,可以将 CLA 可访问的一些存储器块配置为程序存储器或数据存储器。

此外,还有具有固定配置的专用消息 RAM。也会在存储器映射中寻找这些。下面给出了两个例子。某些器件带有附加消息 RAM。

  • CLA 到 CPU 消息 RAM:CLA 可以读取/写入,主 CPU 只能读取
  • CPU 到 CLA 消息 RAM:CPU 可以读取/写入,CLA 只能读取

4.13.如果 C28x 和 CLA 可以访问同一个器件资源,哪个优先?

器件会自动仲裁对资源的访问。也就是说,规定了优先级顺序。

另请参见

如需了解更多信息,请在器件特定技术参考手册 (TRM) 中搜索“仲裁”一词。(器件特定功能。)

请记住,如果主 CPU 对外设寄存器执行读取-修改-写入操作,并且 CLA 在读取和写入之间修改同一个寄存器,则 CLA 所做的更改可能会丢失。一般来说,最好不要让两个处理器对相同的寄存器进行写入操作。

如果将 CLA 配置为响应外设中断,则该中断仍将转到 C28x PIE。这使两个 CPU 都可以在需要时做出响应。

4.14.如何衡量任务的持续时间?

  • 选项 1:使用计时器:

    一种方法是使用自由运行的计时器来捕获任务执行所用的周期数。CLA 可以访问 PWM 计时器。例如,您可以捕获 C 中的周期数,如下所示:

    1. 任务开始时,CLA 读取计时器
    2. 执行任务
    3. 任务结束时,CLA 再次读取计时器
    4. 计算 (1) 和 (3) 之间的周期数
    ct1 = EPwm1Regs.TBCTR; // //..... code to be measured here .....// ct2 = EPwm1Regs.TBCTR; delta_ct = ct2 - ct1;
  • 选项 2:使用 GPIO 引脚:

    在某些器件上,CLA 可以直接访问 GPIO 引脚。在这种情况下,CLA 可以在要测量的代码前后切换引脚,而不是读取计时器。使用示波器监控引脚以及时测量增量。

  • 计算开销

    由于触发了 CLA 任务并通知 C28x 任务已完成,这会产生一些开销。为了测试此开销,您可以使用 C28x 上的计时器来为 CLA 任务的开始和停止计时。

    1. 使用 C28x 读取计时器
    2. 通过 C28x 软件启动 CLA 任务
    3. 等待 MIRUN 位清零
    4. 使用 C28x 读取计时器
    5. 计算 (1) 和 (4) 之间的增量
    6. 另请参阅此博文:https://e2e.ti.com/support/microcontrollers/c2000/f/171/t/738758

4.15.C28x 可以终止 CLA 任务吗?

是。如果一个中断已经被标记,但是任务还未运行,那么主 CPU 可以使用 MICLR 寄存器来清除此标记。

如果任务已经运行,那么一个软复位(在 MCTL 中)将终止此任务并将 MIER 寄存器清零。如果您希望将所有 CLA 寄存器清零,可以使用 MCTL 寄存器中的硬复位选项。

4.16.链接器中的“Symbol, X, referenced in a.obj, assumes that data is blocked but is accessing non-blocked data in b.obj.Runtime failures may result”警告是什么意思?

这是在 C2000 代码生成工具 v20.2.x.LTS 中添加的一个诊断程序,用于检测何时根据非阻塞定义访问假设被阻塞的数据。

关于这方面的一个常见用例是 C28 代码中使用的全局 CLA 定义。更多背景信息,请参阅 20.2.x LTS 用于新诊断程序的 README 条目