2013-08-15 3 views
1

Atmel에서 AT91SAM7X256을 프로그래밍 중이며 레지스터를 정의하는 매크로와이를 사용하는 방법에 대해 조금 혼란 스럽습니다.비트를 설정하는 매크로 확장

나는 같은 라인을 사용하는 레지스터의 비트 설정하려면 다음 나는 매크로 확장 후이 볼 때 이런 식으로 뭔가 보이는 지금

AT91C_BASE_PMC->PMC_PCER = 1 << AT91C_ID_PWMC; 

을 :

((AT91PS_PMC) 0xFFFFFC00)->PMC_PCER = 1 << (10); 

정의를 파일에서 찾을 수있는 것 AT91SAM7X256.h

#ifndef __ASSEMBLY__ 
typedef volatile unsigned int AT91_REG;// Hardware register definition 
#define AT91_CAST(a) (a) 
#else 
#define AT91_CAST(a) 
#endif 

하고는 내가 더 아래

... 
#define AT91C_BASE_CKGR  (AT91_CAST(AT91PS_CKGR) 0xFFFFFC20) // (CKGR) Base Address 
#define AT91C_BASE_PMC  (AT91_CAST(AT91PS_PMC)  0xFFFFFC00) // (PMC) Base Address 
#define AT91C_BASE_RSTC  (AT91_CAST(AT91PS_RSTC) 0xFFFFFD00) // (RSTC) Base Address 
... 

AT91C_BASE_PMC의 (고화질)은 그래서이 매우 간단 확장받을 것으로 보인다 찾을 수 있습니다. 마찬가지로 매크로 AT91C_ID_PWMC는

... 
#define AT91C_ID_TWI (9) // Two-Wire Interface 
#define AT91C_ID_PWMC (10) // PWM Controller 
#define AT91C_ID_UDP (11) // USB Device Port 
... 

로 정의되어 있지만 어떻게 역 참조 ((AT91PS_PMC) 0xFFFFFC00가) 수행 -> PMC_PCER 사용할 수 있습니까? PMC_PCER에 대한 몇 가지 정의를 찾을 수 있습니다.

#ifndef __ASSEMBLY__ 
typedef struct _AT91S_SYS { 
    ... 
    AT91_REG  Reserved20[1];  // 
    AT91_REG  PMC_PCER; // Peripheral Clock Enable Register 
    AT91_REG  PMC_PCDR; // Peripheral Clock Disable Register 
    ... 
} AT91S_SYS, *AT91PS_SYS; 
#else 

#endif 

그리고 다시 내려 간다.

#ifndef __ASSEMBLY__ 
typedef struct _AT91S_PMC { 
    ... 
    AT91_REG  Reserved0[1]; // 
    AT91_REG  PMC_PCER; // Peripheral Clock Enable Register 
    AT91_REG  PMC_PCDR; // Peripheral Clock Disable Register 
    ... 
} AT91S_PMC, *AT91PS_PMC; 
#else 
... 
#define PMC_SCSR  (AT91_CAST(AT91_REG *) 0x00000008) // (PMC_SCSR) System Clock Status Register 
#define PMC_PCER  (AT91_CAST(AT91_REG *) 0x00000010) // (PMC_PCER) Peripheral Clock Enable Register 
#define PMC_PCDR  (AT91_CAST(AT91_REG *) 0x00000014) // (PMC_PCDR) Peripheral Clock Disable Register 
... 
#endif 

그래서 제 질문은

  • 어떻게 그 매크로 작업을 할 수 있습니다?
  • 나는 AT91C_BASE_PMC-> PMC_PCER = 1 식으로 단일 비트를 설정할 수 있다는 인상을 가지고있다. < < AT91C_ID_PWMC; ? 사실입니까?
  • 어떻게 그 비트를 해제하겠습니까?
  • 값을 직접 설정하는 것이 아니라 왜 이렇게 복잡합니까?

답변

5

이식 가능한 코드가 아니지만 C의 기능과 메모리 매핑 I/O 장치와의 인터페이스 기능을 설명합니다.

  1. 캐스팅 ((AT91PS_PMC) 0xFFFFFC00) 메모리 어드레스가 입력 0xFFFFFC00 AT91PS_PMC의 구조에 대한 포인터로 취급 될 것임을 의미한다. 그 구조 내에서, 0xFFFFFC00 어드레스로부터의 적절한 오프셋에서 주변 클록 인 에이블 레지스터 (PMC_PCER)가 존재한다.

    따라서 할당은 기본 주소 0xFFFFFC00이 올바른 것으로 가정하고 1024 (1 << 10)을 PMC_PCER 레지스터에 쓰도록 배열합니다.

  2. 이렇게하면 레지스터가 단일 세트 비트를 포함하는 값으로 설정됩니다.대부분의 사람들이 '단일 비트 설정'을 의미하는 것과 같지 않습니다. 그는 같은 라인을 수행 할 것입니다 :

    이의 PMC_PCER의 현재 값을 읽고 그것을 수정하고 다시 쓰는
    AT91C_BASE_PMC->PMC_PCER |= 1 << AT91C_ID_PWMC; 
    

    참고. 읽고 쓰는 것이 안전한지 여부는 칩의 세부 사항에 달려 있습니다.

    AT91C_BASE_PMC->PMC_PCER = 0; 
    AT91C_BASE_PMC->PMC_PCER &= ~(1 << AT91C_ID_PWMC); 
    

    첫 번째는 하나의 비트가 너무 단일 비트가 0 설정 해제에 값을 설정, 설정되어 있다고 가정합니다

  3. 그렇게 적어도 두 가지 방법이 있습니다. 두 번째는 PMC_PCER 레지스터의 현재 값을 읽고, AT91C_ID_PWMC 비트를 제외한 모든 비트가 1 비트 인 값으로 비트 AND를 수행하고 (따라서 비트를 0으로 설정 함) 값을 다시 씁니다.

  4. 왜 이렇게 되었습니까? 모든 플랫폼 별 세부 정보를 수집하고 각 주소를 수동으로 작성하지 않아도되므로 보드를 나중에 수정할 수 있으며 코드를 다시 작성하지 않고 다시 컴파일 할 수 있습니다.

+0

감사합니다. 아주 좋은 설명. 나는 functionally를 가능하게하는 쓰기 전용 레지스터에 쓰기 때문에 단일 비트와 혼동을 느꼈지만 별도의 레지스터는 functionallity를 비활성화합니다. – Lucas