신제품을 개발중인데, GPIO 의 3개 핀을 HW Divice Version를 구별하는 용도로 사용하였습니다.
bootloader 실행하자 마자 nand 및 gpio, pmic 등을 초기화 하는 함수로 뛰게 했는데,
이 함수 첫부분에서 바로 GPIO 3개핀을 읽어 HW Device를 구별하게 했습니다.
근데 이 함수가 bootloader 실행하자 마자 한번 호출되고, start_armboot 가 실행된 후에
다시 한번 불러지게 되더군요 (전에 작업한 사람이 왜 그랬는지 하여튼 2번 호출됩니다)
문제는 첫번째 불러질 때는 정상적으로 HW Device Version을 읽어내는데, 두번째 불러질
때는 정말 황당한 일이 벌어집니다.
원래대로라면 첫번 불러질 때나 두번째 불러질 때나 값이 같다면 if 문안에서도 그 값에
따라 분기하는 곳도 같아야 겠죠...그런데 값은 한가지로 나오는데 황당하게 if 문 안에서
분기되는 위치가 틀립니다.
간략하게 소스에서 주석을 봐주세요..
==============================================================================
* gpio a 4,5,6 모두 open 상태로 high로 검출되어 야 함. 그래서 그런지 rGPADATA 값은 항상 0xfffd 로 검출..
rGPADATA : 0번 비트부터 gpioa 0,1,2,3...15 까지 .
그리고 rINFORM7 은 값을 저장하기 위한 register ...
(chip 에서 값을 저장하는 용도로 쓰라고 만들어 놓은게 있습니다)
rGPAMCON = (rGPAMCON & ~(GP04_MASK|GP05_MASK|GP06_MASK)) <<<< 일단 인풋 설정
| (GP04_INPUT|GP05_INPUT|GP06_INPUT);
rGPAPUD = (rGPAPUD & ~(GP04_MASK|GP05_MASK|GP06_MASK)) <<<< pull up 으로 처리하고
| (GP04_PULLUP|GP05_PULLUP|GP06_PULLUP);
if ( (rGPADATA & (1<<6))== (1<<6) ) <<<< 첫번 호출될 때는 이곳에서 정상적으로 if 문을 인식해 바로 아래로 분기
{ <<<< rGPADATA 값이 0xfffd 이므로 정상임
rINFORM7 = HW_G3_BOARD;
}
else if ( (rGPADATA & (1<<6))== 0 )
{
rINFORM7 = HW_G4_BOARD;
else <<<< 문제의 두번째 호출.. rGPADATA 값이 0xfffd 임에도 불구하고 바로 이곳으로
{ <<<< 분기함. 말이 안되는 것이 비트셋팅은 1 or 0 인데 이곳으로 분기하는 것이 특이함
//에러...절대 이곳으로 분기 할 수 없음.
}
rGPAPUD = (rGPAPUD & ~(GP04_MASK|GP05_MASK|GP06_MASK)) <<<<< 위의 처리가 끝나고 pull down 처리
| (GP04_PULLDOWN|GP05_PULLDOWN|GP06_PULLDOWN);
==============================================================================
두번째 함수 호출될때 비트셋팅이 1 or 0 둘중 하나로 가야하는데 엉뚱한 곳으로 뛰어 버리는게 문제입니다.
정상적이면 high 로 인식하여 if 문 첫번째 조건에 걸려야 되느데 엉뚱하게도 else 로 뛰네요.
비트 셋팅이 1 or 0 인데 양자컴퓨터도 아니고 엉한데로 뛰니..쩝~~..
이거 miss align 문제는 아닌가 생각도 되지만 역어셈을 해봐야 될 거 같기도 하네요..
혹시 왜 이런지 아니면 저와 비슷한 경험이있으신 분은 답변좀 적어주시면 감사하겠습니다.
그리고 역어셈 할려면 어떻게 해야 하는지 간략히 알려주심 더 감사하겠습니다...
ps : 그리고 또 특이한게 위의 gpio 확인하는 함수가 딱 1번만 호출되면 정상적으로 동작을 합니다.
댓글 6
-
김영일
2010.12.06 20:01
-
김영일
2010.12.07 15:03
에구...방금 제가 다시 측정했는데 딜레이를 안주면 아예 레벨이 올라가지도 안는군요
pull up -> data read -> pull down 하는 과정이 무척 빠르게 진행 되나 봅니다.
그리고 for 문으로 delay를 줘야 , 그제서 high로 움직이네요...
^^
-
김영일
2010.12.07 13:57
저희쪽 하드웨어 하는 사람과 이야기 한건데요.일단 .mmu 설정전과 후의 차이는 아니고요..
순전히 하드웨어의 전기적 특성때문에 발생한 문제라고 사료되는데,. 초기 부팅시 전원이 공급되기 시작할 때,
GPIO에 걸리는 전압레벨이 0V 냐 아니면 어정쩡한 플로팅 상태에서 시작하냐의 차이죠...
플로팅 상태에서 시작하면 완전히 high로 올라가는 시간이 덜걸릴테고요, 완전히 low에서 시작하면
high로 되기 까지 시간이 좀 더 걸리죠..
첫번째 잘동작한 것들은 대부분 플로팅 상태에서 올라 갔기 때문에 high로 인식되는 시간이 짧았고, 두번째 읽은때는
완전히 0v 로 떨어뜨린 다음에 시작하니까 high가 되기 전까지 시간이 좀 더 걸리죠.
해당 gpio가 open 상태이고 소프트웨어로 pull up / pull down을 걸기 때문에 pull up / pull down 걸기 전 까지는 GPIO 선이 어떤
상태인지 예측하기가 힘든 상태죠...
정말 예외적인 상황인데, 확실히 하기 위해 딜레이를 약간 주는 것이 가장 확실하죠..
처음 전원 들어오자 마자 전압레벨이 논리적으로 안정상태까지 가는데 걸리는 시간이 어느정도냐에 따라 정상 또는 비정상으로
동작할 수 있는 문제죠...
그리고 약간 애매모하기 한데 참고로 칩의 내부 레지스터에 gpio 값을 저장하도록 했을 때는 정상동작했었는데, 이것은 아마도
내부 레지스터에 저장하는 시간이 결국 메모리를 읽어들이는 시간이다 보니 메모리 읽을 때의 시간에서 자연스런 delay가 걸리지 않았나 싶습니다. 그리고 값을 지역변수로 해서 읽었을 때는 문제가 되었는데 지역변수가 stack에 잡힌게 아니라 어쩌면 register 변수로 잡히지 않았나 싶습니다. 그렇게 되면 메모리에서 읽을 때 보다 속도가 엄청 빠를 테니 gpio 읽을 때도 속도가 너무 빨라 안정화 된 level 로 올라가기 전에 읽을 수도 있겠죠..그렇게 되면 값이 이상할 테고요..
실은 저도 이런 경우는 첨이라 참 애매모했었죠...
대부분 개발하면서 접압레벨이 안정화 된 상태에서 이래저래 초기화 하고 시작했는데, 지금같이 시작과 동시에 데이타를 읽고 하니 문제가 발생하네요.
jtag로 찍어도 값을 나오는데, 단순히 jtag에 만 의존하면 논리적인 생각만 하게 되어, 혹시 스텍이 깨지는 현상인가 생각도 했었죠..
저도 들은 이야기지만 칩이 돌아가고 어셈에서 C 함수로 bl 한다는 것이 기본적인 스택이 없이는 불가는 하기 때문에 칩자체에서 기본 스택을 지원하거나 또는 어디선가 기본적인 스택을 정의 했을 거라 들은 적이 있어요..(혹시 lds를 말하는 것인지...저도 좀...ㅡ,.ㅡ)
정확한 건지는 모르지만요..
이백님 답글 감사합니다..
-
맥주
2010.12.07 08:16
딜레이, volatile 로 예상은 했었는데, 첫번째는 잘 동작한다고 해서, if ~ else 문만 뚫어져라 쳐다 보고 있어네요...^^
아마도 mmu 설정 전과 후의 차이로 인한 것인지?
역어셈.. 오브젝트 덤프 말씀하시는 건가요? 해당 object 파일 혹은 커널 및 부트로더 이미지로 해보십시요.
arm-linux-objdump -d xxx.o ( 또는 -D )
-
맥주
2010.12.07 16:07
네.. 근데 rGPADATA 는 언제 읽습니까?
-
김영일
2010.12.07 16:18
nand 초기화 할때 읽습니다.
그리고 nand 를 초기화 하는 함수는 start.s 에서 bl 로 점프하죠...nand 초기화 함수가 bl 되는 위치는 start.s의 거의 첫부분입니다.
start.s 시작하자 마자 거의 바로 불러진다고 생각하시면 됩니다.
그리고 이런 저런 잡다구리 동작을 한다음에 stack_setup을 합니다.
.
확인해보니...pull up 처리후 delay 가 필요했네요...
그 delay 가 없어서 gpio 데이타 값이 읽혀지는 순간 잘못된 값으로 읽혀지네요..
delay 하나 추가 했더니 모든 문제가 싹 사라졌습니다...
생각해보니 이문제 처리 할 때 delay 문제는 아닐가 하고 for문을 100000 번 돌려 봤었는데...
변수선언에서 volatile 로 설정을 안해서 최적화되어 제대로 안 돌았내요...ㅠ.ㅠ....
풀업 후 특별히 delay가 필요 없을 거라 생각했거든요..
지금까지 gpio 셋팅 후 delay를 준적도 없었구요..근데 보드에 따라서 필요한 것도 있네요...
정말 새로운 것을 알았네요...알고나니 별거 아닌거 같긴 하지만..
내가 글올리고 내가 답달고 완전히 자폭이네요........ㅠ.ㅠ......
근데 역어셈은 어떻게 하죠???