2011-07-19 9 views
5

Trong các định nghĩa CMSIS cho gcc bạn có thể tìm thấy một cái gì đó như thế này:dữ liệu Memory Barrier (DMB) trong các thư viện CMSIS cho Cortex-M3S

static __INLINE void __DMB(void) { __ASM volatile ("dmb"); } 

Câu hỏi của tôi là: những gì sử dụng không một rào cản bộ nhớ có nếu nó không khai báo "bộ nhớ" trong danh sách thư mục?

Đây có phải là lỗi trong core_cm3.h hoặc có lý do khiến gcc hoạt động bình thường mà không có bất kỳ trợ giúp nào khác không?

+1

Câu hỏi hay. Lưu ý rằng Linux sử dụng 'bộ nhớ' clobber: http://lxr.free-electrons.com/source/arch/arm/include/asm/system.h?v=2.6.39#L135 – ninjalj

+1

@ninjalj: Cảm ơn vì liên kết. (không xuất hiện trên googling nhanh chóng) – jpc

Trả lời

5

Tôi đã thực hiện một số thử nghiệm với gcc 4.5.2 (được xây dựng với LTO). Nếu tôi biên dịch mã này:

static inline void __DMB(void) { asm volatile ("dmb"); } 
static inline void __DMB2(void) { asm volatile ("dmb" ::: "memory"); } 

char x; 

char test1 (void) 
{ 
    x = 15; 
    return x; 
} 

char test2 (void) 
{ 
    x = 15; 
    __DMB(); 
    return x; 
} 

char test3 (void) 
{ 
    x = 15; 
    __DMB2(); 
    return x; 
} 

sử dụng arm-none-eabi-gcc -Os -mcpu=cortex-m3 -mthumb -c dmb.c, sau đó từ arm-none-eabi-objdump -d dmb.o tôi có được điều này:

00000000 <test1>: 
    0: 4b01  ldr r3, [pc, #4] ; (8 <test1+0x8>) 
    2: 200f  movs r0, #15 
    4: 7018  strb r0, [r3, #0] 
    6: 4770  bx lr 
    8: 00000000 .word 0x00000000 

0000000c <test2>: 
    c: 4b02  ldr r3, [pc, #8] ; (18 <test2+0xc>) 
    e: 200f  movs r0, #15 
    10: 7018  strb r0, [r3, #0] 
    12: f3bf 8f5f dmb sy 
    16: 4770  bx lr 
    18: 00000000 .word 0x00000000 

0000001c <test3>: 
    1c: 4b03  ldr r3, [pc, #12] ; (2c <test3+0x10>) 
    1e: 220f  movs r2, #15 
    20: 701a  strb r2, [r3, #0] 
    22: f3bf 8f5f dmb sy 
    26: 7818  ldrb r0, [r3, #0] 
    28: 4770  bx lr 
    2a: bf00  nop 
    2c: 00000000 .word 0x00000000 

Rõ ràng là __DBM() chỉ chèn hướng dẫn dmb và phải mất DMB2() để thực sự buộc các trình biên dịch xóa các giá trị được lưu trong bộ đăng ký.

Tôi đoán tôi đã tìm thấy lỗi CMSIS.

2

IMHO phiên bản CMSIS là đúng.

Chích hướng dẫn rào cản mà không có bộ nhớ trong danh sách clobber đạt được chính xác những gì nó là vụ phải làm:

Nếu ghi trước vào "x" biến được đệm sau đó nó được thực hiện. Điều này rất hữu ích, ví dụ, nếu bạn định chuyển địa chỉ "x" thành địa chỉ DMA, hoặc nếu bạn định thiết lập MPU.

Nó không có hiệu lực khi trả về "x" (chương trình của bạn được đảm bảo đúng ngay cả khi bạn bỏ qua rào cản bộ nhớ).

Mặt khác bằng cách chèn bộ nhớ vào danh sách dấu kiểm, bạn không có tác dụng nào trong các trường hợp như ví dụ trước (DMA, MPU ..).

Sự khác biệt duy nhất trong trường hợp thứ hai là nếu bạn có ví dụ ISR sửa đổi giá trị "x" ngay sau "strb", thì giá trị sẽ được trả về là giá trị được sửa đổi bởi ISR, vì clobber khiến trình biên dịch đọc từ bộ nhớ để đăng ký lại. Nhưng nếu bạn muốn có được điều này thì bạn nên sử dụng biến "dễ bay hơi".

Nói cách khác: rào cản buộc bộ nhớ cache và bộ nhớ cam kết để đảm bảo tính nhất quán với các tài nguyên HW khác có thể truy cập bộ nhớ RAM, trong khi bộ nhớ clobbering khiến trình biên dịch ngừng giả sử bộ nhớ không thay đổi và đọc lại trong sổ đăng ký cục bộ , đó là một điều khác với các mục đích khác nhau (nó không quan trọng nếu một thay đổi bộ nhớ vẫn còn trong bộ nhớ cache hoặc đã cam kết trên RAM, bởi vì một hoạt động tải asm cuối cùng được đảm bảo để làm việc trong cả hai trường hợp không có rào cản).

+1

Nhưng không phải là trình biên dịch miễn phí để sắp xếp lại các hướng dẫn xung quanh để ghi vào "x" không đạt bộ nhớ cache ở tất cả tại thời điểm rào cản được thực hiện? Tôi muốn các bộ nhớ clobber để trình biên dịch buộc phải cam kết biến để (có thể bộ nhớ cache) bộ nhớ, và sau đó là rào cản để buộc bộ nhớ cache tuôn ra. – jpc