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.

[参考译文] AM6422:计时器 DDR

Guru**** 2465890 points


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

https://e2e.ti.com/support/processors-group/processors/f/processors-forum/1454716/am6422-timer-ddr

器件型号:AM6422

工具与软件:

您好、

 我发现一个问题。 在 DDR 上运行时、我定义了一个周期为1S、时钟频率为200MHz 的计时器。 我在接收到标准 PPS 后记录计时器的值、然后记录当前的第二个脉冲和上一次脉冲。  PPS 的计时器计数差 在理论上应该相同、但事实并非如此、我将在下面发布实际测量结果。 您能帮助分析这种情况吗? 在 MSRAM 上运行时也是如此、没有如此大的偏差。我还会发送我的 link.cmd 文件。

从记录的数据来看、相邻 PPS 之间的时间间隔差相对较大、差异大于1us。 根据这个时钟频率、我想不应该是这样。μ s

为了获得计时器值、我执行了以下处理操作:

PPS 脉冲中断函数:μ s

void PPS_INT()

{

cap32val = TimerP_getCount(gTimerBaseAddr[CONFIG_TIMER1S]);
cap32val = cap32val-(0xffffffff-(200000000-1));

B_coding.os_time_us1 = cap32val;
if(B_coding.os_time_us1<B_coding.os_time_us2)
    B_coding.Interval1 = B_coding.os_time_us1 + 200000000 - B_coding.os_time_us2;
else
    B_coding.Interval1 = B_coding.os_time_us1 - B_coding.os_time_us2;
inter[bcodecnt++] = B_coding.Interval1;
// TIM_CLR(gTimerBaseAddr[CONFIG_TIMER1S]);
inter[bcodecnt++] = val;
if(bcodecnt==300)
    bcodecnt = 0;
B_coding.os_time_us2 = B_coding.os_time_us1;

/* This is the stack that is used by code running within main()
 * In case of NORTOS,
 * - This means all the code outside of ISR uses this stack
 * In case of FreeRTOS
 * - This means all the code until vTaskStartScheduler() is called in main()
 *   uses this stack.
 * - After vTaskStartScheduler() each task created in FreeRTOS has its own stack
 */
--stack_size=32768
/* This is the heap size for malloc() API in NORTOS and FreeRTOS
 * This is also the heap used by pvPortMalloc in FreeRTOS
 */
--heap_size=32768
-e_vectors  /* This is the entry of the application, _vector MUST be plabed starting address 0x0 */

/* This is the size of stack when R5 is in IRQ mode
 * In NORTOS,
 * - Here interrupt nesting is enabled
 * - This is the stack used by ISRs registered as type IRQ
 * In FreeRTOS,
 * - Here interrupt nesting is disabled
 * - This is stack that is used initally when a IRQ is received
 * - But then the mode is switched to SVC mode and SVC stack is used for all user ISR callbacks
 * - Hence in FreeRTOS, IRQ stack size is less and SVC stack size is more
 */
__IRQ_STACK_SIZE = 4096;
/* This is the size of stack when R5 is in IRQ mode
 * - In both NORTOS and FreeRTOS nesting is disabled for FIQ
 */
__FIQ_STACK_SIZE = 4096;
__SVC_STACK_SIZE = 4096; /* This is the size of stack when R5 is in SVC mode */
__ABORT_STACK_SIZE = 4096;  /* This is the size of stack when R5 is in ABORT mode */
__UNDEFINED_STACK_SIZE = 4096;  /* This is the size of stack when R5 is in UNDEF mode */

SECTIONS
{
    /* This has the R5F entry point and vector table, this MUST be at 0x0 */
    .vectors:{} palign(8) > R5F_VECS

    /* This has the R5F boot code until MPU is enabled,  this MUST be at a address < 0x80000000
     * i.e this cannot be placed in DDR
     */
    GROUP {
        .text.hwi: palign(8)
        .text.cache: palign(8)
        .text.mpu: palign(8)
        .text.boot: palign(8)
        .text:abort: palign(8) /* this helps in loading symbols when using XIP mode */
    } > R5F_TCMA

    /* This is rest of code. This can be placed in DDR if DDR is available and needed */
    GROUP {
        .text:   {} palign(8)   /* This is where code resides */
        .rodata: {} palign(8)   /* This is where const's go */
    } > DDR_1

    GROUP {
        /* This is the resource table used by linux to know where the IPC "VRINGs" are located */
        .resource_table: {} palign(4096)
    } > DDR_0

    /* This is rest of initialized data. This can be placed in DDR if DDR is available and needed */
    GROUP {
        .data:   {} palign(8)   /* This is where initialized globals and static go */
    } > DDR_1

    /* This is rest of uninitialized data. This can be placed in DDR if DDR is available and needed */
    GROUP {
        .bss:    {} palign(8)   /* This is where uninitialized globals go */
        RUN_START(__BSS_START)
        RUN_END(__BSS_END)
        .sysmem: {} palign(8)   /* This is where the malloc heap goes */
        .stack:  {} palign(8)   /* This is where the main() stack goes */
    } > DDR_1

    /* This is where the stacks for different R5F modes go */
    GROUP {
        .irqstack: {. = . + __IRQ_STACK_SIZE;} align(8)
        RUN_START(__IRQ_STACK_START)
        RUN_END(__IRQ_STACK_END)
        .fiqstack: {. = . + __FIQ_STACK_SIZE;} align(8)
        RUN_START(__FIQ_STACK_START)
        RUN_END(__FIQ_STACK_END)
        .svcstack: {. = . + __SVC_STACK_SIZE;} align(8)
        RUN_START(__SVC_STACK_START)
        RUN_END(__SVC_STACK_END)
        .abortstack: {. = . + __ABORT_STACK_SIZE;} align(8)
        RUN_START(__ABORT_STACK_START)
        RUN_END(__ABORT_STACK_END)
        .undefinedstack: {. = . + __UNDEFINED_STACK_SIZE;} align(8)
        RUN_START(__UNDEFINED_STACK_START)
        RUN_END(__UNDEFINED_STACK_END)
    } > DDR_1

    /* Sections needed for C++ projects */
    GROUP {
        .ARM.exidx:  {} palign(8)   /* Needed for C++ exception handling */
        .init_array: {} palign(8)   /* Contains function pointers called before main */
        .fini_array: {} palign(8)   /* Contains function pointers called after main */
    } > DDR_1

    /* General purpose user shared memory, used in some examples */
    .bss.user_shared_mem (NOLOAD) : {} > USER_SHM_MEM
    /* this is used when Debug log's to shared memory are enabled, else this is not used */
    .bss.log_shared_mem  (NOLOAD) : {} > LOG_SHM_MEM
    /* this is used only when IPC RPMessage is enabled, else this is not used */
    .bss.ipc_vring_mem   (NOLOAD) : {} > RTOS_NORTOS_IPC_SHM_MEM
}

/*
NOTE: Below memory is reserved for DMSC usage
 - During Boot till security handoff is complete
   0x701E0000 - 0x701FFFFF (128KB)
 - After "Security Handoff" is complete (i.e at run time)
   0x701F4000 - 0x701FFFFF (48KB)

 Security handoff is complete when this message is sent to the DMSC,
   TISCI_MSG_SEC_HANDOVER

 This should be sent once all cores are loaded and all application
 specific firewall calls are setup.
*/

MEMORY
{
    R5F_VECS  : ORIGIN = 0x00000000 , LENGTH = 0x00000040
    R5F_TCMA  : ORIGIN = 0x00000040 , LENGTH = 0x00007FC0
    R5F_TCMB0 : ORIGIN = 0x41010000 , LENGTH = 0x00008000

    /* when using multi-core application's i.e more than one R5F/M4F active, make sure
     * this memory does not overlap with other R5F's
     */
    MSRAM     : ORIGIN = 0x70080000 , LENGTH = 0x40000

    /* This section can be used to put XIP section of the application in flash, make sure this does not overlap with
     * other CPUs. Also make sure to add a MPU entry for this section and mark it as cached and code executable
     */
    FLASH     : ORIGIN = 0x60100000 , LENGTH = 0x80000

    /* when using multi-core application's i.e more than one R5F/M4F active, make sure
     * this memory does not overlap with other R5F's
     */
    /* Resource table must be placed at the start of DDR_0 when R5 cores are early booting with Linux */
    DDR_0       : ORIGIN = 0xA0100000 , LENGTH = 0x1000
    DDR_1       : ORIGIN = 0xA0101000 , LENGTH = 0xEFF000

    /* shared memory segments */
    /* On R5F,
     * - make sure there is a MPU entry which maps below regions as non-cache
     */
    USER_SHM_MEM            : ORIGIN = 0xA5000000, LENGTH = 0x80
    LOG_SHM_MEM             : ORIGIN = 0xA5000000 + 0x80, LENGTH = 0x00004000 - 0x80
    RTOS_NORTOS_IPC_SHM_MEM : ORIGIN = 0xA5004000, LENGTH = 0x0000C000
    LINUX_IPC_SHM_MEM       : ORIGIN = 0xA0000000 , LENGTH = 0x100000
}

我们目前对这一问题没有任何怀疑、我们希望你能提出一些解决办法。

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

    我认为通过软件读取寄存器时、精度不会高得多。  从高级操作系统读取寄存器时、会由于内部数据路径的变化而具有固有的可变性。  我认为您必须使用 ICSS 获得更高的准确性。   

    此致、

    James

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

    您好、

       感谢您的建议、能否提供相关示例? 我从未使用过您提到的 ICSS。

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

    您好、Wanglili、

    您能否提供有关您要尝试执行的操作的其他信息?

    例如、您是否 尝试通过 PPS 信号跨多个器件同步时间? 您是否只是尝试设置一个软件计时器、以便 MCU+代码在每 X 段时间后执行一项任务?

    如果您尝试同步时间、从哪里得到时间? (例如、以太网 PTP?) R5F 是接收时间、还是从其他地方(例如 Linux)接收?

    通常、我不建议通过写入 GPIO 引脚来手动生成1PPS 信号进行时间同步。 这应该由 PWM 输出处理,该输出根据时钟主站的更新调整波形的时间(例如,从 Linux 端,我们使用 CPSW 内的 CPTS,根据我们通过 CPSW 以太网、协议 https://software-dl.ti.com/processor-sdk-linux/esd/AM64X/10_00_07_04/exports/docs/linux/NetworkPTP/Kernel/CPSW-PThtml 读入 Kernel_Drivers 的时间,生成 Foundational_Components 信号)。

    我将向 MCU+团队成员发送您的主题、以征求进一步意见。

    此致、

    Nick

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

    您好、

       感谢您的答复。 我们使用的方法实际上非常简单。 我们使用 R5F 内核、并配置一个串行端口和一个 GPIO 外部中断来接收 GPS 模块的信号。1S 计时器使用外部中断来识别 GPS 的 PPS。 当 GPS 的 PPS 到达时、计时器计数被清除、并通过读取大约30秒的脉冲计数来调整 GPS 的 PPS。 计数值用于达到1S 计时器中断、GPS 的 PPS 基本上同时到达。 目前、在 DDR 上运行该程序时、接收 GPS PPS 信号的外部中断的计数每次都有很大不同。 从理论上讲,当 GPS 的 PPS 到达计时器计数被清除时,当 GPS 的 PPS 再次出现时,计时器计数值应该几乎相同。我 不知道 这是什么原因?

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

    您好、

    有任何新消息?

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

    您好!

    我认为已有 e2e、如果您可以、我将让另一位工程师继续讨论: https://e2e.ti.com/support/processors-group/processors/f/processors-forum/1432141/am6422-sdk-8-6-timer-compare-and-capture-modes/5585718#5585718

    此致、

    Vaibhav

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

    您好、

    此链接没有答案。