chyyuu 发表于 2004-1-10 00:47:32

问题和回答 ",关于skyeye 下的 ucOSII 移植

求助,关于skyeye 下的 ucOSII 移植
我下载了skyeye下的ucOSII,移植到TI 的ARM7上,可是对于OS_ENTER_CRITICAL() 和 OS_EXIT_CRITICAL()的实现却有一点疑问。
       这两个宏实现在skyeye中如下:

_ARMDisableInt:               
MRS      r0, cpsr
STMFD      sp!, {r0}               ; push current PSR
ORR      r0, r0, #0x80
MSR      cpsr, r0               ; disable IRQ Int s
MOV      pc, lr
      
_ARMEnableInt:      
LDMFD      sp!, {r0}                ; pop current PSR
MSR      cpsr_c, r0               ; restore original cpsr      
MSR      cpsr, r0               ; restore original cpsr               
MOV      pc, lr

基本上是这样的,OS_ENTER_CRITICAL ( disable IRQ) 将CPSR
入栈,SP --; OS_EXIT_CRITICAL ( enable IRQ) 将 CPSR
弹出栈,SP ++;可是在这两个中间,如果有用到局部变量,而C中
的局部变量多半是以SP为base索引的,就会出问题。

   或者是我什么地方错了? 请多多指教 。。
---------------------------------------------------------------------------
liming's answer
hi, 你好!
    首先,这确实是个好问题,当时我也没有考虑到,现在提出来了,
虽然写论文很忙,但还是仔细想了一下。
    我查看了一下源码,并且对比了 ADS 的 armcc 和 GNU 的
arm-elf-gcc 编译后的汇编代码,发现所有用到局部变量的地方都不是
使用 sp 来标识的,而大多是用的 r1,r2 之类的通用寄存器,没有
用 sp+offset 来定位,所以没有影响局部变量的值。
    但这种做法,在局部变量很少的情况下是可以的,但是如果很多呢?
我也比较疑惑,于是我做了个实验如下,:

这里我开了一个局部数组,看编译器怎么办?

void Task2(void * pParam)
{
int a;
y=1000;
    while (1)
      {      
                a = 1234;
                a = 4321;
                a = a + a;
                y --;
                which = 1;
                Sleep(6);
      }
}

下面的是编译后得到的汇编码,可以着重看我红色标出来的部分 ——

010014b0 <Task2>:
10014b0:       e1a0c00d      mov   r12, sp
10014b4:       e92dd9f0      stmdb   sp!, {r4, r5, r6, r7, r8, r11, r12, lr, pc}
10014b8:       e24cb004      sub   r11, r12, #4    ; 0x4

void Task2(void * pParam)
{
int a;
y=1000;
    while (1)
10014bc:       e3a05e4d      mov   r5, #1232       ; 0x4d0
10014c0:       e2855002      add   r5, r5, #2      ; 0x2
10014c4:       e3a04d43      mov   r4, #4288       ; 0x10c0
10014c8:       e2844021      add   r4, r4, #33   ; 0x21
10014cc:       e0847005      add   r7, r4, r5
10014d0:       e59f203c      ldr   r2,    ; 1001514 <Task2+0x64>
10014d4:       e3a03ffa      mov   r3, #1000       ; 0x3e8
10014d8:       e59f8038      ldr   r8,    ; 1001518 <Task2+0x68>
10014dc:       e1a06002      mov   r6, r2
10014e0:       e24dde19      sub   sp, sp, #400    ; 0x190
10014e4:       e5823000      str   r3,
      {      
                a = 1234;
10014e8:       e50b5028      str   r5,
                a = 4321;
10014ec:       e50b402c      str   r4,
                a = a + a;
10014f0:       e50b7030      str   r7,
                y --;
                which = 1;
10014f4:       e3a03001      mov   r3, #1; 0x1
10014f8:       e5962000      ldr   r2,
                Sleep(6);
10014fc:       e3a00006      mov   r0, #6; 0x6
1001500:       e5883000      str   r3,
1001504:       e2422001      sub   r2, r2, #1      ; 0x1
1001508:       e5862000      str   r2,
100150c:       eb000003      bl      1001520 <Sleep>
      }
1001510:       eafffff4      b       10014e8 <Task2+0x38>
1001514:       01006060      tsteq   r0, r0, rrx
1001518:       01006064      tsteq   r0, r4, rrx
}
100151c:       e91ba9f0      ldmdb   r11, {r4, r5, r6, r7, r8, r11, sp, pc}


    相信你已经知道为什么没有影响局部变量的值了。
---------------------------------------------------------------
richard hoo的回复:

      多谢,回复很快:-)
      看来ADS是先保存了SP的值到寄存器中,然后一直用这个寄存器
来做基值寻址。
      我目前在TI DSC25上做开发,用的是TI 的CCS,我仔细看了
汇编和反汇编的代码,它都是直接用SP来寻址的,所以这样写
就有问题。
      目前我考虑有两个办法,一个是强行disable IRQ/enable IRQ,
不保存当前的CPSR值; 另外一个办法就是用另外的一个不用的
STACK SP,比如ABT exception 一直不用,用它来push/pop.
不过这样每次disable/enables的时候就要切换工作模式,
比较耗时间。

hawkzone 发表于 2004-1-10 12:27:32

我正在看ucos2,邵贝贝翻译的2001版本
觉得ucos是基于x86讲的,先看懂x86,再移植到其他系统上

各位大侠:
1,是不是要全部仔细从前往后看,能不能跳着看一些,先上手啊?
2,我要往DSP或者ARM上移植的话,学习哪些内容会比较快一些呢?
3,请搞这个的大侠写点东西吧,让我们快速入门啊,呵呵

也可email联系我,谢谢!!

chyyuu 发表于 2004-1-10 23:55:56

ucosii的书中是基于x86讲的.
不过没有关系.
1 可以跳着看,特别是与具体硬件无关的ucosi部分
2 ARM相关的硬件知识需要有.
3 基于ARM的书籍很多,你可以参考一下.
然后看看与基于skyeye仿真的at91开发板有关的相关文档(可到166.111.68.183/pub/embed 处下载),再用skyeye运行调试一下ucosii 就会有比较快的感受.
页: [1]
查看完整版本: 问题和回答 ",关于skyeye 下的 ucOSII 移植