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.

[参考译文] CCS/LAUNCHXL-F28377S:访问 CLA 内的 c 结构

Guru**** 2341440 points
Other Parts Discussed in Thread: CONTROLSUITE
请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/587229/ccs-launchxl-f28377s-accessing-c-struct-within-cla

器件型号:LAUNCHXL-F28377S

工具/软件:Code Composer Studio

分为两部分的问题。

我之前创建了一个简单的环形缓冲区类、用于在 CPU 和 CLA 之间共享队列。 类标头包含用于存储它的 c 结构定义。 但是,CLA 任务永远无法访问结构(variable->buffer)中的任何内容。 因此、我将环形缓冲器的各个部分拆分为单独的变量、这样就可以正常工作了。 但是、我很好奇是否还有其他我可以测试的东西、或者结构对于 CLA 编译器来说是否太不透明。

第二部分。 上述结构(以及现在的变量)存储在 CPUtoCLA 消息 RAM 中(因为 CLA 只需要读取、而不需要写入队列)。 然而、我刚刚意识到 CLA 数据空间可从 CPU 进行读取/写入访问-并且我可以使其尽可能大。 我很好奇、使用 CLA 数据空间是否有任何不利之处、因为我在其他地方还有其他受到消息 RAM 限制的大型变量。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    [引用 user="Adam Jones"]但是,CLA 任务无法访问结构(变量->缓冲区)中的任何内容。

    如果您的结构有指针、则可能是这样做的原因。 指针在 CLA 和 CPU 上具有不同的大小、如果您尚未将它们定义为指针和 uint32的联合体、您将在 CLA 侧看到访问问题。 您可以在器件固件用户指南中找到有关"处理指针"的部分。  

    对于2837xD、您可以在 C:\ti\controlSUITE\device_support\F2837xD\V210\doc\F2837xD-FRM-EX-UG.pdf、第4.7.1节中找到该选项。

    [引用 USER="Adam Jones"]我很好奇使用 CLA 数据空间是否有任何不利之处,因为我在其他地方还有其他很大的变量受到消息 RAM 的限制。

    仲裁。 如果 CPU 正在写入该结构体、同时 CLA 正在从中读取、则最终可能会出现陈旧的数据、因为内核之间的仲裁是循环方案、请参阅 TRM 的第2.11.1.6节

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    啊、我明白了。 我以前读过该文件太快了。 我现在看到"叶"函数不能超过1级深。 鉴于这些指针的差异、我不确定如何编写一个将在 CPU 和 CLA 之间工作的 c 结构。 所有数据类型均为16位宽、结构仅为:

    typedef 结构{
    uint16_t *缓冲区; //缓冲区
    uint16_t 大小; //缓冲区大小
    uint16_t 可用; //可用
    使用 uint16_t; //已使用
    uint16_t read_index;//读取索引
    uint16_t write_index;//写入索引
    }ring 缓冲区_t;
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    我想我会尝试这种方法(尽管我现在无法验证)。

    typedef union{
    uint16_t * ptr;//与低16位对齐
    uint32_t pad;//32位
    } cla_uint16_t_ptr;

    typedef 结构{
    uint16_t 大小; //缓冲区大小
    uint16_t 可用; //可用
    使用 uint16_t; //已使用
    uint16_t read_index;//读取索引
    uint16_t write_index;//写入索引
    cla_uint16_t_ptr 缓冲区; //缓冲区
    }ring 缓冲区_t;
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    [引用 user="Adam Jones">我之前看过该文档的速度太快了。 我现在看到"leaf "函数不能超过1级深[/quot]

    该限制适用于较旧的(6.2.0及更高版本)编译器。 使用较新的编译器可以有多个嵌套级别、限制由分配的暂存区数量决定。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    现在、一周左右之后、我能够测试这个。 虽然它符合要求很好、但我无法访问 CLA 函数本身内部的任何结构成员。

    我复制了以下相关代码。 我可以从 CPU 中毫无问题地获得已用值、但我无法从 CLA 中读取它。

    网址为 ring_buffer.h

    typedef union{
    uint16_t * ptr;//与低16位对齐
    uint32_t pad;//32位
    }aligned_uint16_t;
    
    typedef 结构{
    uint16_t 大小; //缓冲区大小
    uint16_t 可用; //可用
    使用 uint16_t; //已使用
    uint16_t read_index;//读取索引
    uint16_t write_index;//写入索引
    aligned_uint16_t 缓冲区;//缓冲
    区}ring 缓冲区_t; 

    在 dsp_output.c 中

    #pragma DATA_SECTION (DSP_CODE_queue_low、"CLA_DATA");
    ring 缓冲区_t * DSP_CODE_queue_low;
    

    网址为 dsp_output_cla.h

    extern ring_buffer_t * dsp_code_queue_low; 

    在 DSP_OUTP_CLA.CLA 中

    _interrupt void CLA_task2_process_dsp_strobe _queue (void){
    
    //增加 tic
    DSP_CURRENT_Tic = DSP_CODE_queue_low->已使用;
    //实数代码只会增加 tic 直到发生翻转(调试器显示正常增加效果很好)
    }
    
    

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    DSP_CODE_queue_low 的地址是什么? 您还可以发布与这行代码关联的反汇编代码

    DSP_CURRENT_Tic = DSP_CODE_queue_low->已使用;

    我看到您已将指针定义到 ring 缓冲区_t (DSP_CODE_queue_low)的位置、但我看不到它应该指向的 ring 缓冲区_t 对象。 它指向的对象也必须驻留在 CLA_DATA 段中

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    我即将发布。 我认为第一个问题是、创建环形缓冲区依赖于 calloc 和 malloc (并且、CLA 没有堆)。 因此、我尝试重写一些内容、以便编译器创建必要的存储器。

    在 dsp_output.c 中

    #pragma DATA_SECTION (DSP_CODE_LOG_LOW_STRUCT、"CLA_DATA");
    RING_BUFF_t DSP_CODE_LOG_LOW_STRUCT;
    #pragma DATA_SECTION (DSP_CODE_LOG_LOW、"CLA_DATA");
    ring_buffer_t * dsp_code_queue_low;
    #pragma DATA_SECTION (dsp_code_queue_lust_buffer、"cla_data");
    uint16_t dsp_code_queue_lust_buffer[code_ring buffer_length];
    
    ...
    void init_dsp_output(){
    //手动初始化 ring 缓冲区
    DSP_CODE_queue_low =&DSP_CODE_queue_low_struct;
    DSP_CODE_QUEUGE_LOAD_LLOW ->大小= CODE_RING_BUFFER_LOW_LENGTH;
    dsp_code_queue_low->available = code_ring_buffer_low_length;
    DSP_CODE_QUEK_LOW_->已使用= 0;
    DSP_CODE_QUEUGE_LOW_->READ_INDEX = 0;
    DSP_CODE_QUEK_LOW->WRITE_INDEX = 0;
    DSP_CODE_LOG_LOAD->buffer.ptr = DSP_CODE_LOG_LOW_BUFFER
    ;}
    
    但是,这也不起作用。 

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    好的、您在链接器命令文件中将 CLA_DATA 分配给了哪个 RAMLSx (s)。 您是否已将这些 RAMLSx 块配置为 CLA 数据存储器(通过 MemCfgRegs)?
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    我使用的是以下代码:

    //选择 RAMLS0和 RAMLS1作为 CLA 的编程空间
    //首先将 LS0和 LS1配置为与 CLA 共享,然后配置
    //将空格设置为程序块(阻止 CPU 访问)
    MemCfgRegs.LSxMSEL.bit.MSEL_LS0 = 1; /CLA 可访问
    MemCfgRegs.LSxCLAPGM.bit.CLAPGM_LS0 = 1;//程序块(无 CPU 访问)
    MemCfgRegs.LSxMSEL.bit.MSEL_LS1 = 1; /CLA 可访问
    MemCfgRegs.LSxCLAPGM.bit.CLAPGM_LS1 = 1;//程序块(无 CPU 访问)
    
    //下一步将 RAMLS2和 RAMLS3配置为 CLA 的数据空间
    //首先将 LS2和 LS3配置为与 CLA 共享,然后配置
    //将空格设置为数据块(CPU 仍可访问)
    MemCfgRegs.LSxMSEL.bit.MSEL_LS2 = 1; /CLA 可访问
    MemCfgRegs.LSxCLAPGM.bit.CLAPGM_LS2 = 0;//数据块(CPU 访问)
    MemCfgRegs.LSxMSEL.bit.MSEL_LS3 = 1; /CLA 可访问
    MemCfgRegs.LSxCLAPGM.bit.CLAPGM_LS3 = 0;//数据块(CPU 访问) 

    如果"cla_data"(LS2、3)中的其他12个左右 CLA 变量(包括基元和基元数组)运行得非常好、 这是我尝试使用的唯一管道和/或结构指针。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    嗯、我希望能轻松解决。

    在这种情况下、我们需要查看反汇编。 您能否布置这些线路的反汇编、

    DSP_CODE_queue_low =&DSP_CODE_queue_low_struct;
    DSP_CODE_QUEUGE_LOAD_LLOW ->大小= CODE_RING_BUFFER_LOW_LENGTH;
    dsp_code_queue_low->available = code_ring_buffer_low_length;
    DSP_CODE_QUEK_LOW_->已使用= 0;
    DSP_CODE_QUEUGE_LOW_->READ_INDEX = 0;
    DSP_CODE_QUEK_LOW->WRITE_INDEX = 0;
    dsp_code_queue_low->buffer.ptr = dsp_code_queue_low_buffer;

    以及 DSP_CODE_queue_low 和 DSP_CODE_queue_low_struct 的地址
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    Vishal、

    感谢您的快速回答。 我能够获得代码、主要是在昨晚进行了一些更改:

    //定义(在 c 中)
    #pragma DATA_SECTION (dsp_code_queue_low_struct、"cla_data");
    ring_buffer_t dsp_code_queue_llow_struct;
    #pragma DATA_SECTION (dsp_code_queue_low_buffer、"cla_data");
    uint16_t DSP_code_queue_low_buffer[code_ring buffer_low_length+1];//需要额外1个来容纳 ring buffer//init
    
    (在 c 中)
    DSP_code_queue_struct.size = code_ring buffer_length_length;
    DSP_code_queue _low_struct.available = DSP_code_ring_ral_rure_rure.t
    dsp_code_queue_low_struct.used
    
    = DSP_ring_ral_ring_r.ral_rength_ring_ring_r.index = DSP_ral_ring_0_r.t = code_ral_ring_ral_ral.t
    dsp_code_queue_low_struct.buffer.ptr = DSP_CODE_queue_low_buffer;
    
    //CLA 用法(随机片段)
    dsp_code_queue_low_struct.used > 0
    CLA_cling_buffer_read (&DSP_CODE_queue_struct,&DSP_current_code);// a cla copy of the same ring buffer function in c
    

    我发现非常有趣的是、虽然队列(有两个、虽然我在这里只显示一个)正在工作、但当我遇到向整个队列添加新元素的情况时、它将始终锁定。 如果我一次从未尝试添加超过队列长度的队列、它将快速清空(CLA 任务的时间为每毫秒处理2个元素)。

    void send_dsp_code (uint16_t 代码、bool 为_high_priority){
    //假设它可以等待空间
    
    如果(是_HIGH_PRIORITY){
    while (dsp_code_queue_high_struct.available = 0);
    
    环缓冲区写入(&DSP_CODE_QUEK_HIGH_STRUCT,&CODE);
    } 否则{
    while (dsp_code_queue_low_struct.available = 0);
    
    环缓冲区写入(&DSP_CODE_queue_low_struct、&code);
    }
    } 

    但是、如果我对代码进行两次更改:1)添加任务后 ISR、如果任一队列几乎已满、该 ISR 会增加一些等待时间;2)更改上述 SEND_DSP_CODE 以执行相同操作。

    _interrupt void CLA_task2_process_dsp_strobe _queese_isr (){
    静态 uint16_t LAST_LOW_Available;
    静态 uint16_t LAST_HIGH_Available;
    
    //检查任一队列是否被占用
    if (dsp_code_queue_high_struct.available!=last_high_available || dsp_code_queue_low_struct.available!= last_low_available){
    
    //如果可用空间少于2个,则添加延迟以防止队列锁定
    if (dsp_code_queue_high_struct.available < 2 || dsp_code_queue_low_struct.available < 2){
    DELAY_US (1000);//微小延迟以允许 CLA 消耗缓冲
    器}
    
    last_low_available = dsp_code_queue_low_struct.available;
    LAST_HIGH_Available = DSP_CODE_queue_high_struct.available;
    }
    
    //确认 CLA 任务结束中断
    PieCtrlRegs.PIEACk.bit.ACK11 = 1;//所有 CLA 后 ISR 都在组11
    中}
    
    void send_dsp_code (uint16_t code、bool is_high_priority){
    //假设它可以等待空间
    
    如果(是_HIGH_PRIORITY){
    if (dsp_code_queue_high_struct.available < 2){delay_US (1000);}
    
    环缓冲区写入(&DSP_CODE_QUEK_HIGH_STRUCT,&CODE);
    } 否则{
    if (dsp_code_queue_low_struct.available < 2){delay_US (1000);}
    
    环缓冲区写入(&DSP_CODE_queue_low_struct、&code);
    }
    } 

    我还需要询问您对反汇编的任何建议、因为虽然我已经打开了.lst 文件的创建、但它只为.c 文件而不是.cla 创建这些文件、 我无法真正了解 C 代码和汇编代码之间的相关性。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    Adam、

    DELAY_US 调用一个函数 F28x_usDelay、它是一个 C28x 汇编函数。 它不适用于 CLA。

    [引用 user="Adam Jones">我还必须询问您对反汇编的任何建议、就像我已经打开了.lst 文件的创建、它只为.c 文件创建这些文件、而不是为.cla 创建这些文件。 我无法真正了解 C 代码和汇编代码之间的相关性。

    在调试代码时,您可以通过 CCS 菜单栏(View->Disassembly 窗口)打开反汇编窗口,然后从其中复制代码。 或者、在项目属性(C2000编译器>高级选项->汇编器选项)中、您可以打开--keep_asm (保留生成的汇编文件)和--c_src_interlist (使 C 代码及其相应的指向汇编出现在.asm 文件中)。 这使得分析装配体更容易。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    DELAY_US 仅从 CPU 调用。 请注意、我说过这两个函数是从 CPU 调用的、其中一个函数是任务后 ISR。 我将为您提供获取装配体的指导。