2012-02-09 2 views
2

기본 베어 메탈 Cortex-M3 프로그래밍 정보를 찾을 때 다음과 매우 비슷한 것을 보았습니다. (여기에서 대단한 답을 얻었습니다. 나중에 찾으려고합니다.)ARM 링커는 예외 테이블이 중지되는 위치를 어떻게 알 수 있습니까?

/* vectors.s */ 
.cpu cortex-m3 
.thumb 

.word 0x20002000 /* stack top address */ 
.word _start  /* 1 Reset */ 
.word hang  /* 2 NMI */ 
.word hang  /* 3 HardFault */ 
.word hang  /* 4 MemManage */ 
.word hang  /* 5 BusFault */ 
.word hang  /* 6 UsageFault */ 
.word hang  /* 7 RESERVED */ 
.word hang  /* 8 RESERVED */ 
.word hang  /* 9 RESERVED*/ 
.word hang  /* 10 RESERVED */ 
.word hang  /* 11 SVCall */ 
.word hang  /* 12 Debug Monitor */ 
.word hang  /* 13 RESERVED */ 
.word hang  /* 14 PendSV */ 
.word hang  /* 15 SysTick */ 
.word hang  /* 16 External Interrupt(0) */ 
.word hang  /* 17 External Interrupt(1) */ 
.word hang  /* 18 External Interrupt(2) */ 
.word hang  /* 19 ... */ 

.thumb_func 
.global _start 
_start: 
    bl notmain 
    b hang 

.thumb_func 
hang: b . 

이 나에게 의미가 있습니다 (... 또는 CPU, 나는 어떤을 모르겠어요) 나는 그것이 무엇을 이해하지만, 나에게 이해가되지 않습니다 무엇 링커가 어떻게 어디 예외 테이블을 알고있다 실제 코드가 시작됩니다. Cortex-M3 문서에서 테이블에 임의의 수의 외부 인터럽트가있을 수 있습니다.

어떻게 작동하나요? 배우기 위해 무엇을 읽어야합니까?

답변

2

그건 내 코드이고, 프로그래머는 무슨 일이 일어나고 있는지 알아야하는 링커가 아닙니다. cortex-m은 다른 벡터 테이블을 가지며 상당히 길고 많은 개별 인터럽트 벡터를 가질 수 있습니다. 어느 날 어느 날 맛이 위의 것보다 빠릅니다. 리셋 벡터 이상을 사용하지 않는다면 더 많은 메모리 위치를 구워서 전체 테이블을 생성해야합니까? 아마. 정의되지 않은 예외 및 중단을 다루기에 충분히 깊은 것을 원할 수 있습니다. 따라서 제어 된 중단으로 트랩 할 수 있습니다. 리셋과 하나의 인터럽트 만 필요하지만 인터럽트가 꽤 깊다면 두 테이블 모두를 커버하기 위해 커다란 테이블을 만들거나 잃어버린 공간을 복구하기 위해 용감한 코드를 넣을 수 있습니다.

자세한 내용을 보려면 armv7-m 코어 용 ARM ARM은 물론 특정 cortex-m 코어 cortex-m0, cortex-m3 및 cortex-m4에 대한 TRM 기술 참조 설명서를 참조하십시오. m (대뇌 피질 -m은 모두 armv7-m 계열 임). ARM ARM은 일반적으로 전체 제품군에 대해 이야기하지만 핵심적인 세부 사항까지도 다루는 ARM 아키텍처 참조 설명서를 의미하므로 일반적으로 ARM을 프로그래밍 할 때 ARM ARM과 올바른 TRM이 필요합니다. asm 또는 특정 레지스터와 같은 수준). 모든 것은 ARM 웹 사이트 infocenter.arm.com에서 찾을 수 있습니다. 왼쪽 구조는 Cortex-M 시리즈 프로세서입니다.

이 코어는 충분히 새 것이므로 원래의 rev 번호보다 많지는 않습니다. 구형 코어의 경우 특정 코어에 대해 TRM을 얻는 것이 가장 좋습니다. ARM11 Mpcore의 경우, 예를 들어 벤더가 사용 설명서의 구형 표시에도 불구하고 코어의 1.0 (r1p0)을 사용한다면 차이점이있을 경우 rev 1.0 매뉴얼을 사용하려고합니다. 벤더들은 항상 어떤 레브를 사거나 사용했는지 알려주지 않으므로 문제를 프로그램 할 방법을 정할 때 문제가 될 수 있습니다. 또는 정오표가 적용될 때와 그렇지 않은 경우를 구분할 수 있습니다. (Linux는 이것을 이해하지 못하기 때문에 ARM과 관련된 실수가 많습니다. 일반적으로 잘못된 에라타가 적용되거나 잘못된 코어에 적용되거나, 잘못된 코어 또는 잘못된 시간에 사용 된 명령어 등).

필자는 먼저 cortex-m3에 대한 핸들러를 작성한 다음 처음에 하나를 얻었을 때이를 잘라내어 붙여 넣거나 붙여 넣어 수정/변경하려고했습니다.

코어 (CPU, 로직)는 지원되는 인터럽트 수를 확실히 알고 있으며 벡터 테이블의 전체 구성을 알고 있습니다. 코어의 가장자리에는 이러한 종류의 것들을 바꿀 수있는 제어 신호가있을 수 있으며, 벤더는 그 한 방향으로 묶거나 프로그램 가능하게 만들었을 것입니다. 그 코어에 대한 논리가 무엇인지에 관계없이 벡터 테이블이 무엇인지 확실히 알고 있더라도 프로그래머가 필요에 따라 코드를 하드웨어와 일치시키는 것처럼 말입니다. 이 모든 내용은 해당 핵심에 대한 TRM에 설명되어 있습니다.

이러한 이벤트 나 인터럽트의 각 오프셋 주소 또는 될 것입니다 논리에 하드

편집

. 따라서 인터럽트 나 이벤트가 발생하면 해당 주소에서 메모리 읽기를 수행합니다.

이것은 플래시 메모리의 뱅크이며, 주소에 피드 스트로브를 넘겨주고 일부 데이터가 나옵니다. 그 비트들은 문맥에 넣기 전까지는 의미가 없습니다. 해당 주소에서로드 명령어를 수행하는 일부 코드를 작성하거나 해당 주소로 분기 할 수 있고 명령어를 찾기를 원하는 위치를 페치 사이클이 읽는 경우 및 이벤트에 하드 코드 된 코드가있는 경우 주소 0x10에서 메모리 순환이 발생할 수 있습니다 주소를 읽고 그 주소에서 읽기가 발생하면 처리기에 대한 주소를 찾고자합니다. 그러나 그것은 단지 기억 일뿐입니다. 파일 시스템의 파일과 마찬가지로 디스크의 바이트 수. 그것이 jpeg이면 특정 바이트가 픽셀 일 수 있습니다. 디스크의 파일이 프로그램 인 경우 오프셋의 바이트가 명령어가 될 수 있습니다. 그것의 단지 1 바이트.

이러한 주소는 로직에서 직접 생성됩니다. 요즘의 논리는 프로그래밍 언어 (보통 verilog 또는 vhdl 또는 출력으로 verilog 또는 vhdl을 생성하는 일부 고급 언어)를 사용하여 작성됩니다. 당신이 좋아하는 언어로 프로그램을 작성한다면 당신은 문자 그대로 어떤 주소를

x = (unsigned int *)0x1234; 

를 하드하도록 선택할 수 있습니다 또는 당신이 구조 또는 배열이나 다른 프로그래밍 스타일의 일종을 사용하도록 선택할 수 있지만, 한 번하는 것보다 다르지 않습니다

unsigned int vector_table[256]; 
... 
handler_address = vector_table[interrupt_base+interrupt_number]; 
... 

그래서 프로그래머로서,이 낮은 수준에서, 당신은 하드웨어가이 주소 중 하나 이유를 읽으려고하는 경우에 때 알고있다 : 컴파일 여전히 몇 가지 고정 된 주소 또는 오프셋을 생산 끝납니다. 인터럽트를 사용하지 않기 때문에 결코 인터럽트를 사용하지 않으면 인터럽트 핸들러 주소를 정상적으로 보유 할 수있는 메모리 위치가 이제는 원하는 모든 용도로 사용할 수있는 메모리 위치가됩니다. 당신이 많은 경우에 보았 듯이, 거의 모든 나의 예제들 중 오직 오직 리셋 벡터를 필요로하고 나머지는 사용하지 않습니다. 실수로 정렬되지 않은 액세스를 수행하는 경우 실수로 정의되지 않은 명령어 처리기 또는 데이터 중단이 발생할 수 있지만 대개 처리기를 배치 할 정도로 걱정하지는 않습니다. 나는 충돌 할 것이고 어쨌든 걸어 놓을 것이다. 내가 거기에 갈 때 그 문제를 해결할 것이고, 내가 갈 때 다리를 건너는 것이다. 그래서 껍질-m 스택 주소에 대한 최소한 대개 내용이고 다시 주소 :

.cpu cortex-m3 
.thumb 

.word 0x20002000 /* stack top address */ 
.word _start  /* 1 Reset */ 

.thumb_func 
.global _start 
_start: 
    bl notmain 
    b hang 

.thumb_func 
hang: b . 

그리고 네, 절대적으로 내가 NMI의 ​​메모리 위치에 두 개의 단어 명령 BL의 notmain에 놓여있다. NMI가 발생하면 CPU가 해당 위치를 읽고, 핸들러의 주소라고 가정하고, 그 주소에서 명령을 가져 오도록 시도합니다. 누가 그 주소를 알 수 있습니까? 그것은 심지어 그것이 잘못된 주소이고 위의 경우 어딘가에 또 다른 주소가 될 데이터 중단을 야기하기 전에 알 수 있으며, 데이터 중단의 무한 루프로 변할 수 있습니다. 또는 우연히 그러한 지침 중 하나가 우리 프로그램의 주소처럼 나타나는 경우 기본적으로 프로그램 중간에 바로 뛰어 들어서 어떤 종류의 충돌이 발생할 수 있습니다. 추락 무엇입니까? 정말? cpu가 메모리에서 바이트를 읽고 해당 명령어가 정렬되지 않은 액세스를 수행하도록 지시하거나 해당 바이트가 유효한 명령어가 아니거나 잘못된 벡터 메모리 주소를 읽게되면 벡터 테이블로 되돌아 가도록 명령을 해석합니다. 또는 코드 공간의 중간에서 점프하여 쓰거나 읽는 엉망인 주소가 플래시 뱅크를 지우거나 uart를 빠져 나가는 바이트 또는 gpio 입력 포트가 출력 포트 (정말로 운이 좋으면 바닥이나 무언가를 몰아 치고 칩을 녹일 수 있습니다).

이상한 일들이 보이기 시작하면 (벡터가 보이지 않거나 냄새가 나지 않거나 잘 보이지 않는 경우) 벡터 테이블에서 수십 개의 항목을 던져 버릴 수도 있고 처리기를 가리킬 수도 있습니다. 포트 밖으로 무엇인가 침을 뱉거나 gpio/led를 켭니다.내 기괴함이 이제이 주도자가되거나 처리기의 출력이 나오면 어떤 이벤트가 발생했는지를 정리해야합니다. 또는 애플리케이션의 마지막 몇 가지 변경 사항에 대해 생각해 보면 정렬되지 않은 액세스 나 분기가 있음을 알 수 있습니다. 등

그것은 그 말에 돌아갑니다 잡초로, "컴퓨터 나던 당신이 그것을 할 수을 원하는 무엇, 그것은 당신 그것을 할 말한 않습니다". 거기에 바이트를 넣고 올바른 위치에 올바른 바이트를 넣지 않으면 올바른 위치에 벡터 주소를 넣고 올바른 작업을 수행하는 지침과 올바른 위치에 올바른 데이터를 넣습니다. 할 수 있거나 충돌 할 수 있습니다.

+0

나는 이것이 인터럽트 벡터 테이블이라는 것을 알고 있으며, 이것이 필요하기 때문에 희소하고 완전 할 수 있다는 것을 이해하지만, 내가 이해하지 못하는 것은 CPU 나 그게 무엇인지 알고 있다는 것이다. 특정 라인의 덩어리는 인터럽트 벡터 테이블이며 그 다음 라인은 인터럽트 벡터 테이블이 아닙니다. 섹션을 구분하는 것은 무엇입니까? 파일에서 벡터 테이블이 제일 먼저 있어야합니까? "첫 번째 .thumb_func 지시문 앞에 오는 모든 것"으로 정의됩니까? – Mark

+0

또는 단순히 벡터 테이블을 끝내고 나머지는 코드 공간으로 사용하고 있습니까? I.E. 예를 들어 NMI 인터럽트가 끝난 후 테이블을 종료하고 BusFault 인터럽트가 발생했다면 벡터 테이블의 슬롯에 일부 명령어 나 데이터가 있었기 때문에 이상한 곳으로 건너 뛸까요? – Mark

1

답변은 그렇지 않습니다. 프로그래머는 CPU에서 생성 된 모든 것을 잡아 내기 위해 충분한 수의 벡터를 넣어야합니다. 그것을 망치면 CPU는 벡터 테이블 뒤에 (예 : _start 코드의 명령과 같은) 무언가를로드하고 벡터처럼 취급하여 점프하려고 시도 할 수 있습니다 (데이터 중단이 발생할 수 있음).

관련 문제