이런게 있네... ㅡ_ㅡ;;;

83a8: e3a00006 mov r0, #6 ; 0x6
83ac: eaffffff b 83b0
83b0: e91ba800 ldmdb fp, {fp, sp, pc}

내가 C 소스 코드에서 무엇을 했는고 하니.. ㅡ_ㅡ;;;

return 6;

했더랬다. 저 어셈코드를 보면, 사실 mov r0, #6를 하고 ldmdb fp, {fp, sp, pc} 하면
될것을 return 을 했다고 폴짝 바로 아랫줄로 뛰어들고 있음을
"확인"
할 수 있다. 얼래.. ㅡ_ㅡ;;; 머지.. 저런식으로 코드를 생성하면 먼가 이득이 있나??
아님 내가 멀 잘못알고 있는건가??
설마 brench 명령으로 CPU Cache를 Flush하는 그런 말도안되는.. ㅡ_ㅡ;;;;;
내가 써놓고도 좀 말이 안되는거 같네. 만약 Flush를 위함이라하면 brench가 도배되
어야 정상이지......
O1을 줘서 약간의 Optimizing을 하면.. 아래와 같은 결과가 나온다.

8310: e3a00001 mov r0, #6 ; 0x6
8314: e91ba800 ldmdb fp, {fp, sp, pc}

컥.. brench가 온데간데 없다. @0@/~
이.. 이럴수가..





??
어.. 이상하다. ㅡ_ㅡ;;; 분명 Interrupt Vector는 Address 0x00000000 에서 시작한다. 그리고
이 영역은 현재 Flash가 차지하고 있다. 음... 그렇다면 Kernel에서 Boot Loader가 mapping
한 interrupt vector를 다시 Kernel에 맞게 remapping을 할 일이 분명 있을텐데......
어떻게 하는거지?? 설마 그냥 Flash에 Write를 해버리는건가?? ㅡ_ㅡ;;;
만약 그렇다면 kernel이 이상하게 되서 Vector를 복구하지 못하고 죽어버렸을때는, 문제가 심각
해 질것인데... 으음... 아니면 Remapping용으로 무언가 있는건가??
한번 찾아봐야겠다. @0@/~~
ldmia A, B 명령어는 A 어드레스에서 B에 있는 레지스터의 개수만큼 순차적으로 읽어 B에 저장하는 역할을 하는 명령어입니다. ^^;;;

lr 뒤에 붙은 "!"는 ldmia를 수행하고 난 뒤에 lr 레지스터의 값을 변경하여, 읽은 레지스터의 개수만큼 어드레스를 증가시키라는 뜻입니다.

B의 명령어가 위처럼 { r0 - r12, pc }라면 A 어드레스부터 4byte * 14개를 읽어서 순차적으로 r0->r12, pc에 저장한다음, lr 레지스터의 값은 "lr = lr + 14 * 4" 되는 것이지요.

그리고 lr 뒤에 붙은 "^" 표시는 ldmia의 대상 레지스터로 pc가 지정되어 있는 경우, SPSR 레지스터의 값이 CPSR 레지스터로 복사가 됩니다.

코드를 보면 대충 눈치채셨겠지만... 예전에 만들었던 OS의 태스크 스위칭 코드의 일부입니다. ^^;; 지금음 오래되서 기억도 안나는데... LDMIA로 검색해서 들어오시는 분들이 꽤 되서 내용을 보강합니다. ^^

그럼 좋은 하루 되세요 ;)

ps) http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0068b/BABEFCIB.html 로 가시면 ARM 명령어에 대한 자세한 설명을 보실 수 있습니다. ^^


아래는 원래 블로그에서 옮겨온 원본 글입니다. ^^;;;

===========================================================================================================
이 명령에서 제대로 실행이 안되고 뻣는 이유는... ㅡ_ㅡ;;;
도데체 무엇이란 말인가?? ㅡ_ㅡ;;;;;
분명 IRQ Mode이고 SPSR 레지스터도 잘 설정해 줬건만... 뻗어버리는 이유는.. ㅡ_ㅡ;;;;
으으.. ^를 빼면 그래도 스위칭하는데 별 문제가 없어보이는데....
것참 이상하네......
먼가 다른 이유가 있을것도 같은데, 쿨럭...;;;
어려워 어려워.. @0@/~~
오오~~ @0@/~~ 드뎌 좀 되기 시작했다.
이때까지 ldmia ...^ 해서 뻣던건, 실제로 뻗은게 아니라 OS Timer를 초기화 해주는걸 또
까먹어서 열심히 Interrupt 루틴이 불리고 있던 것이었다. @0@/~~
크아~~ 이런 낭패가.. ㅡ_ㅡ;;; 역시 머리가 나쁘면 손발이 고생하는거 같다.
머 그외에 ARM을 잘 몰라서 내멋대로 작성한 코드가 지멋대로 동작해서(당연한가?? ㅡ_ㅡ;;)
문제가 좀 됬었는데, 참고 문헌을 좀 뒤지고 해서 해결을 봤다.

지금은

내멋대로 작성한 코드가 내가 의도한대로 동작하고 있어서 다행이다. ㅋㅋㅋ
여튼 참... 하나라도 어디 쉽게 넘어가는게 없구만. 쩝쩝...
이제 C 코드로 만든 커널을 컴팔해서 뒤에 붙여넣은 다음 적절한 메모리 위치에 로드해서
사용하는 것만 고민하면 될것 같기도 하다.

음... 그나저나 역시 코드는 지저분하군... ㅡ_ㅡ;;;
잘 모르는 상태에서 마구 코딩한거니 어쩔 수 없는건가... 쿠.. 쿨럭..;;;;
Vector Table을 재구성한 뒤... 재실행한 결과....
Interrupt가 계속 튄다.. @0@/~
머지?? IRQ Interrupt Vector에 Led On/Off를 넣어놓으니 그것만 계속 켜졌다 꺼졌다 한다.
쿨럭..;;;
확실히 먼가 이상하다. 분명 Enable된 Vector는 OS Timer께 맞고 이놈의 Interrupt는 특정조건
을 만족해야 계속 튀게 되어있는데, 특정 조건이란게 순식간에 맞을 정도로 만만한게 아닌
것을....... ㅡ_ㅡ;;;;
혹시 내가 Interrupt Mask를 OS Timer가 아니라 다른걸 Enable한걸까??
당췌 잘 몰것네.. 쩝쩝...
OS Timer Interrupt가 죽어라고 발생하여, 해결방법을 찾던 중... 얼핏 ezboot 소스가 생각났
다. 음... 이놈도 필시 OS Timer를 이용하리라고 생각되어 소스를 뒤지던중...
내가 생각지도 못한 코드를 발견했는데... 그 코드는 이러하였다.

OSSR = OSMR0

이것이 무엇인고 하니, Status Register를 0으로 초기화 하는게 아니라 1로 초기화 하는 것이
었다.

SA-1110 Manual의 표에는 다음과 같이 나와있다.


bit 0, M0, 0 - OS Timer match Register 0 has not matched the OS Timer counter sind the last clear.
1 - OS Timer match Register 0 has matched the OS Timer counter.



이런 문장을 보면 누구라도 딱 일케 생각하지 않나??

"음.. 그래 그람 초기화는 0으로 해야지.. ㅡ_ㅡ;;;"

쿨럭..;;; 나만 그런가.. ㅡ_ㅡ;;;; 머 그래가지고 0으로 초기화 하니 줄창 Interrupt가 끝도없이
뜨더랬다.
1로 초기화 하는 코드를 보고 다시 SA-1110 Manual을 보니 다음과 같은 문장이 눈에 들어온다.

"and cleared by writing a one to the proper bit position. Writing zeros to this register has no effect."

컥.. ㅡㅁㅡ... 이말인 즉슨 걍 니가 멀하든간에 해당 비트를 무조건 1로 셋팅해라는 말이었던 것인가??
실제로 IRQ Interrupt가 발생했을 때, OSSR를 보면 해당 비트에 1이 설정되어있다. 그리고 다시
내가 1로 한번더 설정해 줘야 정상적인 Interval로 Interrupt가 발생된다.
쿠.. 쿨럭...;;;
나보고 어쩌라고.. ㅡㅁㅡ;;;;;
죽어도 모를뻔 했다. 쩝쩝.... 여튼 황당.... ㅡ_ㅡ;;;;
컥.. 어제 저녁에 삽질을 좀해서 OS Timer를 Enable 할 수가 있었다.
그런데 이상한것은 이놈이 interrupt가 발생하면 FIQ Handler가 불리는 것이었다.
분명 Interrupt Register의 Level Register는 모두 IRQ Interrupt로 설정된 상태였는데.... ㅡ_ㅡ;;
IRQ Handler를 부르게 할려고 혹시나 값을 바꾸면 될까해서 여러가지로 노력해 봤으나...
나온 결론은 두가지...

OS Timer는 IRQ Interrupt로 설정된게 확실하다.
지금 튄 Interrupt는 분명 IRQ Interrupt다. (비록 FIQ Handler가 불리긴 하지만.. ㅡ_ㅡ;;; )

오늘 혹시나 해서 Vector Table에 대한 문서를 보니... 컥.. 아래와 같았다.

0x00000000 Reset Handler
0x00000004 Undefined Instructions Handler
0x00000008 Software Interrupt Handler (SWI)
0x0000000C Prefetch Abort Handler
0x00000010 Data Abort Handler
0x00000018 IRQ Interrupt Handler
0x0000001C FIQ Interrupt Handler

음.. 머가 이상한지 처음엔 몰랐지만 Address를 보면 0x00000014 부분이 사용되지 않고 있었
던것이다. @0@/~~
이런.. 난 걍 문서에 나온 Vector Handler의 순서만보고 그냥 연번호로 할당했으니

0x00000014 IRQ Interrupt Handler
0x00000018 FIQ Interrupt Handler 가 될 수 밖에~~ @0@/~~

머여... 강조 같은걸 써서라도 좀 눈에 띄게 해놓던가.... ㅡ_ㅡ;;;;
삽질만 했네 그려.. 쿨럭..;;;;
쿨럭..;;; 어제 실컷 해보고 알았는데, SWI 명령으로 발생하는 interrupt는 Interrupt핀을
통해 발생하는 Interrupt와는 달랐다.
Vector Table에 위치하는 곳도 다르고, 무엇보다 중요한것은 SVC Mode라는 것이다.
음냥.. Reset을 했을때 Mode가 이미 SVC 이기땜시롱 SWI를 통해 Interrupt를 발생
시키면 그냥 brench 한것과 마찬가지 결과가 된다.

또 IRQ Interrupt와 SWI의 다른점은
SWI Interrupt는 lr에 들어가있는 Address가 SWI 바로 뒤의 명령을 가리키고
IRQ Interrupt는 lr에 들어가있는 Address가 다음에 수행할 명령의 다음 명령(??)

Thumb Mode가 아닌 경우 Next Instruction + 4
Thumb Mode인 경우 Next Instruction + 2
를 가지므로 lr에 4 or 2를 sub해 줘야 정상적으로 동작된다는 결론~~

으으.. ㅡ_ㅡ;;;
x86은 int 명령하고 IRQ Interrupt가 별차이가 없는데... 야들은 왜 일케 틀린지 모르겠
다.
여튼 SWI로 테스트를 해보겠다는 나의 생각은 무~ 로 돌아가고... ㅡ0ㅜ/~~
그냥 OS Timer를 이용해서 해야겠다.

쉽지 않구만... ㅡ_ㅡ;;;;;;;;
쿨럭..;;; 오늘 Memory Setting을 좀 해볼려고 문서를 딱 펴 들었는데...






다.

@0@/~~

머 연결방법하고 라인수에 따라서 Memory Register에 설정해주는 값이 틀리던데...
아아~~ 어찌 연결된줄 알고 한단 말이냐아아아아아~~ ㅡ0ㅠ...
그래서 걍 한참을 고민하다가...
기존의 부트로더 Memory Setting 코드를 그대로 Dump해서 테스트했다.
역시나 잘되는군.. ㅡ_ㅡ;;;
함 잡아볼려고 맘 먹었는데... 굉장히 복잡하네...
DSP의 MCBSP 설정만큼 황당한거 같다. 쿨럭..;;;
크윽.. ㅡ0ㅠ... 난 너무 허접한거 같은....
아아아아아아~~ 모르겠다아아아아~~~
Interrupt Vector Table에 Reset을 제외한 나머지에 모두 같은 Function으로 brench
하게 설정한다음 SWI 0x01 일케 했다.
음~ LED에 불이 들어오는걸 확인했다. 으음... Software Interrupt를 발생하게하는건
x86이랑 거의 차이가 없네..
명령만 틀린거 같고... 흐음...

아웅.. 잠와...
아침이 왜이리 빡신지.. 모르겠다.
난주 생각해야지.. ㅡ_ㅡzZZ
음... Interrupt를 이용한 Context Switching을 고민하고 있는데...
User Level에서 Switching하는거 보다 약간 더 까다로운 문제가 있군.

첫째, Banked Register에 대한 처리 ( SP, LR )
둘째, Reenterance에 대한 처리

이 두가지가 문제가 되는거 같다.
머 사실 Baked Register는 CPSR을 조작하면 되는 문제인데, Reenterance는 쬐금
생각을 더 해봐야겠다.
지금까지의 생각은 Task끼리 Interrupt없이 Sleep() 같은걸 하기위해 Switching을
할때는 직접적으로 Switching 함수를 불러서 수행할 생각이었는데, 이것이 만약에
직접 Call한 Switching함수에서 Interrupt가 불려서 다시 스위칭이 될 경우...
현재 루틴에서는 문제가 발생할 소지가 있다. @0@/~~

간단히 하려고 생각하고 있는데, 자꾸 문제가 나오면서 점점 더 복잡한 로직으로
가는 듯도 하고.. ㅡ_ㅡ;;;
머 빵빵한 x86 같으면 Task 마다 IRQ, SVC Stack을 각각 할당하고
마구 Stack 전환을 난무(??) 하면서 할텐데... 이것도 사실 오바인거 같고.. Orz

흠.. 걍 Task끼리 Switching 할때도 SWI를 통한 Interrupt로 하도록 해서 단순화를
하는것도 생각해 볼만한거 같다.
일단 그람 그래해 볼까나??
훗.. @0@/~~
으으.. 어제 만든 Context Switching 코드를 테스트 한답시고 요것조것 바꿔가면서 하고있었는데, 아무리 해도 시나리오 대로 진행이 되지 않았다.
쿨럭..;;;

첫번째 문제는 Link를 한 목적파일의 코드가 Start Address 0 으로 정렬되지 않았다는 것이고, 두번째 문제는 DRAM쪽 메모리를 초기화 하지 않아서 DRAM쪽에 메모리를 아무리써 도 읽을때 내가 쓴 값이 아니라는 것이었다.

Start Address야 머, 역어셈하면서 왼쪽에 Address 나오는거 보고도 지나쳤고, DRAM쪽은....

초기화 해야하는지 몰랐다. @0@/~

이때까지 코드에 자동적으로 라인을 초기화하는 코드가 숨어있었기 땜시롱... ㅡ0ㅠ...
으으.. 몬산다 몬살아...
자.. 그람 또 MEMORY쪽을 살펴볼까...
크윽..;;; Orz
링크
앗쌀 좋구나 @0@/~~

이것도 한번 써봐야 쓰것다~
오늘 한 2시간 삽질한 결과 허접하게나마 Task Switching을 시험해 볼 수 있었다.
음.. 새로구한 ARM Emulator로 비교적 순조롭게 디버깅을 하면서 진행했는데, 상당
히 괜찮은 프로그램을 구한 것 같다는 생각이 든다.
@0@/~~ 어셈코드 마구 보여주고 메모리도 덤프해주고..
음냥 넘 좋은거 아니라..ㅋㅋㅋ

근데.. 역시 사람이 어떤걸 자주 접하게 되면 거기에 물드는거 같다.
처음에 Context를 저장하는걸 Stack에 안하고 따로 내가 만든 영역에 하려고 생각했
었는데, 워낙 예제 코드들이 자기 Stack에다가 저장하는걸 많이 보여줘서...

결국 내가 짠 코드는...
내가만든 영역에.. Stack Order로 저장하는.. 쿠.. 쿨럭..;;;;
디버깅하다가 한참을 헤맸다. 분명 되야하는데, 이놈이 거꾸로 들어간다 하면서...
당연히 거꾸로 들어갈 수 밖에.. Stack Order 명령을 줬으니.. ㅡ_ㅡ;;;;;
쩝.. 여튼 나중에 알고 깜짝 놀랐다. @0@/~~

이제 쫌만 더하면 안되겠나.. ㅋㅋㅋ
으음... Context Switching을 한번 해볼려고 어셈코드를 잡고 씨름중인데.. ㅡ_ㅡ;;;
어셈을 잘 모르니 참 답답하다. 일단 c 코드를 만든 다음 역어셈해서 나오는 어셈코드
를 중심으로 살펴보고는 있으나, 역쉬... 머리속에 그림이 잘 그려지지 않는다.
우째야 쓰까나...
코드는 대충 짜 놨는데, 잘 돌아가는지 테스트 할려니 넘 야심하네...
기분도 우울한데... 쩝쩝... 낼 해야 쓰겄다. @0@/~~
ARM Assembly
흠... 나름대로 괜찮은거 같은데, 일단 난주 둘러보기로 하자.
자야징... ( ^0^)r~~
여전히 부트코드를 돌아다니며 훓어보고 있는데 아래와 같은 루틴이 보였다.

FlashingWait:
mov r0, #FLASHING_DELAY
FlashingWait1:
subs r0, r0, #1
bne FlashingWait1 <<== 요기.. 주목...

sub 함수 밑에 바로 brench 명령이 딱 붙어있는 것이었다. 그것도 ne를 붙이고..
음.. sub도 s를 따라 붙이긴 했는데 멀까 하면서 ARM 문서를 신나게 뒤진 결과...
s가 붙으면 sub를 한 결과에 따라 cmp 명령처럼 Condition Field에 Update를 하는
것 같다.
음냥.. 그람 조걸 풀어쓰면..

sub r0, r0, #1
cmp r0, #0
bne FlashingWait1

으음.. 것참 신기하구만.. @0@/~~
약 30분 정도를 삽질한 끝에 시리얼로 데이터를 송신할 수 있게 되었다. 시리얼 설정하
는 레지스터가 PC의 메인보드에 달려있는 시리얼 설정하는 레지스터랑 거의 비슷해서
별 무리없이 된거 같다.
혹시 똑같은건가?? ㅡ_ㅡ;;; 워낙 오래되서 PC꺼는 생각이 잘 안나는데.. 쩝쩝...
메뉴얼을 보고 요것 조것 넣어가면서 어설프게 9600으로 송신하는걸 만들었으니,
이제 쫌더 손봐서 송수신 하도록 하고 Baud Rate도 쫌더 높여야겠다.
쩝... 이제야 먼가 되가는거 같군.
컥.. 이런.. 다른 PC에서 Cygwin을 깔고 툴을 컴파일하니까..




가 난다. ㅡ_ㅡ;;; 몬산다 몬살아... 이상하네 분명히 같은 버전인데 왜 여기서는
안될까나??
으으.. 머리에 스팀이 꽉차서 죽겠다. ㅡㅠㅡ;;;;
음냥.. 프로젝트 전체에 넘치는 Global 들로인해 드뎌 어디서 머가 되고, 어떤 파일에
이 Global 들이 있는지 파악하기 어려운 단계에 이르렀다.
쿨럭..;; 여튼 정리를 하긴 해야 할 것 같은데...
Class를 만들어서 처리를 할려고 하니 쓰는 곳이 한두군데가 아니어서 상당히 빡시게
구르고 있다.
완전 노가다다.. ㅡ_ㅡ;;;
우쒸... 이러다가 관절염 걸리겠네 그려...
아아.. 참 길고도 험한 여정이었다. ㅡ_ㅠ
Cache 땜시롱 한번 헤매고, EDMA 땜시롱 한번 헤매고, AD535 ADC 땜시롱 또 헤매
고... 음메, 왜 일케 빡신겨...
사실 Sampling 처리에 문제가 조금 있었는데, 내가 녹음한 MP3 파일은 44khz Stero
형식인데, C6711의 AD535는 Mono에 8khz다.
따라서 변환이 필요한데, 머 마땅히 어디서 손쉽게(??) 긁어올 수 있는 곳은 안보이고,
고민하던중 또 나의 얍삽이가 고개를 들었다. (어찌나 고마운지.. ㅋㅋ)

"음... 8khz는 44khz의 약 1/5 쯤이니까 버퍼를 5개씩 뛰어가면서 0xFFFE로 AND한
다음 그걸 담아서 EDMA로 전송하게 하면... +ㅁ+/~~"

지금 생각해보니, 정말 하드코어(??) 얍삽인데.. ㅡ_ㅡ;;; 여튼 급하니까 일단 구현을
했었다.
MP3 Codec이 한번 디코딩을 하면 4068(?? 확실치 않음)byte 정도의 데이터가 나왔
는데, 이걸 내가 만든 얍삽이로 play를 하게되면 아래와 같이 된다.


정상적인 44khz Stero를 쓸때 :
4068 / ( 44 * 1024 * 2 ) = 0.0451초

하드코어 얍삽이 + 8khz Mono를 쓸때 :
4068 / ( 2 * 5 ) / ( 8 * 1024 ) = 0.0497초


따라서 소리가 약간 늘어지고 거칠게 들리긴 하는데, 나름대로



고 생각한다. ㅡ_ㅡ;;;; (절대 타협하는건 아니고, 진짜 들을만 하다 +ㅁ+/~)
근데 허무한건, 난 아무것도 아직 한게 없다는 것이다.
기껏해야 EDMA랑 MCBSP랑을 연결해서 출력을 하게 했는데 걍 소리 나오고.. ㅡ_ㅡ;
C5510 할때는 실수 연산하는 함수까지 내가 만들어서 Clock을 줄일려고 난리쳤는데...
FPU의 힘을 강하게 느끼는 계기가 되었다.

없는놈이 있는 놈을 이기려면, 같은 조건가지고는 영 어렵겠군.
여튼 1차 완료~ @0@/~
음... 오늘 ARM 문서를 보면서 여러개의 레지스터의 값을 메모리로 저장하고, 메모리
에서 읽어오고 하는 문서를 봤는데... 역시 책으로만 보니 별로 잘 모르겠다. ㅡ_ㅡ;;
일단 명령을 실행하고 메모리를 보면 금방 알꺼 같은데.. 그러기 위해서는 눈으로
멀 표시하게 하는게 최고 우선인거 같다.
당장 붙어있는 놈이라고는 LED하고 시리얼 정돈데... LED로 보는건 좀 어의없는거
같고 그렇다면 역시 시리얼쪽을....... +ㅁ+
흠... 일단 UART쪽 프로그래밍을 쬐금 해서 write만 구현해 놓고 PC에서 확인하는
쪽으로 진행을 해야겠다.
LCD가 없으니 쫌 답답하군... ㅡ_ㅡ;;;
쿨럭.. ㅡ_ㅡ;;;; 오늘 AD535에 대한 문서를 줄줄이 뽑아서 읽어보던중... DSP -> AD535로 가는 Voice Data 중 0bit가 특별한 의미를 갖는다는걸 알았다.

0bit가 1로 설정되면 다음 16bit data는 Codec Register 설정에 대한 데이터를 의미하는 것이었었더랬었던 것이다.(?? ㅡ_ㅡ;;; 상당히 문법이 의심스러운... 갑자기 회사 사람이 이야기 해준 Hello,World 누가 길게 찍나가 생각나네.. ㅋㅋ)

쿨럭..;;
그렇다면 AD535는 0xFFFE로 AND 연산을 해준다음 데이터를 쏴야~ 제대로 소리가나온다는.. 쿨럭..;;;

여튼 그래서 AND를 해주고 데이터를 송신하니 별 이상없이 소리가 나긴 나는거 같다.
거참 어렵구만.. ㅡ_ㅡ;;;
Boot Code를 분석하던 중에 LDR과 MOV의 명령을 보게 되었다.
ARM 문서를 보니 둘다 레지스터에 값을 넣는거던데.. ㅡ_ㅡ;;;
이래 저래 서로 명령어를 스위칭해가면서 테스트 했는데 실패...
웹상에서 아는 분께 물었더니,

LDR ==> 메모리에서 레지스터로 값을 넣음.
MOV ==> 레지스터 또는 Immediate를 레지스터로 넣음.

이었던 것이다.
음냥.. 근데 여기서 이상한걸 발견할 수가 있는데, LDR과 MOV 모두 12bit Address
bit를 가지고 있다.
근데, LED 포트는 0x90040000로 표기되는 32bit인데 어떻게 LDR r0, =0x90040000
를 통해 레지스터에 32bit 값을 넣을 수 있는 것일가??

arm-linux-gcc로 일단 컴파일 링크를 거친다음 arm-linux-objdump로 역어셈블해본
결과 위의 코드는 아래와 같이 되어있었다.

80c8: e59f0068 ldr r0, [pc, #68] ; 8138 <LedFlashing+0x1c>
.....
8138: 90040000 andls r0, r4, lr

컥... 결국 메모리에 0x90040000를 어딘가에 써넣고, LDR 명령에는 해당 OFFSET의
메모리 Address만 넣어둔 것이었다 @0@/~~
쿠.. 쿨럭..;;
저.. 저런식인가.. ㅡ_ㅡ;;;
으으.. 나의 허접한 ARM 어셈실력으로 메뉴얼을 뒤져가며 삽질한 결과...
드뎌 LED가 라운드로빈되면서 켜지기 시작했다.
하려하는 구체적은 생각은 있는데, 어셈명령을 몰라 일단 생각나는 x86 어셈을 마구
난타한다음 컴파일 실행 @0@/~
역시나



!!!

눈물을 줄줄 흘리면서 Linux 커널에 있는 .S 파일을 뒤져서 보던중 BLE 란놈을 발견
하고 문서를 뒤진결과 B + 조건 의 형태로 구성되어있는 명령어들을 발견 @0@/~~
코딩후 바로 실행~~
오오~~ LED가 돌아가는걸 확인 할 수 있었다.
아아.. 드뎌 한 걸음 땠구나... ㅡ0ㅠ..
Flash에 구워서 되는걸 확인했으니, 이제 슬슬 해보면 될꺼 같다.
흐믓하군. ㅋㅋ
홧팅 >ㅁ</~
으으.. ㅡ_ㅡ;;; 왜일케 복잡한지... 믿었던 문서에 약간 미비한점도 있고...
여튼 이래 저래 하다보니 결국 크로스 컴파일러를 만들었다.
근데, 이놈도 마찬가지로 링크할때 바로 binary로 링크가 안되고 ELF로 링크가
되었다. binary를 사용하게 포멧을 binary로 줬더니 ARM링크할때는 ELF말고는
안된다는 에라 메시지가 나온다.
힘들게 컴파일 했더니만, 결국 GNUARM과 같은 결과가 나왔다.
일케되면 GNUARM을 걍 설치하고 PATH만 잡아주는거랑 같은결관데.. ㅡ0ㅠ/~
완전 생쇼를 했군... ㅡ_ㅡ;;;
머 그래도 제대로 설치 됬으니, 그것 하나는 다행인거 같고...
부트로더 같은거 만들려면... 순수 Binary가 필요한데 멀로 만드나...
ObjCopy라는게 있긴하던데, 이걸로 만드는감...
일단 낼 또 한번 뺑이를 쳐봐야 겠군.

오.. 글고 신기한건, 어셈 파일 형식인데 .S라는 확장자를 가지고 내부적으로는 C파일
전처리기 + 어셈코드 인거 같다.
어셈코드안에 #include 가 있는걸 보니...
으음.. 일케되면 걍 쓰면 된다는 결론이 나오네...

좋구로.. ㅋㅋㅋ
아.. 야심하군. 자야긋다.
홧팅 @0@/~~
쿠오~ 오늘 KESL 사이트를 뒤지다가
Cygwin에서 소스를 다 받아서 크로스 컴파일러를 만드는 문서를 구했다.
문서에 보니깐 테스트까지 해봤다고 해서, 속는 셈 치고 해봤더니
얼래.. ㅡ_ㅡ;;
gcc와 glibc가 만들어지는거 까지 확인했다.





!!!

이것만 되면 또 열심히 삽질하면서 플래쉬 굽고 리셋하고를 반복하겠군.
아아.. x86 커널 만들면서 다시는 안하겠다고 다짐했는데.. ㅡ_ㅡ;;;
시간이 좀 지나니 또 관심이 가는것이... 으으.. ㅡ_ㅠ...
일단 어셈코드부터 익숙해져야 겠다.
다 알 필요는 없지만 부트 코드랑 어셈 함수 정도는 만들 수 있어야 나중에 편해지니
까 고정도까지만 해둬야징...

여튼 좋구나아아아아~~~
쿠하하핫 @0@/~
음메... Cygwin과 GNUARM의 조합으로 구축해 보려던 환경은 오늘 실패로 끝났다.
으으... 설정파일 같은걸 시도하다가 결국 실패하여 파일을 한 폴더에 몰아넣는
'하드코어' 테크닉을 구사하여 머 실행까지는 시켰는데... ㅡ_ㅡ;;;
문제가 3가지 정도 있었다.

1. library 파일을 못찾는다.
2. include 파일을 못찾는다.
3. elf 파일 포멧 말고는 못만든다. (난 Binary 파일하고 coff 파일이 필요한데.. ㅡ_ㅡ)

쿠.. 쿨럭..;;;
걍 리눅스 깔아서 거기서 쓸까나.. ㅡ_ㅡ;;;;
요즘 또 ARM쪽에 문서를 보기 시작했는데, 이놈이 참 재밌는 구조를 하고 있다.
특히 IRQ위에 상위 Fast IRQ인가 하는게 더 있던데...(명칭 불확실) IRQ보다 우선순위
가 높아서 IRQ가 발생한 시점에도 Fast IRQ가 선점가능하다.
그리고 운영 모드도 여러 모드가 있어서 상당히 세분화 되있는듯한 느낌을 받았는데,
인상적인건 각 모드마다 banked register라는게 있어서 모드가 변경될때 이 레지스터
들은 이전 모드에서 사용하는 레지스터가 아니라는 것이다. @0@/~
오우~ 얼마나 헷갈리는 이야기인가.. ㅡ_ㅡ;;;
머 여튼 뺑이 쳐보면 알겠지.. ㅋㅋ
글고 어셈 명령이 좀 특이하던데, 어셈명령하나로 여러개의 레지스터에 줄줄이 넣고
빼고 할 수 있는거 같넹.
스택에 줄줄이 넣고 빼던데 이걸 사용하면 걍 스택에 넣는걸로 해서 Task Switching
을 구현할 수 있을꺼 같다.
쿠핫핫핫핫~
뺑이다 뺑이 @0@/~~
아래 바로가기 누르기

GNU ARM

+ Recent posts