2011-06-18 8 views
9

Tôi đang làm việc trên một dự án ARM7TDMI bằng GCC 4.3 và tôi đang nói với trình biên dịch để sử dụng các cuộc gọi dài trong một số trường hợp nhất định.long_calls giữa các phần RAM và ROM trên ARM kim loại trần với gcc

Quá trình xây dựng chạy arm-eabi-gcc để tạo định vị các file đối tượng ELF cho mỗi tập tin nguồn .c (CFLAGS phù hợp nhất bao gồm -Os -ffunction-sections -fdata-sections -mthumb -mthumb-interwork), sau đó liên kết tất cả chúng thành một thực thi ELF (hầu hết LDFLAGS liên quan bao gồm -Wl,--gc-sections -Wl,-static -Wl,-n -nostdlib, và một kịch bản tùy chỉnh mối liên kết) . Sau đó, tập tin ELF được chuyển đổi thành một tập tin thực thi thô với arm-eabi-objcopy -O binary, và một bộ tải khởi động tùy chỉnh sao chép nó từ ROM sang RAM (một SRAM duy nhất với cả mã và dữ liệu) khi khởi động. Vì vậy, tất cả mọi thứ sau đó thực hiện từ RAM, .rodata là hiện diện trong RAM, và mọi thứ tiến hành nhanh chóng, hoàn toàn bỏ qua ROM sau khi khởi động.

Tôi đang cố gắng thay đổi điều đó, sao cho một số phần dữ liệu RO nhất định và văn bản của các hàm chọn có thể chỉ hoạt động trong ROM và được truy cập trong thời gian chạy khi cần thiết. Tôi đã sửa đổi kịch bản trình liên kết để biết về hai phần mới ".flashdata"".flashtext", cả hai phần này phải được đặt ở một địa chỉ cố định trong ROM. Tôi cũng đã rải __attribute__((__section__(".flashdata")))__attribute__((__section__(".flashtext"),__long_call__)) trên toàn bộ mã C khi thích hợp và tôi đã tái hoạt hóa quy trình xây dựng để hiện tượng objcopy cũ thêm -R .flashdata -R .flashtext và tôi thực hiện một objcopy thứ hai với -j cho từng phần đó, sau đó tôi kết hợp hai tệp đầu ra sao cho bộ nạp khởi động có thể làm điều đúng và các phần ROM xuất hiện ở vị trí được ánh xạ bộ nhớ mong muốn.

này tất cả hoạt động tốt - Tôi có thể printf dây gắn thẻ vào phần .flashdata, và tôi có thể gọi một hàm .flashtext từ mã chạy trên RAM (mà biết sử dụng một cuộc gọi dài do đặc tính __long_call__ bên cạnh thuộc tính __section__(".flashtext")). Chức năng dựa trên ROM đó có thể gọi ngắn gọn các chức năng dựa trên ROM khác, và nó có thể quay trở lại với trình gọi dựa trên RAM của nó.

Sự cố xảy ra khi cố gắng gọi từ một chức năng dựa trên ROM thành một bộ nhớ dựa trên RAM, đó cũng phải là một cuộc gọi dài. Tôi không muốn sử dụng các cuộc gọi dài ở khắp mọi nơi, vì vậy tôi không muốn -mlong_calls trong CFLAGS của tôi. Nếu tôi nhóm tất cả các chức năng để sống trong ROM thành một đơn rom.c, tôi có thể tạo một tệp với -mlong-calls và mọi thứ hoạt động. Tuy nhiên, tôi mạnh mẽ muốn tránh điều đó, và giữ cho các chức năng được nhóm lại theo mục đích, chỉ cần gắn thẻ một vài ở đây và ở đó khi thích hợp để chạy từ ROM.

Ngẫu nhiên, điều này không đủ theo gcc 3.4. Sử dụng -mlong-calls có trình biên dịch suy nghĩ đúng, nhưng nó không thể đi qua vì nó chỉ sẵn sàng thực hiện các bước nhảy dài với những người trợ giúp _call_via_rX ... tất cả đều sống trong RAM và chỉ có thể truy cập thông qua một cuộc gọi dài. This was fixed in the linker in gcc 4.0, but not backported to anything in the 3.x tree.

Vì vậy, thật tuyệt vời mà bây giờ tôi có thể gọi lại vào RAM vì tôi đang sử dụng gcc 4.3. Sẽ tốt hơn nếu tôi bằng cách nào đó có thể gắn thẻ mã trong các hàm dựa trên ROM để buộc nó sử dụng các cuộc gọi dài. Có một #pragma long_calls, nhưng nó chỉ ảnh hưởng đến các khai báo, vì vậy tôi có thể sử dụng nó thay vì __attribute__((__long_call__)). Thật đáng buồn là không có sức ép buộc trình biên dịch sử dụng các cuộc gọi dài cho tất cả các cuộc gọi chức năng gặp phải trong khi nó có hiệu lực.

Về mặt tổ chức, đơn giản là không phải là điều đúng đắn để nhóm tất cả mã chạy chậm thành một tệp, ngoài ngữ cảnh và tách biệt với mã khác trong danh mục chung của nó. Vui lòng cho tôi biết có một tùy chọn mà tôi chưa xem xét. Tại sao không phải là phần chức năng hoặc chỉ thực tế là mã ở các phần khác nhau (.text so với .flashtext) tự động khắc phục sự cố của tôi?

Nhân tiện, lỗi ra khỏi trình liên kết khi nó chỉ ra rằng trình biên dịch đã sử dụng một cuộc gọi ngắn mà không để lại đủ không gian để quản lý việc di chuyển là: relocation truncated to fit: R_ARM_THM_CALL against symbol foo 'được xác định trong phần .text.foo objs/foo.o (and the section .text.foo is used instead of .tiếp theo because of -chức năng-phần` trong CFLAGS).

Trả lời

3

Dường như sự cố có thể được khắc phục trong gcc 4.3.3 trở lên, nhưng tôi đã sử dụng 4.3.2. Tôi đã tạo một ví dụ thú cưng sẽ không thực thi, nhưng thể hiện việc sử dụng các phần khác nhau và lỗi liên kết kết quả. Không thể xây dựng với arm-2008q3 của Codesourcery, nhưng nó xây dựng với arm-2009q1 và sau đó. Sẽ mất nhiều thời gian hơn để tôi cập nhật toàn bộ dự án để sử dụng phiên bản gcc mới hơn, vì vậy tôi chưa thể nói dứt khoát rằng điều này khắc phục được sự cố của tôi, nhưng tôi thực sự nghi ngờ nó.

Như một sang một bên, tôi có một giải pháp thay thế cho việc nhóm tất cả các hàm dựa trên ROM thành một rom.cố -mthumb-calls -built: Gọi mọi thứ qua con trỏ hàm. Trong trường hợp của workaround này, chữa bệnh là tồi tệ hơn bệnh:

((void(*)(void*, void*, int))&memcpy+1)(&dest, &src, len); 

Bạn cần +1 để tôi ưu hoa không outsmart bạn, nhưng nó không phải là một vấn đề trong trường hợp của tôi vì bx -ing cho một địa chỉ lẻ cho biết chế độ ngón tay cái và tất cả mã của tôi đều là ngón tay cái. Tuy nhiên, tôi không tin rằng có một cách để tạo macro chung để bao bọc tất cả các cuộc gọi hàm, vì mỗi con trỏ sẽ cần phải được đúc một cách rõ ràng để khớp với kiểu trả về và danh sách đối số - bạn kết thúc một cách rõ ràng khai báo lại mọi hàm bạn muốn gọi, ngay cả các chức năng thư viện mà bạn không cung cấp.

3

Tôi nghi ngờ không có cách nào để làm những gì bạn muốn tự động. Tôi có một gợi ý, mặc dù nó không phải là chính xác những gì bạn muốn.

Khai báo các chức năng RAM (trong ram_funcs.h, nói) như thế này:

int foo() RAM_CALL; 

Sau đó đặt tất cả các chức năng ROM của bạn vào các tập tin riêng của họ, và bắt đầu mỗi của những tập tin như thế này:

#define RAM_CALL __attribute__((__long_call__)) 
#include "ram_funcs.h" 

file khác sẽ sử dụng:

#define RAM_CALL 
#include "ram_funcs.h" 

Đây không phải là tốt hơn nhiều so với sử dụng -mlong-calls, nhưng ít nhất nó đặt logic gần các chức năng thay vì trong một số tùy chọn biên dịch. Làm cho nó dễ dàng hơn để đặt một vài chức năng trong mỗi tập tin .c, ví dụ.