在eboot下我写了如下代码:
volatile S3C2440A_IOPORT_REG *s2440IOP ;
s2440IOP = (S3C2440A_IOPORT_REG *)OALPAtoVA(S3C2440A_BASE_REG_PA_IOPORT, FALSE);
s2440IOP->GPFDAT &=0xFB;
mdelay(1);//如果我去掉这个延时,会导致s2440IOP->GPFDAT &=0xFB无效,加上延时才有效,也就是bit[2]不会等于零
s2440IOP->GPFDAT &=0xFE;
mdelay(1);//如果我去掉这个延时,会导致s2440IOP->GPFDAT &=0xFB无效,加上延时才有效
——这个问题我觉得很奇怪,对于地址,是uncache地址了,怎么2440速度这么慢呢!我觉得很不解,加个延时,啥都好了,不会2440会这么奇怪吧。
还有,如果这样写 s2440IOP->GPFDAT=(s2440IOP->GPFDAT&0xFB)&0xFE;又完全正确,真是神了。
还有
// Set GPF0 as output pin
s2440IOP->GPFCON &=~(1 < <1);
s2440IOP->GPFCON |=(1 < <0);
这样一个与与一个或搭配又完全正确,
1. 建议 LZ 将 compiler 出来的 assembly code 拿来看看, 来判断是否为 Optimization 的问题.
2.
-
C/C++ code
-
s2440IOP -> GPGCON &= ~ ( 3 < < 8 );Set LCD_PWREN as output s2440IOP -> GPGCON |= ( 1 < < 8 );
与
-
C/C++ code
-
s2440IOP -> GPGCON = (s2440IOP -> GPGCON & ~ ( 3 << 8 )) | ( 1 << 8 );
是不同的, 一个是两次 assign 的动作, 一个只有一次, 至於两次 assign 的动作中间的时间会发生什麽事, 那是 programmer 须注意的.
3. GPxDAT 的动作是 Read-Modify-Write, GPIO 若 driving 能力不强时, 则状态改变的 slope 可能过大, 故未作适当的 delay 再去读时就有可能会读到还未完全转态的状态.
Paul, Chao @ Techware
3. GPxDAT 的动作是 Read-Modify-Write, GPIO 若 driving 能力不强时, 则状态改变的 slope 可能过大, 故未作适当的 delay 再去读时就有可能会读到还未完全转态的状态.
想想解释的不清楚, 再多说一遍
s2440IOP->GPFDAT &=0xFB;
s2440IOP->GPFDAT &=0xFE;
LZ 要的是在 GPIO PF bit 2 先输出 0, 而後再将 bit0 输出 0, 若假设 GPF2 其转态速度为 1 mV/nS, 该指令执行时间为 500nS, 则 BIT2 输出 0 後最多再 500nS, 其就会再读一遍 GPFDAT, 则此时该电位为 3.3V - (1mV/nS * 500nS) = 3.3V - 0.5V = 2.8V, 故仍为 high.
所以 LZ 要解此问题, 应将其 code 改为
-
C/C++ code
-
DWORD dwGPFDAT = s2440IOP -> GPFDAT; dwGPFDAT &= ~ ( 1 << 2 ); s2440IOP -> GPFDAT = dwGPFDAT; dwGPFDAT &= ~ ( 1 << 0 ); s2440IOP -> GPFDAT = dwGPFDAT;
或是想办法将 GPF2 的转态速度增加为 10 mV/nS.
Paul, Chao @ Techware