2013-03-07 36 views
7

Vì tôi tương đối mới đối với C, tôi phải sử dụng cho một trong các dự án của mình như sau: tôi phải khai báo một số biến toàn cục phải được lưu trữ mỗi khi chương trình chạy cùng một địa chỉ bộ nhớ. Tôi đã đọc một số và tôi thấy rằng đó là tôi tuyên bố nó "tĩnh" nó sẽ được lưu trữ tại cùng một vị trí bộ nhớ.Làm thế nào để lưu trữ một biến tại một vị trí bộ nhớ cụ thể?

Nhưng câu hỏi của tôi là: tôi có thể chỉ định chương trình lưu trữ biến đó hay không. Ví dụ: int a được lưu trữ tại 0xff520000. Điều này có thể được thực hiện hay không? tôi đã tìm kiếm ở đây nhưng không tìm thấy bất kỳ ví dụ có liên quan nào. Nếu họ là một số bài cũ về điều này, xin vui lòng được như vậy loại để chia sẻ liên kết.

Cảm ơn mọi người trước. Laurentiu

Cập nhật: Tôi đang sử dụng một 32uC

+1

Phổ biến trên hệ thống nhúng có đăng ký phần cứng tại địa chỉ cụ thể. Tuy nhiên, trên một máy tính bình thường, không thể dự đoán biến của bạn sẽ kết thúc ở đâu và bạn có thể không đặt biến vào vị trí bộ nhớ cụ thể tương tự như bản đồ bộ nhớ của chương trình không cố định. Đây có phải là cho một hệ thống nhúng hoặc cho một máy tính bình thường? –

+1

Tại sao địa chỉ lại quan trọng? Nó là ** bộ nhớ ảo ** anyway. – UmNyobe

+0

Xin chào, tôi phải làm như sau. Làm một loại nền tảng thử nghiệm cho một UC 32 bit, nhưng sau khi nhấp nháy qua OCD, nền tảng nên có (chạy) trên truyền thông UART. Và giả sử tôi có bộ đếm đếm số lần chương trình đã chạy, hoặc bộ đếm lưu trữ bao nhiêu thời gian chương trình chạy mà không có lỗi, thì giáo sư của tôi sẽ cung cấp thông tin gì qua đầu vào Hyper Terminal địa chỉ có bộ đếm biến đó, để có được giá trị của nó. Đó là những gì tôi cần .. bất kỳ ý tưởng nào: – Laurentiu

Trả lời

10

Trong IDE của bạn, sẽ có một bản đồ bộ nhớ có sẵn thông qua một số tệp liên kết. Nó sẽ chứa tất cả các địa chỉ trong chương trình. Đọc hướng dẫn MCU để xem địa chỉ nào có bộ nhớ hợp lệ cho mục đích của bạn, sau đó đặt trước một số bộ nhớ đó cho biến của bạn. Bạn phải đọc tài liệu về nền tảng phát triển cụ thể của bạn.

Tiếp theo, xin lưu ý rằng các biến bản đồ tại các địa chỉ cụ thể không có ý nghĩa trừ khi chúng là bộ đăng ký phần cứng hoặc biến không biến đổi nằm trong flash hoặc EEPROM.

Nếu nội dung của vị trí bộ nhớ như vậy sẽ thay đổi trong quá trình thực thi, vì nó là một thanh ghi, hoặc vì chương trình của bạn chứa thuật toán lập trình bộ nạp khởi động/NVM thay đổi ô nhớ NVM, thì các biến phải được khai báo là dễ bay hơi. Nếu không trình biên dịch sẽ phá vỡ hoàn toàn mã của bạn khi tối ưu hóa.

Trình biên dịch cụ thể rất có thể có cách không chuẩn để phân bổ biến tại các địa chỉ cụ thể, chẳng hạn như #pragma hoặc đôi khi toán tử lạ, phi tiêu chuẩn @. Cách hợp lý duy nhất bạn có thể phân bổ một biến tại một vị trí cố định trong tiêu chuẩn C, là:

#define MY_REGISTER (*(volatile uint8_t*)0x12345678u) 

nơi 0x12345678 là địa chỉ có 1 byte của vị trí đó. Khi bạn có khai báo macro như thế này, bạn có thể sử dụng nó như thể đó là một biến:

void func (void) 
{ 
    MY_REGISTER = 1; // write 
    int var = MY_REGISTER; // read 
} 

Thông thường bạn muốn loại biến này nằm trong không gian tên chung, do đó macro. Nhưng nếu bạn vì lý do nào đó muốn phạm vi của biến bị giảm, sau đó bỏ qua macro và truy cập địa chỉ theo cách thủ công bên trong mã:

void func (void) 
{ 
    *(volatile uint8_t*)0x12345678u = 1; // write 
    int var = *(volatile uint8_t*)0x12345678u; // read 
} 
+0

Cảm ơn bạn.Đây là những gì tôi muốn. Tôi nghe theo lời khuyên của bạn và thấy như sau: NHỚ iROM \t: XỨ = 0x00000000, \t LENGTH = 3072k IRAM \t: XỨ = 0xFEDC0000, \t LENGTH = 256k BURAM \t: XỨ = 0xFF760000, \t LENGTH = 16k
Tôi cho rằng tôi phải selec một số phạm vi từ RAM từ những gì tôi cần phải không? – Laurentiu

+1

Nhân tiện: Tại sao bạn sử dụng địa chỉ như 0x12345678u? những gì u từ cuối đại diện? – Laurentiu

+2

@Laurentiu Hậu tố 'u' (hoặc' U') có nghĩa là chữ số nguyên là loại 'unsigned'. Nó ở đó để đảm bảo rằng loại thụt lề được sử dụng, tôi đã viết nó chủ yếu là từ thói quen cũ. Một chữ số nguyên trong nguồn C là kiểu (đã ký) 'int' theo mặc định, nhưng vì địa chỉ không bao giờ có thể là số âm, nên không sử dụng biến được ký để lưu trữ nó. Nói chung, bạn không bao giờ muốn sử dụng kiểu 'int' mặc định trong các hệ thống nhúng. Trong một số trường hợp khi làm số học đơn giản, bạn có thể muốn sử dụng các loại 'sintN_t', trong đó N = 8, 16 vv Nhưng hầu hết thời gian, bạn chỉ sử dụng các biến chưa ký. – Lundin

1

Không bạn không thể nói với nó một cách rõ ràng nơi để lưu trữ một biến trong bộ nhớ. Chủ yếu là bởi vì trên các hệ thống hiện đại, bạn có nhiều thứ được thực hiện bởi hệ thống liên quan đến bộ nhớ, đó là ngoài tầm kiểm soát của bạn. Bố trí địa chỉ Ngẫu nhiên là một điều mà nói đến cái tâm mà sẽ làm cho điều này rất khó.

0

Không phải ở cấp C. Nếu bạn làm việc với ngôn ngữ lắp ráp, bạn có thể trực tiếp kiểm soát bố cục bộ nhớ. Nhưng trình biên dịch C thực hiện điều này cho bạn. Bạn không thể thực sự gây rối với nó.

Ngay cả khi lắp ráp, điều này chỉ kiểm soát bố cục tương đối. Bộ nhớ ảo có thể đặt nó ở bất kỳ vị trí vật lý thuận tiện nào.

8

Bạn có thể thực hiện việc này bằng các tập lệnh liên kết, điều này khá phổ biến trong lập trình được nhúng. Trên một hệ thống Linux, bạn có thể không bao giờ nhận được cùng một địa chỉ ảo do ngẫu nhiên không gian địa chỉ (tính năng bảo mật để tránh khai thác dựa trên việc biết chính xác vị trí của một biến như bạn mô tả).

Nếu đó chỉ là con trỏ lặp lại bạn muốn, bạn có thể ánh xạ địa chỉ cụ thể với mmap, nhưng điều đó không được đảm bảo.

+0

Đúng. Khi tôi nghĩ rằng bằng cách sử dụng mmap, để ánh xạ địa chỉ không gian vào tập tin có thể giải quyết vấn đề. Chỉ cần chăm sóc của nó sẽ phải được thực hiện để mmap (CONST_ADDR, ....., fd, CONST_FILE_OFFSET); sẽ không thất bại (hoặc bản đồ tại diff-addr hơn COSNT_ADDR). Sau đó CONST_ADDR trở thành địa chỉ của biến toàn cục và các thay đổi được thực hiện cho bộ đếm toàn cầu này sẽ phản ánh trong tệp, có thể được sử dụng thêm trong chương trình tiếp theo. –

0

Bạn có thể thực hiện việc này với một số phần mở rộng của trình biên dịch, nhưng có lẽ đó không phải là những gì bạn muốn làm. Hệ điều hành xử lý bộ nhớ của bạn và sẽ đặt những thứ mà nó muốn. Làm thế nào để bạn thậm chí biết rằng địa chỉ bộ nhớ bạn muốn sẽ được ánh xạ trong chương trình của bạn? Bỏ qua tất cả mọi thứ trong đoạn này nếu bạn đang ở trên một nền tảng nhúng, sau đó bạn nên đọc hướng dẫn cho nền tảng/trình biên dịch đó hoặc ít nhất đề cập đến nó ở đây để mọi người có thể đưa ra một câu trả lời cụ thể hơn.

Ngoài ra, biến tĩnh không nhất thiết phải có cùng địa chỉ khi chương trình chạy. Nhiều hệ điều hành sử dụng các tệp thực thi độc lập vị trí và ngẫu nhiên hóa không gian địa chỉ trên mọi thực thi.

0

Bạn có thể khai báo một con trỏ đến một địa chỉ bộ nhớ cụ thể, và sử dụng các nội dung của con trỏ đó như là một biến Tôi cho rằng:

int* myIntPointer = 0xff520000; 
+0

inecast it. – anishsane

1

Giống như đã được đề cập trong câu trả lời khác - bạn có thể không. Nhưng, bạn có thể có cách giải quyết. Nếu đó là ok cho globals được khởi tạo trong main(), bạn có thể làm điều gì đó thuộc loại này:

int addr = 0xff520000; 

int main() 
{ 
    *((int*)addr) = 42; 
    ... 
    return 0; 
} 

Lưu ý, tuy nhiên, điều này là rất phụ thuộc vào hệ thống của bạn và nếu chạy trong môi trường được bảo vệ, bạn sẽ rất có thể có được một vụ tai nạn thời gian chạy.Nếu bạn đang ở trong môi trường nhúng/không được bảo vệ, điều này có thể hoạt động.

+0

Cái này hoạt động. Nhưng bạn có thể vui lòng cho tôi biết làm thế nào tôi có thể tìm thấy một vị trí nơi để lưu trữ thực sự biến của tôi? Bởi vì tôi cho rằng tôi không thể sử dụng một số vùng bộ nhớ ramdom của UC? – Laurentiu

+0

@Laurentiu Trong IDE của bạn sẽ có một bản đồ bộ nhớ có sẵn thông qua một số tập tin liên kết. Nó sẽ chứa tất cả các địa chỉ trong chương trình. Đọc hướng dẫn MCU để xem địa chỉ nào có bộ nhớ hợp lệ cho mục đích của bạn, sau đó đặt trước một số bộ nhớ đó cho biến của bạn. Bạn phải đọc tài liệu về nền tảng phát triển cụ thể của bạn. – Lundin

Các vấn đề liên quan