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.

sitara系列 访问寄存器问题咨询

Other Parts Discussed in Thread: AM3359

请教一下:

1、sitara系列的ARM端程序访问外设寄存器,是不是只能通过指针的形式?

2、用C2000的那种位域结构体定义的外设头文件访问外设寄存器,进调试模式系统就跑飞。把头文件换成指针结构就没问题

  • 操作位应该也是可以的,但一般通过指针来访问,寄存器部分的详细配置选项一般都会定义好,直接操作就可以了。
  • 比较好奇,用位域结构体访问为什么会跑飞,而指针结构访问就没问题,这个和是否开启MMU功能有关系吗,另外,我调试sitara系列的ARM端的时候,程序运行时,寄存器观察窗口显示的片内外设寄存器都无法观察,显示的是不能识别,只能暂停或者打断点程序运行到断点处停下来才能正确观察到寄存器,这个是不是也和MMUC是否开启有关系呢?
  • user18914063 说:
    我调试sitara系列的ARM端的时候,程序运行时,寄存器观察窗口显示的片内外设寄存器都无法观察,显示的是不能识别,只能暂停或者打断点程序运行到断点处停下来才能正确观察到寄存器,这个是不是也和MMUC是否开启有关系呢?

    是裸机下还是RTOS或者Linux?有没有基于TI给出的例程上测试看一下能否看到寄存器。

    位域结构体访问方式贴出来看一下。跟指针访问测试的是同一个寄存器吗?

  • 你好,是裸机代码,位域结构体的相关地址分配定义在AM3359的CMD文件里面,这种访问导致跑飞,然后改成了指针形式,相关代码如下:
    // GPIO 寄存器组
    struct hw_GPIORegs
    {
    Uint32 Revision;//IP核版本
    Uint32 rsvd1[3];
    union GPIOSYS_CONFIG Config;//系统配置
    Uint32 rsvd2[3];
    union GPIO_EOI Eoi;
    union GPIO_Regs IRQSTATUS_RAW0;
    union GPIO_Regs IRQSTATUS_RAW1;
    union GPIO_Regs IRQSTATUS0;
    union GPIO_Regs IRQSTATUS1;
    union GPIO_Regs IRQSTATUS_SET0;
    union GPIO_Regs IRQSTATUS_SET1;
    union GPIO_Regs IRQSTATUS_CLR0;
    union GPIO_Regs IRQSTATUS_CLR1;
    union GPIO_Regs IRQWAKEN0;
    union GPIO_Regs IRQWAKEN1;
    Uint32 rsvd3[50];
    union GPIO_SYS_STATUS SYS_STATUS;
    Uint32 rsvd4[6];
    union GPIORegs_CTRL Ctrl; //控制寄存器
    union GPIO_Regs OE; //输出使能,方向寄存器
    union GPIO_Regs IN_DATA; //输入数据寄存器
    union GPIO_Regs OUT_DATA; //输出数据寄存器
    union GPIO_Regs LowLevelDetection0;//低电平检测使能
    union GPIO_Regs LowLevelDetection1;//低电平检测使能
    union GPIO_Regs RisDetection;//上升沿检测使能
    union GPIO_Regs FalDetection;//下降沿检测使能
    union GPIO_Regs DebouncEnable;//去抖动使能
    union GPIO_DEBOUNCTIME DebouncTime;//去抖动时间
    Uint32 rsvd5[14];
    union GPIO_Regs CLR_DATAOUT; //复位寄存器
    union GPIO_Regs SET_DATAOUT; //置位寄存器
    Uint32 rsvd6[922];
    };
    // GPIO 外设存储空间映射
    extern volatile struct hw_GPIORegs GpioARegs;
    extern volatile struct hw_GPIORegs *GpioBRegs;
    extern volatile struct hw_GPIORegs *GpioCRegs;
    extern volatile struct hw_GPIORegs *GpioDRegs;

    以上是GPIO的寄存器,很奇怪,端口A可以直接按位域结构体的形式定义在CMD文件里面,其余IO口只能是指针形式,下面是A口在CMD文件里面的地址分配
    MEMORY
    {
    PAGE 0: /* Program Memory */
    PAGE 1: /* Data Memory */
    //ETH_DESCRIPTOR : o = 0x4A102000, l = 0x00000100 /* 256B MDIO物理地址 */
    //MDIO_REG : o = 0x4A101000, l = 0x00000100 /* 256B MDIO物理地址 */
    //CM_PER_REG : o = 0x44E00000, l = 0x00000400 /* 1KB CM_PER物理地址 */
    //CM_WKUP_REG : o = 0x44E00400, l = 0x00000100 /* 256B CM_PER物理地址 */
    //CM_DPLL_REG : o = 0x44E00500, l = 0x00000100 /* 256B CM_PER物理地址 */
    //CM_MPU_REG : o = 0x44E00600, l = 0x00000100 /* 256B CM_PER物理地址 */
    //CM_DEVICE_REG : o = 0x44E00700, l = 0x00000100 /* 256B CM_PER物理地址 */
    //CM_RTC_REG : o = 0x44E00800, l = 0x00000100 /* 256B CM_PER物理地址 */
    //CM_CEFUSE_REG : o = 0x44E00A00, l = 0x00000100 /* 256B CM_PER物理地址 */

    //PRM_PER_REG : o = 0x44E00C00, l = 0x00000100 /* 256B CM_PER物理地址 */
    //PRM_CEFUSE_REG : o = 0x44E01200, l = 0x00000100 /* 256B CM_PER物理地址 */
    //CTRL_MODULEREG : o = 0x44E10000, l = 0x00002000 /* 128KB 控制模块物理地址 */
    GPIOAREG : o = 0x44E07000, l = 0x00001000 /* 4KB GPIOA物理地址 */
    //GPIOBREG : o = 0x4804C000, l = 0x00001000 /* 4KB GPIOB物理地址 */
    //GPIOCREG : o = 0x481AC000, l = 0x00001000 /* 4KB GPIOC物理地址 */
    //GPIODREG : o = 0x481AE000, l = 0x00001000 /* 4KB GPIOD物理地址 */
    //TIMER2_REG : o = 0x48040000, l = 0x00001000 /* 4KB GPIOD物理地址 */
    //INTCREG : o = 0x48200000, l = 0x00001000 /* 4KB GPIOD物理地址 */
    //PWMSS0REG: o = 0x48300000 l = 0x00000100 /* 4KB PWMSS0物理地址 */
    //ECAP0REG : o = 0x48300100 l = 0x00000080 /* 80B Ecap0物理地址 */

    //PWMSS1REG: o = 0x48302000 l = 0x00000100 /* 4KB PWMSS1物理地址 */
    //ECAP1REG : o = 0x48302100 l = 0x00000080 /* 80B Ecap0物理地址 */

    //PWMSS2REG: o = 0x48304000 l = 0x00000100 /* 4KB PWMSS2物理地址 */
    //ECAP2REG : o = 0x48304100 l = 0x00000080 /* 80B Ecap0物理地址 */

    }


    SECTIONS
    {
    //.Eth_DescriptorFile : > ETH_DESCRIPTOR

    .GpioARegsFile : > GPIOAREG
    //.GpioBRegsFile : > GPIOBREG
    //.GpioCRegsFile : > GPIOCREG
    //.GpioDRegsFile : > GPIODREG

    //.CM_PER_RegsFile : > CM_PER_REG, PAGE = 1
    //.CM_WKUP_RegsFile : > CM_WKUP_REG
    //.CM_DPLL_RegsFile : > CM_DPLL_REG
    //.CM_MPU_RegsFile : > CM_MPU_REG
    //.CM_DEVICE_RegsFile : > CM_DEVICE_REG
    //.CM_RTC_RegsFile : > CM_RTC_REG
    //.CM_CEFUSE_RegsFile : > CM_CEFUSE_REG

    //.CTRL_MODULERegsFile : > CTRL_MODULEREG


    //.PRM_PER_RegsFile : > PRM_PER_REG
    //.PRM_CEFUSE_RegsFile : > PRM_CEFUSE_REG
    //.INTCRegsFile : > INTCREG
    //.PWMSS0RegsFile > PWMSS0REG
    //.ECap0RegsFile > ECAP0REG

    //.PWMSS1RegsFile > PWMSS1REG
    //.ECap1RegsFile > ECAP1REG

    //.PWMSS2RegsFile > PWMSS2REG
    //.ECap2RegsFile > ECAP2REG

    //.MDIORegsFile : > MDIO_REG
    //.TIMER2_RegsFile : > TIMER2_REG
    }
    用双斜杠屏蔽掉的地址分配都只能是指针形式,都在另一个C文件里面单独定义,如下:
    /*
    * AM335x_GPIODefs.c
    *
    * Created on: 2021年3月13日
    * Author: 二哥
    */
    #include "AM335x_Device.h"

    #pragma DATA_SECTION(GpioARegs,".GpioARegsFile"); //这里A口可以使用位域结构体,所以在CMD里面分配地址
    volatile struct hw_GPIORegs GpioARegs;

    //#pragma DATA_SECTION(GpioBRegs,".GpioBRegsFile");
    //volatile struct hw_GPIORegs GpioBRegs;
    volatile struct hw_GPIORegs *GpioBRegs = (volatile struct hw_GPIORegs *)0x4804C000;
    //volatile struct hw_GPIORegs GpioBRegs __attribute__((location(0x4804C000)));

    //#pragma DATA_SECTION(GpioCRegs,".GpioCRegsFile");
    //volatile struct hw_GPIORegs GpioCRegs __attribute__((location(0x481AC000)));
    volatile struct hw_GPIORegs *GpioCRegs = (volatile struct hw_GPIORegs *)0x481AC000;

    //#pragma DATA_SECTION(GpioDRegs,".GpioDRegsFile");
    //volatile struct hw_GPIORegs GpioDRegs;
    volatile struct hw_GPIORegs *GpioDRegs = (volatile struct hw_GPIORegs *)0x481AE000;
  • 以上,不管是A口的直接位域结构体访问寄存器,还是指针访问寄存器,在调试模式的运行期间都不能在寄存器窗口观察,必须暂停下来才能观察到。上面文件是我看了3359技术参考手册后自己独立完成的。
  • #define LED1 GpioBRegs->OUT_DATA.bit.GPIO4
    #define LED2 GpioBRegs->OUT_DATA.bit.GPIO5
    #define LED3 GpioBRegs->OUT_DATA.bit.GPIO7

    #define LED5 GpioARegs.OUT_DATA.bit.GPIO20
    #define LED6 GpioARegs.OUT_DATA.bit.GPIO19


    以上位定义都能正常工作,相关LED完全受控制
  • 我的理解是,指针是间接访问,在CMD文件里面分配地址的位域结构体那种是直接访问,这就是两种访问的唯一区别,但直接访问导致跑飞,感觉是MMU没有开启的缘故,我也只是猜测
  • 其它外设的寄存器访问也是完全相同的情况,包括PRCM,电源,复位,时钟,这些系统基本的控制寄存器