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.

[参考译文] RTOS/AM3358:链接 PRU 目标文件

Guru**** 2589300 points


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

https://e2e.ti.com/support/processors-group/processors/f/processors-forum/638949/rtos-am3358-linking-pru-object-file

器件型号:AM3358

工具/软件:TI-RTOS

大家好、

我一直在开发使用 BeagleBone Black 的计算机视觉产品、并且一直在开发用于获取帧并将其写入 RAM 的 PRU 代码。 我让 PRU 代码独立于 TI-RTOS 工作、我正在思考如何将代码集成到 TI-RTOS 中。 我已使 HexPRU 实用程序正常工作、就我所能说的那样。 我找到了显示如何完成 由 hexpru 实用程序生成的 obj 文件链接的 TI 链接器文件、但它使用 TI 编译器/链接器、而我创建的项目使用 GCC。 我希望重新计算链接器文件比重写我的项目所依赖的库的编译系统更容易。 我要发布的 lds 文件如下、它主要是锅炉板连接器文件。  

内存
{

SRAM: O = 0x402F0400、l = 0x0000FC00 // 64KB 内部 SRAM */
L3OCMC0:o = 0x40300000、l = 0x00010000 // 64KB L3 OCMC SRAM */
M3SHUMEM:o = 0x44D00000,l = 0x00004000 // 16kB M3共享统一代码空间*/
M3SHDMEM:o = 0x44D80000,l = 0x00002000 // 8kB M3共享数据存储器*/
DDR0: o = 0x8000000、l = 0x20000000 // 256MB 外部 DDR 组0 */
}//

链接器脚本,用于放置段和符号值。 应*
与定义存储器区域 DDR0的其他链接器脚本一起使用。
*它引用了以下符号,这些符号必须在代码中定义:
* entry:entry of reset handler
*
它定义了以下符号,这些符号可以在没有定义的情况下使用:
*__exidx_start
*__exidx_end
*__etext
*__data_start__
*__preinit_array_start
*__preinit_array_end
*__init_array_start
*__init_array_end *__init_array_end
*__fini_array_start
*___limi_array_end
*___bss_end______en__enss_en____en___en___en__en__en___en___en___en___en___en______en__en___en____en___





-与 Linaro 的半主机支持*
__StackLimit
*__StackTop
*__StackBase 兼容-与 Linaro 的半主机支持
*__stack
*/
entry (entry)

SECTIONS
{兼容
速记:
{
。 =对齐(0x10000);
Keep (*(.isr_vector))
*STARTUP_ARMCA8.o (.text)
} > DDR0

。 =对齐(4);
.text:
{
*(.text*)

Keep (*(.init))
Keep (*(.fini))

/*.ctors */
*crtbegin.o (.ctors)
*crtbegin?.o (.ctors)
*(exclude_file (* crtend?.o * crtend。o).ctors)
*(sort (.ctors。*))
*(.ctors)

/*.dtors */
*crtbegin.o (.dtors)
*crtbegin?.o (.dtors)
*(exclude_file (* crtend?.o * crtend。o).dtors)
*(sort (.dtors。*))
*(.ditors)

*(.rodata*)

Keep (*(.eh_FRAME*))
} > DDR0

arm.extab:
{
*(.arm.extab*.gnu.linkone.armextab.*)
} > DDR0

_exidx_start =.;
arm.exidx:
{
*(.arm.exidx*.gnu.linkone.armexidx.*)
} > DDR0
_exidx_end =.;


.data:
{
。 =对齐(4);
__data_start__=.;
*(VTABLE)
*(.data*)

。 =对齐(4);
/*预初始化数据*/
Provide_hidden (__preinit_array_start =.);
Keep (*(.preinit_array))
Provide_hidden (__preinit_array_end =.);

。 =对齐(4);
/*初始化数据*/
Provide_hidden (__init_array_start =.);
Keep (*(sort (.init_array。*)))
Keep (*(.init_array))
Provide_hidden (__init_array_end =.);


。 =对齐(4);
/* finit 数据*/
Provide_hidden (__fini_array_start =.);
Keep (*(sort (.fini_array。*)))
Keep (*(.fini_array))
Provide_hidden (__fini_array_end =.);



。 =对齐(4);
/*所有数据结束*/
__DATA_END__=;

} > DDR0

.bss:
{
。 =对齐(4);
_bss_start__=.;
*(.bss*)
*(通用)
__bss_end__=;
} > DDR0

堆(NoLoad):
{
/*下面的行可用于用已知值和填充存储器
*调试任何堆栈溢出。 为使其正常工作、请参见上面的说明符(NoLoad)
必须删除*、但代价是输出二进制大小增加*/
Fill (0xDEADBEF)
。 =对齐(4);
__end__=.;
结束=__end__;
/*下面创建的行与 Linaro 的半主机支持兼容*/
__HeapBase =__end__;
*(.heap*)
。 =。 + HEAPSIZE;
_HeapLimit=.;
} > DDR0

framegrabber_text:
{
PRU1_framegrabber.obj (.text);
}> DDR0

framegrabber_data:
{
PRU1_framegrabber.obj (.data);
}> DDR0

ramwriter_text:
{
PRU0_ramwriter.obj (.text);
}> DDR0_ramwriter



(.ramdata):{PRURAM0)




/*.stack 段不包含任何符号。 只是这样
*用于链接器计算堆栈段的大小并进行分配
*值到稍后堆栈符号*/
.stack (NoLoad):
{
/*下面的行可用于用已知值和填充存储器
*调试任何堆栈溢出。 为使其正常工作、请参见上面的说明符(NoLoad)
必须删除*、但代价是输出二进制大小增加*/
填充(0xBAD0BAD0)
。 =对齐(4);
__StackLimit=. ;
*(.stack*)
。 =。 + STACKSIZE;
_StackTop =。 ;
/*下面创建的行与 Linaro 的半主机支持兼容*/
__StackBase =。 ;
} > DDR0
提供(__stack =__StackTop);

} 

然后、我引用包含数据和指令文件的段、该文件(我希望)将包含 PRU 的数据和指令 RAM。  

const unsigned char __attribute__(((section ("framegrabber_text"))) framegrabber_inst[0x1000];
const unsigned char __attribute__((section ("framegrabber_data"))) framegrabber_writer [0x1000];
const ramchar __attribute_("0x1000_)("ramramram_attribute_)("0x1000_write_)[0x1000_writer_write_(
"0x1000)("ramramramram_write_)[0x1000_write_)(")("ramramramram_write_)(0x1000)

在所有这些文件的末尾、我会得到以下错误:

在[800000008001727b]加载的段 framegrabber_text 与在[800000008001727b]加载的段.text 重叠

我假设这是其余部分的错误。 是否有人知道如何修复此错误? 我已经能够将以前的 E2E 帖子和其他资源中的各种修复粘贴到一起、但我对 GCC 链接器脚本不了解、因此我觉得我在这里有点偏离我的联盟。 感谢您的任何帮助。 此外、这是我在这里发布的第一篇文章、因此如果这是错误的地方、请告诉我。

在  

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    RTOS 团队已收到通知。 他们将在这里作出回应。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    马克

    如果您只想将帧格式交换器和 ramwriter 放入 DDR 中、则您的段的.text 和.data 条目就足够了、并且不需要帧格式交换器和 ramwriter 的其他属性。

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

    车架、

    感谢您的回答。 帧格式电报和写入器需要进入 RAM、但它们需要能够由 C 代码通过数组引用、因为它们代表 PRU 代码的 DataRAM 和 IRAM 部分、并且需要通过 TI-RTOS 中的 PRU API 加载。

    也许我错过了在后台执行的重要步骤、但从 PRU-support-software 软件包中的 PRUDemo 项目加载 PRU 代码的示例代码就是这样、但对于 TI 工具链、我希望尽可能避免使用该示例代码。 它使用 RUN_START 指令、该指令看起来与 ld 中的指令不同。

    "="">为方便起见、https:/git.ti.com/pru-software-support-package/pru-software-support-package/blobs/master/pru_cape/pru_demo/StarterWare/pru_cape_demo_ccs.cmd ">这是我要引用的链接器文件:

    -stack 0x1000 /*软件堆栈大小 */
    -heap 0x2000 /*堆区域大小 */
    -e entry
    //由于我们使用'entry'作为入口点符号,因此编译
    
    
    器会发出*//*警告(#10063-D:指定的"_c_int00"以外的入口点符号:*//*"entry")。 CCS 版本(5.1.0.08000)停止从命令编译 出现
    警告时显示*//*行。 因此、此警告将通过抑制
    标志下方的*//*。 */
    --diag_suppress=10063
    --retain=PRU_LED0_image.obj (*)
    --retain=PRU_LED1_image.obj (*)
    --retain=PRU_Switch_image.obj
    (*)--retain=PRU_Audio_image.obj (*)
    --retain=PRU_Hardware_image.obj
    
    
    
    
    
    
    
    
    
    (*)*/themory_memory_memory_retorq.obj (*)*/rtorq_memory_memory_memory_orq.obj (*
    DDR_MEM :org = 0x80000000 len = 0x80000 /* RAM */
    }
    /*指定段分配到内存中*/
    SECTIONS
    {
    text: entry : load >0x80000000
    text:load > DDR_MEM /*代码 *
    .data:load > DDR_MEM /*初始化的全局和静态变量*/
    .bss :加载> DDR_MEM /*未初始化或零初始化*/
    /*全局和静态变量*/
    RUN_START (BSS_START)
    RUN_END (BSS_END)
    .const:load > DDR_MEM /*全局常量 *
    .cinit:加载> DDR_MEM
    .stack:LOAD > DDR_MEM HIGH //0x87FFF000 /*软件系统堆栈 *
    LED0_text:{PRU_LED0_image.obj (.text)}load > DDR_MEM run_start (LED0_INST)
    LED0_DATA:{PRU_LED0_IMAGE.obj (.data)}LOAD > DDR_MEM RUN_START (LED0_DATA)
    LED1_text:{PRU_LED1_IMAGE.obj (.text)}LOAD > DDR_MEM RUN_START (LED1_INST)
    LED1_DATA:{PRU_LED1_IMAGE.obj (.data)}LOAD > DDR_MEM RUN_START (LED1_DATA)
    sw_text:{PRU_Switch_image.obj (.text)}load > DDR_MEM run_start (sw_inST)
    sw_data:{PRU_Switch_image.obj (.data)}load > DDR_MEM run_start (sw_data)
    AUDIO_TEXT:{PRU_Audio_image.obj (.text)}load > DDR_MEM run_start (AUDIO_INST)
    
    AUDIO_DATA:{PRU_Audio_image.obj (.data)}load > DDR_MEM run_start (AUDIO_DATA)
    HW_UART_TEXT:{PRU_Hardware_UART_IMAGE.obj (.text)}负载> DDR_MEM RUN_START (UART_INST)
    HW_UART_DATA:{PRU_Hardware_UART_IMAGE.obj (.data)}负载> DDR_MEM RUN_START (UART_DATA)
    
    TEMPSEN0_TEXT:{PRU_RATE_RUN_IMAGE.obj (.data)}DDR_INST_RUN_RATE (UART.AM_RATE)
    TEMPSENSOR0_DATA:{PRU_HDQ_TempSensor0_image.obj (.data)}load > DDR_MEM run_start (slave_data)
    TEMPSENSOR1_text:{PRU_HDQ_TempSensor1_image.obj (.text)}load > DDR_MEM run_start (master_INST_INSTRUMENST)
    TEMPSENSOR1_DATA:{PRU_HDQ_TempSensor1_image.obj (.data)}load > DDR_MEM run_start (master_data)
    } 

    这里是相应定义数组的位置

    extern const unsigned char LED0_INST[0x1000];
    extern const unsigned char LED0_data[0x1000];
    extern const unsigned char LED1_INST[0x1000];
    extern const unsigned LED1_DATA[0x1000];
    extern const unsigned char sw_conST[0x1000];
    extern unsigned data[extern unsigned char
    
    
    0x1000];extern unsigned data_unsigned extern unsigned char unsigned exuart];exuart_conST[0x1000]
    
    extern const unsigned char slave_inst[0x1000];
    extern const unsigned char slave_data[0x1000];
    extern const unsigned char master_inst[0x1000];
    extern const unsigned char master_data[0x1000]; 

    让我知道我的要求是否合理

    感谢您的观看、

    Marc

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

    您提到的链接用于使用 Linux remoteProc 加载 PRU。 有关 TI-RTOS 集成、请参阅 PRUSS 驱动程序-
    processors.wiki.ti.com/.../Processor_SDK_RTOS_PRUSS

    对于 IRAM 和数据 RAM 加载、您可以使用以下 API:
    PRUICSS_setPRUBuffer();
    PRUICSS_pruWriteMemory();
    请参阅 pdk_am335x_1_0_8/packages/ti/drv/pruss/docs/doxygen/html/pruicss__drv_8c.html 中的详细信息

    帧电报和写卡器最初可以保留在 DDR 中。

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

    车架、

    感谢你的帮助。 我有最后一个问题。 如果我的 PRU 代码中的.text 和.data 段存储在链接器文件中的通用.text 和.data 段中、如何将缓冲区指向它们? 这是我尝试使用链接器文件中的 framegrabber 和 ramwriter 段实现的目标、但链接器抱怨段重叠。 如果有一个使用 GCC 实现此目的的现有示例、这将会大有帮助。  

    我的基本策略是:

    从已解析到数据和文本段的 PRU 工程中导入 OBJ 代码

    创建 C 样式数组、用于保存每个 PRU 的数据和文本段(通过链接器魔法完成-此处所述的器件)

    通过您之前引用的 PRUICSS API 写入这些缓冲器。

    这似乎是可行的、但当我强制重叠不通过 lds 文件中的 at()指令发生时、入口点似乎希望指向 PRU 文件中的.text 段、而不是实际可执行代码。  

    感谢您对此提供的帮助

    Marc

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

    此主题应帮助您向前推进- e2e.ti.com/.../2324171、其中详细介绍了将 PRU out 文件转换为.bin 文件和.c 数组、然后执行 PRU 映像的步骤。

    此致、
    Garrett