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.

OMAP138新建工程怎么让ARM进入特权模式

Other Parts Discussed in Thread: OMAP-L138

OMAP138新建工程怎么让ARM进入特权模式啊......不然好多资源操作不了啊,比如管脚复用寄存器

  • 下面的网站上有参考代码。
    http://processors.wiki.ti.com/index.php/OMAP-L138_Bootloader#ARM_Supervisor_vs_User_mode

     

  • 好的,谢谢!

    已经可以进入特权模式了,原来是缺少了"boot.asm"文件。

    加上这个文件以后不用调用“CPUSwitchToPrivilegedMode()”,默认就进入特权模式了。

  • 好的,谢谢,已经可以了。

    ARM Supervisor vs User mode

    By default the TI Code Generation tools for the ARM put the ARM in user mode. This means that certain SYSCFG registers, such as those that control the pinmuxing, cannot be modified by the code. To keep the ARM in supervisor mode, a modified boot.asm file should be included in your ARM project. This file can be found in the following LED blink example project: [3]. In CCS3.3, the "Resolve Symbols to First Library (-priority)" box should be checked in the project linker options to avoid linking errors.

    因为缺少了“boot.asm”这个文件,把这个文件添加进来就可以了。

    其实可以不用调用CPUSwitchToPrivilegedMode()函数进入了,一调用这个函数就飞了。感谢技术支持......

  • 你好,我还行问个问题,就是那些有参考意义的wiki页面是怎么找到的?你给的这个链接我在官网找半天也没发现链接在哪里?

  • wiki网站上有很多有用的资料,在wiki主页面上搜关键字。
    http://processors.wiki.ti.com/index.php/Main_Page

     

  • OK,知道怎么找了。谢谢你!

  • #1. 首先了解一下ARM进入supervisor mode的方法是通过SWI指令. 

    #2. 参考一下starterware里的代码:

    函数:

    cpu.c:

    void CPUSwitchToPrivilegedMode(void)
    {
    asm(" SWI #458752");   }

    上面函数的调用会进入SWIHandler, 这里只是做了一个参数的简单比较,当然用户也可以修改这个参数用来实现不同值的传递,达到判断不同条件,从而做不同处理的目的, mode切换就是在下面两条语句实现的。

    exceptionhandler.asm: 

    SWIHandler:
    STMFD r13!, {r0-r1, r14} ; Save context in SVC stack
    LDR r0, [r14, #-4] ; R0 points to SWI instruction
    BIC r0, r0, #MASK_SWI_NUM ; Get the SWI number
    CMP r0, #458752
    MRSEQ r1, spsr ; Copy SPSR
    ORREQ r1, r1, #0x1F ; Change the mode to System
    MSREQ spsr_cf, r1 ; Restore SPSR
    LDMFD r13!, {r0-r1, pc}^ ; Restore registers from IRQ stack

    异常向量表的排放在在startup.c里实现的。

    static unsigned int const vecTbl[14]=
    {
    0xE59FF018,
    0xE59FF018,
    0xE59FF018,
    0xE59FF018,
    0xE59FF014,
    0xE24FF008,
    0xE59FF010,
    0xE59FF010,
    (unsigned int)Entry,
    (unsigned int)UndefInstHandler,
    (unsigned int)SWIHandler,
    (unsigned int)AbortHandler,
    (unsigned int)IRQHandler,
    (unsigned int)FIQHandler
    };

    unsigned int start_boot(void)
    {

    /* Enable write-protection for registers of SYSCFG module. */
    SysCfgRegistersLock();

    /* Disable write-protection for registers of SYSCFG module. */
    SysCfgRegistersUnlock();

    PSCModuleControl(SOC_PSC_1_REGS, HW_PSC_UART2, 0, PSC_MDCTL_NEXT_ENABLE);

    PSCModuleControl(SOC_PSC_0_REGS, HW_PSC_AINTC, 0, PSC_MDCTL_NEXT_ENABLE);
    /* Initialize the vector table with opcodes */
    CopyVectorTable();

    /* Calling the main */
    main();

    while(1);
    }

    static void CopyVectorTable(void)

    {
    unsigned int *dest = (unsigned int *)0xFFFF0000;
    unsigned int *src = (unsigned int *)vecTbl;
    unsigned int count;

    for(count = 0; count < sizeof(vecTbl)/sizeof(vecTbl[0]); count++)
    {
    dest[count] = src[count];
    }
    }

    对于ARM,这个异常向量表的地址有两种模式,要么放地址0,要么放地址0xFFFF0000. 在L138的ARM上,为0xFFFF0000. 

    程序中的中断等,将都进入这个向量表再跳转.

  • 感谢你的回答,说的很详细。

    http://processors.wiki.ti.com/index.php/StarterWare_01.10.01.01_User_Guide,里面也说

    to privileged mode usingCPUSwitchToPrivilegedMode() at any time

    所以一开始我是在main函数的地方调用“CPUSwitchToPrivilegedMode”。可是调用这个切换到特权模式的时候就会跑飞,直到Shine Zhang告诉我需要Boot.asm就可以了。然后就发现不用调用这个函数就可以默认进入特权模式了。

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    我估计是不是我的工程哪里配置有问题啊,我把cpu.c、startup.c都添加进了工程,代码如下:

    void main(void)

    {
    //ptest = (unsigned int *)0xC0000010;
    //*ptest = 0xAA55;

    CPUSwitchToPrivilegedMode();

    PSCModuleControl(SOC_PSC_1_REGS,HW_PSC_GPIO,PSC_POWERDOMAIN_ALWAYS_ON,PSC_MDCTL_NEXT_ENABLE);

    ......

    程序就跑飞了????这种方式出现的这个问题现在也不知道为啥。您有啥高见?


  • exceptionhandler.asm  文件也是加进来的

  • 怎么让程序运行到  startup.c 里面的 start_boot(),需要在cmd文件里面怎么设置呢?

  • CCS给出的提示为:

    No source available for "0xfffd45e0" 

    右侧对应的汇编

    fffd45e0:  EAFFFFFD  B 0xFFFD45DC
    fffd45e4:  E92D4010  STMFD R13!, {R4, R14}
    fffd45e8:  E59F4B74   LDR R4, 0xFFFD5164
    fffd45ec:  E3A020A0    MOV R2, #0xA0
    fffd45f0:   E3A01000    MOV R1, #0x0
    fffd45f4:   E1A00004    MOV R0, R4
    fffd45f8:   EB00117B   BL 0xFFFD8BEC
    fffd45fc:   E59FCB64   LDR R12, 0xFFFD5168
    fffd4600:  E584C07C  STR R12, [R4, #0x7C]
    fffd4604:  EB00001A   BL 0xFFFD4674
    fffd4608:  E1D4C0B2  LDRH R12, [R4, #0x2]

  • weihua li 说:
    所以一开始我是在main函数的地方调用“CPUSwitchToPrivilegedMode”。可是调用这个切换到特权模式的时候就会跑飞,直到Shine Zhang告诉我需要Boot.asm就可以了。然后就发现不用调用这个函数就可以默认进入特权模式了。

    原因是因为原始的boot.asm里初始化时,配置成了user模式,而你新参考的配置的是supervisor模式(其实不配置,默认就是supervisor mode), 代码对比如下:

    原始的,即CCS安装目录下C:\ti\ccsv6\tools\compiler\arm_5.0.11\lib\src\boot.asm

    _c_int00: .asmfunc

    ;***************************************************************
    ;* FUNCTION DEF: _c_int00
    ;***************************************************************
    _c_int00: .asmfunc

    .if __TI_NEON_SUPPORT__ | __TI_VFP_SUPPORT__
    ;*------------------------------------------------------
    ;* SETUP PRIVILEGED AND USER MODE ACCESS TO COPROCESSORS
    ;* 10 AND 11, REQUIRED TO ENABLE NEON/VFP
    ;* COPROCESSOR ACCESS CONTROL REG
    ;* BITS [23:22] - CP11, [21:20] - CP10
    ;* SET TO 0b11 TO ENABLE USER AND PRIV MODE ACCESS
    ;*------------------------------------------------------
    MRC p15,#0x0,r0,c1,c0,#2
    MOV r3,#0xf00000
    ORR r0,r0,r3
    MCR p15,#0x0,r0,c1,c0,#2

    ;*------------------------------------------------------
    ; SET THE EN BIT, FPEXC[30] TO ENABLE NEON AND VFP
    ;*------------------------------------------------------
    MOV r0,#0x40000000
    FMXR FPEXC,r0
    .endif

    ;*------------------------------------------------------
    ;* SET TO USER MODE
    ;*------------------------------------------------------
    MRS r0, cpsr
    BIC r0, r0, #0x1F ; CLEAR MODES
    ORR r0, r0, #0x10 ; SET USER MODE
    MSR cpsr_cf, r0

    你新参考的boot.asm也是基于上面这个文件改的,只将0x10改成了0x13(不过注释没改):

    ;* SET TO USER MODE
    ;*------------------------------------------------------
    MRS r0, cpsr
    BIC r0, r0, #0x1F ; CLEAR MODES
    ORR r0, r0, #0x13 ; SET USER MODE
    MSR cpsr_cf, r0

    因为你的新工程序默认的入口entry_point是_c_int00(这个函数本身是在rts库里的,只是编译器在工程里找符号时是先从源文件里找,再到库里找,所以你把boot.asm加进来后,调用的_c_int00是上面修改后的了),所以程序下载后就从上面执行下来,初始为对应的mode了。其实上面把这段代码去掉,效果是一样的,因为默认为supervisor mode,还有一个常识是如果当前是user mode,是不能通过这种直接修改cpsr从user mode改到supervisor模式的。这也是为什么有swi存在的原因。从user mode,必需先进入swi才能修改cpsr。

    第二问题是为什么跑飞了,原因是你的工程序里没有初始化异常向量表,就比如工程中没有初始化中断向量表,又把中断使能了,而且来了个中断,自然就跑飞了。

    有兴趣可以继续看一下boot.asm和auto_init.asm,RTS库从这里就跳入用户的main了,没有进一步的初始化。这对于简单的C工程可以正常运行,因为需要的C环境初始化都做了,但是对于系统来说,还没有做exception vector的初始化,所以系统不能有中断。

  • weihua li 说:
    怎么让程序运行到  startup.c 里面的 start_boot(),需要在cmd文件里面怎么设置呢?

    对比一个startware里的工程,比如拿timerCounter.cmd:

    -stack 0x8000 /* SOFTWARE STACK SIZE */
    -heap 0x2000 /* HEAP AREA SIZE */
    -e Entry

    /* SPECIFY THE SYSTEM MEMORY MAP */

    上面指定了入口是Entry,这个是init.asm里的, 这里初始化各个模式下的堆栈,最后是system mode的,所以你看到的是为什么starterware工程起来后就可以改任意寄存器。

    ; Set up the Stack for USer/System mode
    ;
    MSR cpsr_c, #MODE_SYS|I_F_BIT ; change to system mode
    MOV sp,r0 ; write the stack pointer

    ; Set up the Stack for USer/System mode
    ;
    MSR cpsr_c, #MODE_SYS|I_F_BIT ; change to system mode
    MOV sp,r0 ; write the stack pointer

    ;
    ; Clear the BSS section here
    ;
    Clear_Bss_Section:

    LDR r0, _bss_start ; Start address of BSS
    LDR r1, _bss_end ; End address of BSS
    SUB r1,r1,#4
    MOV r2, #0
    Loop:
    STR r2, [r0], #4 ; Clear one word in BSS
    CMP r0, r1
    BLE Loop ; Clear till BSS end

    BL __TI_auto_init ; Call TI auto init

    ;
    ; Enter the start_boot function. The execution still happens in system mode
    ;
    LDR r10, _start_boot ; Get the address of start_boot
    MOV lr,pc ; Dummy return
    BX r10 ; Branch to start_boot
    SUB pc, pc, #0x08 ; looping

    所以上面你把这几个文件加到了你的工程序,但是没有把入口地址改成entry,所以没有执行上面步骤,上面代码最后跳到start_boot,做了向量初始化后才真正进入用户的main.

    unsigned int start_boot(void)
    {

    /* Enable write-protection for registers of SYSCFG module. */
    SysCfgRegistersLock();

    /* Disable write-protection for registers of SYSCFG module. */
    SysCfgRegistersUnlock();

    PSCModuleControl(SOC_PSC_1_REGS, HW_PSC_UART2, 0, PSC_MDCTL_NEXT_ENABLE);

    PSCModuleControl(SOC_PSC_0_REGS, HW_PSC_AINTC, 0, PSC_MDCTL_NEXT_ENABLE);
    /* Initialize the vector table with opcodes */
    CopyVectorTable();

    /* Calling the main */
    main();

    while(1);
    }

  • (其实不配置,默认就是supervisor mode), 代码对比如下:

    原始的,即CCS安装目录下C:\ti\ccsv6\tools\compiler\arm_5.0.11\lib\src\boot.asm

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    我使用的是ccsv5.5,在你说的路径下面没有看到有boot.asm呀,

    路径如下  C:\ti\ccsv5\tools\compiler\arm_5.1.1\lib,没发现这个文件。

    我一开始用过ccs6.0,只是用的早发现仿真不行,后来跟咱们技术支持沟通退回到5.5了。

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    我参考过你说的那个timerCounter.cmd,试着将 -e Entry加上,但总是报错

    >> Compilation failure
    warning #10063-D: entry-point symbol other than "_c_int00" specified: "Entry"
    error #10010: errors encountered during linking; "omapl138_arm.out" not built
    gmake: *** [omapl138_arm.out] Error 1
    gmake: Target `all' not remade because of errors.

    **** Build Finished ****

    另外,我不知道要加rts库,我加上这个库再试试吧

  • C:\ti\ccsv6\tools\compiler\arm_5.0.11\lib\src\boot.asm VS.  C:\ti\ccsv5\tools\compiler\arm_5.1.1\lib

    rts库默认就加上了。

    >> Compilation failure
    warning #10063-D: entry-point symbol other than "_c_int00" specified: "Entry" ----这只是提醒。
    error #10010: errors encountered during linking; "omapl138_arm.out" not built ----- 要查这个错误怎么来的。

  • 我这里 lib路径下面没有src文件夹啊,有个rtssrc.zip,我解压看了里面倒是有个boot.asm。难道这是CCS5和CCS6的区别么。

    我先把环境换到 6.1.2 ,弄成跟你的一样,有6.1.2的破解文件么?

  • 就是这个文件,自已解开也一样,用CCS5也可以,当前我们的目的是了解C工程运行的过程,知道为什么自己新建的工程为什么不是privilege mode,而换了个boot.asm就可以的原因就好了。

  • 啊,上午已经把ccsv5给卸载了,安装了6.1.1。

    新建了一个工程,在不指定 -e  Entry 的情况下,挂上仿真器应该就是还是在 User mode 模式下......

    另外:我发现6.1.1里面的boot.asm也不是你说的路径哦,C:\ti\ccsv6\tools\compiler\ti-cgt-arm_5.2.5\lib\src   VS  C:\ti\ccsv6\tools\compiler\arm_5.0.11\lib\src

  • 用的都是官方的文件,怎么就是不行呢?

    没想到被OMAP的一个最小工程给难倒了......

  • 那只是编译器版本号,不同版本的编译器名字自然不同,(不要说你也是装的CCS6,我说的是编译器版本)~~~

    能找到就好了~~~~

    你还可以对照不跑程序时CPSR的模式是10011

  • 上附件,帮我看看吧......

  • 恩,你说的这些我也明白。现在就是挂上仿真器进入main函数,不是 10011,。

    另外 带上-e Entry就会报错,上传了一个附件,在等版主审核,估计明天才能看到附件。

    注:前年搞过半年的OMAPL138的底层驱动,那会还是用的CCS3.3。现在全部在新的环境上,配合新的软件方案进行改版。没想到的是没有难倒在后续的软件算法上,被TI的最小工程载了大跟头。也用过好几家的处理器,目前TI的这个OMAP是最让我头疼的。

  • #1. 你上面提供的编译出错信息,完整的应该是下面所示,而你把关键的部分没提供出来,这些信息告知这些函数找不到,这里在starterware库里的,这里鉴于简单验证而已经,那么就在startup.c里先注释掉其调用。你也可以把库加进来.

    <Linking>

    undefined first referenced
    symbol in file
    --------- ----------------
    PSCModuleControl ./startup.obj
    SysCfgRegistersLock ./startup.obj
    SysCfgRegistersUnlock ./startup.obj

    error #10234-D: unresolved symbols remain
    warning #10063-D: entry-point symbol other than "_c_int00" specified: "Entry"
    error #10010: errors encountered during linking; "arm9_previlege_Mode.out" not built

    >> Compilation failure
    gmake: *** [arm9_previlege_Mode.out] Error 1
    gmake: Target `all' not remade because of errors.

    **** Build Finished ****

    #2. 还应该有头文件找不到的出错,把相应的头文件路径加进来。

    #3. cmd里也可做简单修改,如果你把system_config.lib加到了工程里,就不用改了。

    .init : {
    /* system_config.lib<init.obj> (.text) */
    } load > 0xC1080000

    然后编译结果如下,成功生成.out:

    "./startup.obj" "../timerCounter.cmd" -l"libc.a"
    <Linking>
    warning #10063-D: entry-point symbol other than "_c_int00" specified: "Entry"
    'Finished building target: arm9_previlege_Mode.out'
    ' '

    **** Build Finished ****

    运行结果如下:

  • 按照上面我说的步骤建的工程,可以在任意模式之间自由切换了:

    #include "stdio.h"
    int main(void) {

    printf("\nenter swi...\n");
    CPUSwitchToPrivilegedMode();

    printf("\nback from swi...\n");

    CPUSwitchToUserMode();

    printf("\n entered user mode...\n");

    return 0;
    }

  • 恩,可以了。现在 ARM 和 DSP 都可以挂着仿真器跑起来了。各自运行了一个点灯的小代码。ARM端运行在DDR,DSP端运行在共享内存里面。仿真器运行没有问题,烧写进spi flash就起不来了。有时间给指导指导。

    ccswork.rar