Xác định cuộc gọi lại cho các ngắt


7

Tôi đang làm việc với một STM32 và tôi hơi bối rối về các ngắt, đặc biệt là các ngắt Vectored Nested (NVI). Theo tôi hiểu, có một vectơ NVI (được gọi là NVIC) trong đó mỗi ngắt có mức độ ưu tiên (đôi khi có thể giải quyết được) và một địa chỉ (xem trang 157 của tài liệu tham khảo ARM tại đây ).

Bây giờ tôi giả sử rằng đối với mỗi loại ngắt, có thể đính kèm chức năng gọi lại và tôi nghi ngờ rằng địa chỉ đính kèm với mỗi ngắt có liên quan đến địa chỉ của cuộc gọi lại.

Chính xác địa chỉ được đính kèm với một ngắt nhất định là gì? Làm thế nào tôi có thể định nghĩa (trong C, giả sử) hàm gọi lại cho một ngắt cho trước?


không biết trực tiếp về cánh tay, nhưng nhiều bộ xử lý có một lệnh hoàn trả từ ngắt đặc biệt, giúp loại bỏ thông tin bổ sung khỏi ngăn xếp thường đi kèm với ngắt. Tuy nhiên, chỉ có một mối quan tâm thực sự nếu bạn đang viết chương trình biên dịch chương trình; hầu hết các trình biên dịch C cho phép bạn trang trí chức năng của mình bằng từ 'ngắt' và trình biên dịch sẽ đảm nhiệm việc chọn mã thoát chính xác.
JustJeff

@JustJeff: Bạn có thể chỉ ra tài liệu liên quan đến trang trí 'gián đoạn' này không?
Randomblue

nó thường không quan trọng - chỉ cần dán từ 'ngắt' trước kiểu trả về hàm. Vì vậy, thay vì void foo () {...} , bạn đã làm gián đoạn void foo () {...}
JustJeff

@JustJeff Chỉ cần lưu ý rằng cú pháp để xác định ngắt phụ thuộc vào kết hợp trình biên dịch / trình liên kết chứ không phải bộ xử lý đích. Ví dụ, trình biên dịch ARM GCC và trình biên dịch ARM IAR có thể định nghĩa cú pháp cho một hàm ngắt khác nhau mặc dù thực tế là chúng đang xây dựng mã cho cùng một bộ xử lý.
AngryEE

@AngryEE - Tôi không nghĩ rằng tôi thực sự đã nói nó phụ thuộc vào kiến ​​trúc mục tiêu. Nhưng có, các chi tiết có thể thay đổi theo hoàn cảnh. Tôi chỉ muốn chỉ ra một thực tế là thường có một số việc bạn cần làm, vì ngăn xếp được thiết lập hơi khác so với các ngắt so với các cuộc gọi thông thường.
JustJeff

Câu trả lời:


4

Các ARM thực hiện một bảng ngắt để lưu địa chỉ cho mỗi trình xử lý ngắt (hoặc gọi lại, về cơ bản là cùng một thứ). Về cơ bản, tất cả các địa chỉ của các trình xử lý ngắt được lưu trữ trong bộ nhớ chương trình tại một vị trí được xác định trước. Khi xảy ra gián đoạn, bộ xử lý sẽ biết vị trí trong bảng của mục đó bị gián đoạn, lấy nó và phân nhánh đến địa chỉ được lưu trữ ở đó.

Làm thế nào để bạn điền vào bảng này? Thông thường tất cả thông tin này được chứa trong một tập tin khởi động. Thông thường, bạn chỉ cần xác định một mảng các con trỏ không đổi, điền nó với địa chỉ của các cuộc gọi lại mà bạn muốn sử dụng. Dưới đây là một trang web chi tiết cách tạo tệp khởi động cho một vi điều khiển ARM cụ thể. Điều khó khăn ở đây là hầu như tất cả các chi tiết của việc tạo tệp phụ thuộc rất nhiều vào trình liên kết, trình biên dịch và chip mà bạn đang sử dụng, do đó, bạn sẽ phải tìm một ví dụ ngoài đó hoặc tự mình tìm hiểu.


4

vỏ não-m3 rất thân thiện. Bạn không cần một tấm bạt lò xo trong asm hoặc cần thêm bất kỳ cú pháp trình biên dịch không chuẩn nào để làm cho trình biên dịch làm điều đó cho bạn. Phần cứng phù hợp với abi bằng cách duy trì một số lượng thanh ghi nhất định cho bạn cũng như thay đổi chế độ. Thanh ghi liên kết được mã hóa để khi trở về từ chức năng, phần cứng biết nó thực sự là một sự trở lại từ ngắt. Vì vậy, tất cả những điều bạn phải làm trên một cánh tay và nhiều bộ xử lý khác mà bạn không phải làm.

Tương tự, với mức độ đau đớn, cortex-m (và các nhánh mới hơn) có một vectơ vectơ trong bảng vectơ, hàng chục đến hàng trăm ngắt, v.v. như đã đề cập trong một nhận xét ở trên, hãy xem http://github.com/ dwelch67 / stm32f4d ví dụ blinker05 sử dụng các ngắt với bộ định thời gian, bạn có thể thấy trong vectơ rằng tất cả những gì bạn làm là đặt tên của hàm:

.word hang
.word tim5_handler
.word hang

Và sau đó viết mã C:

//-------------------------------------------------------------------
volatile unsigned int intcounter;
//-------------------------------------------------------------------
// CAREFUL, THIS IS AN INTERRUPT HANDLER
void tim5_handler ( void )
{
    intcounter++;
    PUT32(TIM5BASE+0x10,0x00000000);
}
// CAREFUL, THIS IS AN INTERRUPT HANDLER
//------------------------------------------------------------------

Bây giờ, như với bất kỳ ngắt từ một số thiết bị ngoại vi / thiết bị mà bạn có thể phải, trong trình xử lý, hãy nói với thiết bị để xóa ngắt nếu không bạn có thể bị kẹt liên tục vào lại trình xử lý.

Các ví dụ của tôi không sử dụng IDE, chúng sử dụng các công cụ nguồn mở (gnu gcc và binutils và trình biên dịch clang của llvm). Xóa các nhị phân clang khỏi tất cả: dòng trong makefile nếu bạn không có / muốn sử dụng llvm. Các công cụ gnu rất dễ xuất hiện, cả hai đều được xây dựng từ các nguồn (tôi có hướng dẫn ở đâu đó tại github, có thể là một số địa điểm) hoặc chỉ lấy phiên bản rút gọn từ mã hóa (bây giờ là đồ họa cố vấn). Các ví dụ của tôi được phát triển và thử nghiệm trên linux, nhưng điều đó không làm nản lòng người dùng windows, thay đổi một số thứ như rm -f * .o thành del * .o, những thứ như thế hoặc chỉ xây dựng một tệp bó từ các lệnh của trình biên dịch / trình biên dịch / trình liên kết trong tệp thực hiện.

Tôi rất khuyên bạn nên tháo rời nhị phân của mình, đặc biệt nếu bạn đang cố gắng đặt một trình xử lý trong bảng vectơ, với rất nhiều thứ rất dễ bị nhầm lẫn và không có nó ở đúng địa chỉ. Bạn cần biết địa chỉ từ các tài liệu cánh tay sau đó kiểm tra việc tháo gỡ. ví dụ blinker05 khi tháo rời:

 8000100:       0800014f        stmdaeq r0, {r0, r1, r2, r3, r6, r8}
 8000104:       0800014f        stmdaeq r0, {r0, r1, r2, r3, r6, r8}
 8000108:       08000179        stmdaeq r0, {r0, r3, r4, r5, r6, r8}
 800010c:       0800014f        stmdaeq r0, {r0, r1, r2, r3, r6, r8}
 8000110:       0800014f        stmdaeq r0, {r0, r1, r2, r3, r6, r8}

bù 0x108 là mục tiêu được nhắm mục tiêu. Lưu ý rằng các địa chỉ trong bảng phải là số lẻ 0x178 là địa chỉ thực tế, cánh tay muốn đặt lsbit để chỉ ra đó là địa chỉ tập lệnh ngón tay cái (cortex-m3 chỉ biết ngón tay cái và phần mở rộng ngón tay cái nó không thể thực hiện hướng dẫn cánh tay).

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.