2014-04-05 2 views
2

다음 바이트 주소를 사용하여 임베디드 응용 프로그램 (ARM 베어 메탈)에서 주변 장치 용 32 비트 레지스터 집합을 가지고 있습니다.'C'구조체 요소 사이에 수동으로 패딩 바이트 삽입

CTL 0x0;
STAT 0x4를
TXR 0x8이 < - 불연속 주소
RXR가 0x20
DAT1 0x30에 < - 불연속 주소
DAT2 × 40 < - 불연속 주소
와 너무

에 나는 그룹에 원하는 모든 C 구조체에 등록한다. (포장 된 구조체)

struct my_peri { 
    uint32_t CTL; 
    uint32_t STAT; 
    uint32_t TXR; 
    uint32_t RXR; 
    uint32_t DAT1; 
    uint32_t DAT2; 
}; 

struct my_peri* pPeri0 = (uint32_t*) (BASE_ADDRESS_OF_MY_PERI_0); 

내가 액세스하면 오른쪽에게 어드레스 권리를 얻기 위하여

pPeri->RXR; // This will point to (BASE_ADDRESS + 0x10) 
      // But the actual address i want to refer is (BASE_ADDRESS + 0x20) 

나 수동 주연 사양에 따라 에러를 제공

struct my_peri { 
    uint32_t CTL; 
    uint32_t STAT; 
    uint32_t TXR; 
    uint32_t RESERVED[4]; // 0x10 to 0x1c 
    uint32_t RXR; 
    uint32_t RESERVED_1[3]; // 0x24-0x2c 
    uint32_t DAT1; 
    uint32_t RESERVED_2[3]; // 0x34-0x3c 
    uint32_t DAT2; 
}; 

그러나 RESERVED, RESERVED_1 및 RESERVED_2 모든 액세스 사이에 요소를 추가했다.

Is there a way to add address spacing between the struct elements? 
Without adding RESERVED elements 

If not, is there a way to group these registers into a single data structure?. 
With each register pointing to the right address. 

저는 ARM-GCC toolchain을 사용하고 있습니다.

+1

'휘발성'(예 : '휘발성으로 간주 됨 유해'등)을 원할 수도 있습니다. –

답변

2

예, "비트 필드"를 사용하여 구조체 내 이름 필드를 만들 수 있습니다

struct my_peri { 
    uint32_t CTL; 
    uint32_t STAT; 
    uint32_t TXR; 
    uint32_t : 32; 
    uint32_t RXR; 
    uint32_t : 32; 
    uint32_t : 32; 
    uint32_t : 32; 
    uint32_t DAT1; 
    uint32_t : 32; 
    uint32_t : 32; 
    uint32_t : 32; 
    uint32_t DAT2; 
}; 

는 불행하게도 배열 구문이 없다; 유형을 uint64_t로 변경하여 :32의 쌍을 :64으로 접을 수 있습니다.

필드가이 예와 같은 모든 유형 인 경우 정수를 정수 배열로 처리하고 enum { CTL = 0, STAT = 1, TXR = 2, RXR = 4, ... }을 사용하여 색인을 생성하는 것이 좋습니다.

+0

정렬이 올바를 경우에만 uint64_t로 붕괴 할 수 있습니다.) –

+0

@tc : 정렬이 잘못되면 속성 (packed)을 사용할 수 있지만 플랫폼에 철자가있는 경우 ... 하드웨어를 다루는 경우 어쨌든 잘 할 필요가있다. :) –

0

귀하의 질문에 모두 대답하려면 필연적으로 C는 구조체에 특정 레이아웃을 적용 할 수있는 조항이 없으므로 가짜 패딩 요소가 필연적으로 발생합니다.

그러나 궁극적으로 스파 스 레이아웃을 사용하면 포인터로 가득 찬 구조체를 사용하는 것이 좋습니다. 이렇게하면 어떤 식 으로든 레이아웃을 제한하지 않고 const 대신 gcc가 참조를 완전히 최적화하고 전체 배열을 최적화해야하는 경우 포인터를 대부분의 경우에 한정합니다. 나는 이것이 당신이 요구 한 바가 아니라는 것을 인정하지만, 여전히 문제를 푸는 좋은 방법이라고 생각합니다. 더 이상 C 확장에 의존하지 않고 컴파일러가 패킹 및 레이아웃 요구 사항을 존중하기를 바랍니다.

0
#include <stdio.h> 
#include <stddef.h> 
#include <inttypes.h> 

struct my_peri { 
    uint32_t CTL; 
    uint32_t STAT; 
    uint32_t TXR; 
    uint32_t RXR __attribute__((aligned (32))); 
    uint32_t DAT1 __attribute__((aligned (16))); 
    uint32_t DAT2 __attribute__((aligned (16))); 
}; 

int main(void) 
{ 
    printf("RXR @%x\n", (unsigned) offsetof(struct my_peri, RXR)); 
    printf("DAT1 @%x\n", (unsigned) offsetof(struct my_peri, DAT1)); 
    printf("DAT2 @%x\n", (unsigned) offsetof(struct my_peri, DAT2)); 
    return 0; 
} 

출력 : aligned 값이 두 힘이 될 필요가 있음을

RXR @20 
DAT1 @30 
DAT2 @40 

참고. 그러나 그것은 여기에서 작동합니다.