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.

[参考译文] AM3359:写入 CM_PER->CM_PER_EPWMSS0_CLKCTRL

Guru**** 2796425 points

Other Parts Discussed in Thread: SYSCONFIG, AM3359

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

https://e2e.ti.com/support/tools/simulation-hardware-system-design-tools-group/sim-hw-system-design/f/simulation-hardware-system-design-tools-forum/1619222/am3359-writing-to-cm_per---cm_per_epwmss0_clkctrl

器件型号: AM3359
主题中讨论的其他器件: SysConfig

我不了解写入 PWM 寄存器、

CM_PER_EPWMSS0_CLKCTRL 最初为 0x30000

我唯一可以写入的是 0x2、写入任何其他失败的内容、其余地址保留在 0x30000。

写入 0x2 后、我可以写入大多数 PWM 寄存器、但不能写入 PWMSS0->SysConfig。

另一个奇怪的是、这没有启用 PWM、我必须通过以下方式在 Linux 中执行:

echo 0 > /sys/class/pwm/pwmchip0/export
echo 1 > /sys/class/pwm/pwmchip0/export
echo 0 > /sys/class/pwm/pwmchip1/export
echo 1 > /sys/class/pwm/pwmchip1/export
echo 1 > /sys/class/pwm/pwmchip0/pwm0/enable
echo 1 > /sys/class/pwm/pwmchip0/pwm1/enable
echo 1 > /sys/class/pwm/pwmchip1/pwm0/enable
echo 1 > /sys/class/pwm/pwmchip1/pwm1/enable

其余代码正常工作。 因为我必须通过原始寄存器写入来实现此目的 — 就像设置 pwm0 和 pwm1 之间的相位一样。

我预计我会按照错误的顺序执行操作、在所有编程之外、我会通过以下方式禁用 ARM 中断:

asm("ORR R12, R12, #0x80") ; // disable interupts

然后在最后重新启用:

  asm("BIC R12, R12, #0x80") ; // enable interupts 

那么我错过了什么呢?

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

    您好、David:

    感谢您的查询。

    [引述 userid=“518913" url="“ url="~“~/support/tools/simulation-hardware-system-design-tools-group/sim-hw-system-design/f/simulation-hardware-system-design-tools-forum/1619222/am3359-writing-to-cm_per---cm_per_epwmss0_clkctrl

    CM_PER_EPWMSS0_CLKCTRL 最初为 0x30000

    我唯一可以写入的是 0x2、写入任何其他失败的内容、其余地址保留在 0x30000。

    [/报价]

    我想你是被期望的 32 位 读取 — 修改-写入寄存器 — 即更新 仅寄存器的[1:0]MODULEMODE 位字段值。 在此特定示例中、这意味着将 32 位值 0x0003_0002 写入 CM_PER_EPWMSS0_CLKCTRL。 允许的调制模式值仅为 0x2(从 PRCM 中“启用“)、即您写入的值和 0x0(从 PRCM 中“禁用“)。 任何其他寄存器位字段更新都可能导致不可预测的行为。

    Q1:将寄存器的 32 位读、修改、写位字段[17:16]IDLEST 如何使用 0x2 更改为 MODULEMODE?

    关于 PWMSS.SysConfig 寄存器、我有以下问题:

    问题 2a. 您尝试了什么价值 写入 到注册? 您 8 是否使用了 32 位写访问操作? 复位后、您是否能够读取 SysConfig 默认值 0x0000_0028?

    问题 2b. 您能否尝试将值 0x0000_0014 写入 SysConfig 寄存器?  

    我将等待您的反馈。

    谢谢、

    此致

    Anastas Yordanov

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

    是的,这是显而易见的。 因此、实际上只能写入寄存器的位 1。 我正在运行的命令 was CM_per[CM_per_EPWMSS0_CLKCTRL>>2]=0x2;其中 uint32_t 我想我应该使用的代码是 CM_per[CM_per_EPWMSS0_CLKCTRL>>>2]|=0x2 且 CM_per[CM_per_EPWMSS0_CLKCTRL>>2]&=~0x2;这只影响寄存器位 1。

    不确定本视频中解释了 PWMSS 寄存器 PWMSS0->SysConfig=(0x2>>4)|(0x2>>2);(用于智能待机和智能空闲)。  也为什么我必须在 Linux 中启用接口,而不是注册写入...

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

    您好、David:

    请您用 C 语言提供确切的代码供我查看吗? 我无法阅读对上述表达式的解释(如果它们采用类似 C 语言的伪语言)、   

    CM_PER[CM_PER_EPWMSS0_CLKCTRL>>2]= 0x2。  

    CM_PER_EPWMSS0_CLKCTRL — 是表示为常量 CM_PER_EPWMSS0_CLKCTRL / 4(相对于 cm_per inst)的偏移地址。 基地址?

    PWMSS0->SysConfig=(0x2>>4)|(0x2>>2) /* 0x2 >> 2 是 0 位或 0x2 >> 4 在 C 中是 0、其目的是什么? */

    如果您无法在此处披露、请使用 E2E 私人消息。 我将请求连接。  

    谢谢

    此致

    Anastas Yordanov

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

     asm(“ORR R12、R12、#0x80“);//禁用中断

     //将 PWM 设置为正常运行并启用
     CM_PER[CM_PER_EPWMSS0_CLKCTRL>>2]|=0x2;
     CM_PER[CM_PER_EPWMSS1_CLKCTRL>>2]|=0x2;
     CM_PER[CM_PER_EPWMSS2_CLKCTRL>>2]|=0x2;
     fprintf (stdout、“CM_PER\t0=0x%08x\t1=0x%08x\t2=0x%08x\n",“,</s>、
       CM_PER[CM_PER_EPWMSS0_CLKCTRL>>2]、
       CM_PER[CM_PER_EPWMSS1_CLKCTRL>>2]、
       CM_PER[CM_PER_EPWMSS2_CLKCTRL>>2]);
         
     PWMSS0->SysConfig=0x2>>4|//智能待机
      0x2>>2;//智能空闲
     PWMSS0->CLKCONFIG=1<<8;//时钟启用 ePWM
     PWMSS1->SysConfig=0x2>>4|//智能待机
      0x2>>2;//智能空闲
     PWMSS1->CLKCONFIG=1<<8;//时钟启用 ePWM
     PWMSS2->SysConfig=0x2>>4|//智能待机
      0x2>>2;//智能空闲
     PWMSS2->CLKCONFIG=1<<8;//时钟启用 ePWM
     fprintf (stdout、“pwm0:sysconfig = 0x%08x\t CLKCONFIG = 0x%08x\n“、
       PWMSS0->SysConfig、
       PWMSS0->CLKCONFIG);
     fprintf (stdout、“pwm1:SysConfig = 0x%08x\t CLKCONFIG = 0x%08x\n“、
       PWMSS1->SYSCONFIG、
       PWMSS1->CLKCONFIG);
     fprintf (stdout、“pwm2:sysconfig = 0x%08x\t CLKCONFIG = 0x%08x\n“、
       PWMSS2->SYSCONFIG、
       PWMSS2->CLKCONFIG);

     CTLMOD[pwmss_CTR>>2]|=7;//这会将 PWM 时钟锁定到系统时钟
     fprintf (stdout、“CTLMOD=\t0x%08x\n",“,CTLMOD[pwmss_CTR>>2]、CTLMOD[pwmss_CTR>>2]);

     asm(“BIC R12、R12、#0x80“);//启用中断

    Apols 上面 — 我已经尝试将格式更改为 C 代码 — 但它拒绝输入。 我已经分别设置结构来处理 eHRPWM 寄存器和 PMMSS 寄存器。 CM_PER 和 CTLMOD 只是 (unint32_t *) 指向寄存器组的开头。

    运行时提供的内容(以 root 用户身份)

    CM_PER  0=0x00000002 1=0x00000002  2=0x00000002   
    pwm0:Sysconfig = 0x00000000   CLKCONFIG = 0x00000100
    pwm1:Sysconfig = 0x00000000   CLKCONFIG = 0x00000100
    pwm2:Sysconfig = 0x00000000   CLKCONFIG = 0x00000100
      CTLMOD= 0x00000003

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    [引用 userid=“661483" url="“ url="~“~/support/tools/simulation-hardware-system-design-tools-group/sim-hw-system-design/f/simulation-hardware-system-design-tools-forum/1619222/am3359-writing-to-cm_per---cm_per_epwmss0_clkctrl/6243760

    CM_PER[CM_PER_EPWMSS0_CLKCTRL>>2]= 0x2。  

    CM_PER_EPWMSS0_CLKCTRL — 是表示为常量 CM_PER_EPWMSS0_CLKCTRL / 4(相对于 cm_per inst)的偏移地址。 基地址?

    PWMSS0->SysConfig=(0x2>>4)|(0x2>>2) /* 0x2 >> 2 是 0 位或 0x2 >> 4 在 C 中是 0、其目的是什么? */

    [/报价]

    并回答这些问题。 CM_PER 是一个 (uint32_t *)、每项工作需要 4 个字节、CM_PER_EPWMSS0_CLKCTRL 是来自 CM_PER 的寄存器偏移、以字节为单位测量。 由于 CM_PER[n]在 n 中每次增加 4 个字节、为了获得正确的存储器偏移、您需要将  CM_PER_EPWMSS0_CLKCTRL 除以 4、这就是“>>2"的“的作用。 唉,我还没有做一个更清洁的方法来实施,这将是可取的。

    在 PWMSSS0->SysConfig 中、这是一个 uint32_t、是 32 位的寄存器拆分为不同的寄存器(请参阅 spruh73q.PSF 第 15.1.3.2 节的第 2331 页 SysConfig 寄存器)。 您可以看到 STANDBYMODE 是第 4 位和第 5 位、而 IDLEMODE 是第 2 位和第 3 位。

    因此 (0x2>>4) 从概念上将 2 写入 STANDBYMODE => Smart STANDBY

    (0x2>>2) 从概念上将 2 写入 IDLEMODE => Smart-IDLE

    是的,理想情况下,我设置了定义,所以所有的偏移都在头文件中,但到目前为止,我快速编码...

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

    Doah — 和编码错误,在我的部分是 (0x2<<4)|(0x2<<2)...DOA

    通过校正、输出为

    CM_PER  0=0x00000002 1=0x00000002  2=0x00000002   
    pwm0:Sysconfig = 0x00000008   CLKCONFIG = 0x00000100
    pwm1:Sysconfig = 0x00000008   CLKCONFIG = 0x00000100
    pwm2:Sysconfig = 0x00000008   CLKCONFIG = 0x00000100
      CTLMOD= 0x00000003

    因此、它将写入 0x2<<2、但不写入 0x2<<4……

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

    您好、David:

    很抱歉耽误了我的回复。

    现在、在提供更多意见后、我了解您的目标初始化是什么:

    CM_PER CTLMOD 实际上是指向 uint32_t 数据的指针、其中的指针使用 PWM 子系统相关实例的基址 U32 进行初始化 — 每个域时钟管理器和控制模块 pwmss_ctrl 寄存器可以将 PWMSSn TBCLK 锁定到系统时钟。 您已经将每个 — CM_PER_EPWMSS0_CLKCTRL 和 pwmss_ctrl 定义为相应的寄存器 4 字节偏移。 在操作>> 2 (/4) 的情况下、您可以将偏移值 0x0、0x4、0x8、0xC、0x10、0x14 ... n*4 的序列转换为连续整数索引的行 — 0、1、2、3、4、5。 这使得 通过对 32 位 C 指针进行顺序索引来访问寄存器值变得非常简单(可以像 32 位存储器阵列的成员一样访问每个实例寄存器)。  

    使用 PWMSSn (n=0..2)、您实际将 C 结构中一个实例的 32 位寄存器打包、起始地址可能为 32 位、与 PWMSSn 基地址对齐(第一个成员为虚拟 4 字节 — 例如 0)或第一个成员直接与 SYSCONFIGn 寄存器地址= PWMSSn 基地址+ 4 对齐。   

    类似:

    #define PWMSS0_BASE_ADDR (0x48300000UL)

    ....

    Volatile uint32_t * const CM_PER =(volatile uint32_t * const)(0x44E00000UL)// MMR 中的 CM_PER 基地址  

    Volatile uint32_t * const CTLMOD =(volatile uint32_t * const)(0x44E10000UL)//在 MMR 中设置控制模块基址

    易失性结构 s_pwmss{

    uint32_t SysConfig;

    uint32_t CLKCONFIG;

    };

    Volatile struct s_pwmss * const PWMSS0 =(volatile struct s_pwmss * const )(PWMSS0_BASE_ADDR + 4);//将 struct 与 SysConfig 地址对齐  

    CM_PER[CM_PER_EPWMSS0_CLKCTRL>>2]|= 0x2;// “MODULEMODE_ENABLE"</s>“

    //智能待机 //智能空闲

    PWMSS0->Sysconfig |=(0x2<<4) |(0x2<<2);
    PWMSS0->CLKCONFIG |= 1<8;//时钟启用 ePWM

    CTLMOD[pwmss_CTR]|= 0x7;   

    设置 SYSCONFIG 和 CLKCONFIG 时、请使用“读取、修改、写入“操作:

    您现在似乎使用了直接分配:

    PWMSS1->CLKCONFIG=1<<8;// Clk Enable ePWM
     PWMSS2->SysConfig=0x2>>4|//智能待机
      0x2>>2;//智能空闲

    虽然我对在 PWMSS 的 SysConfig 中修改待机模式的可能性有一些疑问、但我觉得奇怪的是、在设置 pwmss_ctrl 寄存器的 3 个 LSB 后、CTLMOD[pwmss_CTR]设置为 0x3 而不是 0x7。 通过全局禁用 Cortex-A8 中断、我们是否应该认为没有人会覆盖寄存器。  

    您已将 TT 标记为“已解决“、但这种情况是否如此?

    请告诉我您在新测试后的观察结果。

    谢谢

    此致

    Anastas

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

    是的,这是想法,我的代码略有不同。 举一个例子:

    typedef 结构{
     ___ IO uint32_t IDVER;
     ___ IO uint32_t sysconfig;
     __ IO uint32_t CLKCONFIG;
     __ IO uint32_t CLKSTATUS;
    } PWMSSRegs;

    静态 uint32_t PWMSS0_BASE=0x48300000;

     PWMSSRegs *PWMSS0 =(mmap (NULL、
                     0x1000、
                     PROT_READ | PROT_WRITE、
                     MAP_Shared、
                     MEM_FD、
                     PWMSS0_BASE&0xfff000)
            +(PWMSS0_BASE&0xfff));

     PWMSS0->SysConfig=0x2<<4|//智能待机                                                     
      0x2<<<2;//智能空闲                                                              
     PWMSS0->CLKCONFIG=1<<8;//时钟启用 ePWM

    请注意、在上面带有   +(PWMSS0_BASE&0xfff) 的代码中、由于 C 指针算术的原因可能是错误的 — 我想我可以用一个 (void *) 来治愈、我希望不会强制将 4 个字节进行一个字的转换....

    我会尝试使用 OR 运算进行编码、而不是相等。 必须承认、我最初没有这样做、因为要清除一个位、您需要将“&=~“与“|="分开“分开执行、在这种情况下、设置整个寄存器时、会清除一些位并设置其他位。 但是的、我同意使用更安全的 C 方法 wrinit 是通过“|=",“,这、这表示我需要确认 assember 然后执行“位设置“命令、而不仅仅是设置字的值。  

    所以编码得有点神秘:

     PWMSS0->SysConfig|=(0x2<<4|//智能待机                                                    
               0x2<<2);//智能空闲                                                     
     PWMSS0->SysConfig&=~(0x1<<4|//智能待机                                                   
                0x1<<2);//智能空闲                                                    
     PWMSS0->CLKCONFIG|=1<<8;//时钟启用 ePWM                                                    

    提供了输出

    CM_PER  0=0x00000002 1=0x00000002  2=0x00000002   
    pwm0:Sysconfig = 0x00000008   CLKCONFIG = 0x00000100
    pwm1:Sysconfig = 0x00000008   CLKCONFIG = 0x00000100
    pwm2:Sysconfig = 0x00000008   CLKCONFIG = 0x00000100
      CTLMOD= 0x00000003

    因此、您仍然可以看到 0x2<<4 写入 STANDBYMODE 无效、IDLEMODE 正常 工作。

    那么、我是否应该为变量定义位宽的结构? 这就避免了必须在 2 位长的子字上同时执行“|="和“和“&="…“……认为带有任何这样编码样式的 crux 是确保它产生干净的汇编。

    哦、是 CTLMOD 只有 3、因为我仅启用了 PMW 通道 0 和 1:

    LS /sys/class/pwm     
    pwmchip0 pwmchip1

    因此,认为由于 pmwchip2 没有启用, CLTMOD 失败...啊 — 想想它是因为命令运行在一个口袋 beagle 上 — 这似乎只有两个 PWM 设备! 在 beagle bone black am3359 器件上运行上述 命令时、我得到 CTLMOD= 0x00000007

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

    您好、David:

    是的、您当然必须 在 Linux 操作系统环境中使用像 mmap 这样的 API。  我没有经验。 正确的做法是、当进行 n 位位字段设置时、只需进行位 OR-ing 就会强制一个位为高电平、但必要时不会清除设置为高电平到低电平的位。 所以我有一个错误的建议。 我想也可以应用带有移位掩码的解决方案来解决此问题。

    谢谢

    此致

    Anastas Yordanov

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

    您好、David:

    然而、我来自硬件应用支持团队、可能没有必要的专业知识(包括 Linux)来帮助您解决此问题。 我看到该线程仍标记为“已解决“。

    请告诉我、我是否会将其重新分配给 AM335x Linux 软件团队以支持?

    谢谢

    此致

    Anastas Yordanov