2010-11-01 11 views
19

Các RealView ARM C Compiler supports đặt một biến tại một địa chỉ bộ nhớ được sử dụng thuộc tính biến at(address):Làm thế nào để đặt một biến tại một địa chỉ tuyệt đối được đưa ra trong bộ nhớ (với GCC)

int var __attribute__((at(0x40001000))); 
var = 4; // changes the memory located at 0x40001000 

Liệu GCC có một thuộc tính biến tương tự?

+1

Tôi đã viết một [bài viết] (http://a3f.at/articles/register-syntax-sugar), nơi tôi liệt kê các phương tiện để làm như vậy. Có thể hữu ích cho một số người. – a3f

Trả lời

18

Tôi không biết, nhưng bạn có thể dễ dàng tạo ra một cách giải quyết như thế này:

int *var = (int*)0x40001000; 
*var = 4; 

Nó không phải chính xác điều tương tự, nhưng trong hầu hết các tình huống một người thay thế hoàn hảo. Nó sẽ làm việc với bất kỳ trình biên dịch, không chỉ GCC.

Nếu bạn sử dụng GCC, tôi giả sử bạn cũng sử dụng GNU ld (mặc dù nó không chắc chắn, tất nhiên) và ld có hỗ trợ đặt biến wherever you want them.

Tôi tưởng tượng việc cho phép trình liên kết thực hiện công việc đó khá phổ biến.

Lấy cảm hứng từ câu trả lời của @rib, tôi sẽ thêm rằng nếu địa chỉ tuyệt đối dành cho một số thanh ghi kiểm soát, tôi sẽ thêm volatile vào định nghĩa con trỏ. Nếu nó chỉ là RAM, nó không quan trọng.

+0

+1 cho sự sáng tạo. Không biết nếu nó thực sự hoạt động, nhưng nó âm thanh thực sự hợp lý, cũng như di động (theo nghĩa là nó sẽ làm việc cho tất cả các trình biên dịch). – falstro

+1

@roe: Đó là một mẹo khá chuẩn có thể sử dụng trong các trình điều khiển thiết bị cho phần cứng với bộ nhớ đăng ký kiểm soát bộ nhớ cố định.Trong một ứng dụng người dùng chuẩn, nó không có tiện ích gì mà tôi có thể nghĩ đến. – JeremyP

+0

@JeremyP, trong các thiết bị nhúng, đặc biệt là những người không có MMU, tất cả đều quá phổ biến để cho phép "ứng dụng người dùng" tấn công phần cứng. –

5

Bạn đã trả lời câu hỏi của bạn, Trong liên kết của bạn ở trên nó khẳng định:

Với GNU GCC trình biên dịch, bạn có thể chỉ sử dụng các định nghĩa con trỏ để truy cập bộ nhớ vị trí tuyệt đối. Ví dụ:

#define IOPIN0   (*((volatile unsigned long *) 0xE0028000)) 
IOPIN0 = 0x4; 

Btw http://gcc.gnu.org/onlinedocs/gcc-4.5.0/gcc/Variable-Attributes.html#Variable%20Attributes

+0

Thú vị, không biết điều đó. –

8

Bạn có thể sử dụng section attributes và ld linker script để xác định địa chỉ mong muốn cho phần đó. Điều này có lẽ là lộn xộn hơn so với lựa chọn thay thế của bạn, nhưng nó là một lựa chọn.

+3

Lưu ý rằng cách tiếp cận này sẽ * thực sự dự trữ * không gian cho biến, thay vì giả sử nó tồn tại tại địa chỉ được chỉ định. Trong nhiều trường hợp, đây là những gì bạn muốn. – larskholte

+0

Một liên kết trực tiếp hơn cho thuộc tính phần: https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html#Common-Variable-Attributes và ctrl + f cho "section" – Ponkadoodle

0
extern const uint8_t dev_serial[12]; 
    asm(".equ dev_serial, 0x1FFFF7E8"); 
/* or asm("dev_serial = 0x1FFFF7E8"); */ 
    ... 

    for (i = 0 ; i < sizeof(dev_serial); i++) 
     printf((char *)"%02x ", dev_serial[i]); 
+0

Điều này thêm gì cho câu trả lời hiện có? – OrangeDog

+0

Mặc dù đoạn mã này có thể giải quyết được câu hỏi, [bao gồm cả giải thích] (https://meta.stackexchange.com/questions/114762/explaining-entirely-code-based-answers) thực sự giúp cải thiện chất lượng bài đăng của bạn. Hãy nhớ rằng bạn đang trả lời câu hỏi cho người đọc trong tương lai và những người đó có thể không biết lý do cho đề xuất mã của bạn. Ngoài ra, vui lòng không cố gắng gắn mã của bạn với các nhận xét giải thích, điều này làm giảm khả năng đọc của cả mã và giải thích! –