Các trình xử lý ngắt được triển khai trong CMSIS của Cortex M0 như thế nào?


9

Tôi có một bộ LPC1114. Vài ngày qua tôi đã đào sâu triển khai CMSIS của Cortex M0 để tìm hiểu mọi thứ được thực hiện trong đó như thế nào. Cho đến nay tôi đã hiểu làm thế nào mỗi thanh ghi được ánh xạ và làm thế nào tôi có thể truy cập nó. Nhưng tôi vẫn không biết làm thế nào các ngắt được thực hiện trong đó. Tất cả những gì tôi biết về các ngắt trong CMSIS là có một số tên xử lý ngắt được đề cập trong tệp khởi động. Và tôi có thể viết các trình xử lý của riêng mình bằng cách viết một hàm C có cùng tên được đề cập trong tệp khởi động. Điều khiến tôi bối rối là trong hướng dẫn sử dụng, người ta nói rằng tất cả GPIO có thể được sử dụng làm nguồn ngắt ngoài. Nhưng chỉ có 4 ngắt PIO được đề cập trong tệp khởi động. Vậy nói với tôi:

  1. Làm cách nào tôi có thể triển khai các trình xử lý ngắt ngoài cho các GPIO khác?
  2. Bảng ngắt được ánh xạ trong CMSIS ở đâu?
  3. Sự khác biệt chính giữa NVIC và việc thực hiện ngắt trong các AVR / PIC là gì? (ngoại trừ NVIC có thể được ánh xạ ở bất cứ đâu trong flash)

Câu trả lời:


14

Các thông tin sau đây ngoài câu trả lời tuyệt vời của Igor.

Từ góc độ lập trình C, các trình xử lý ngắt được xác định trong tệp cr_startup_xxx.c (ví dụ: tệp cr_startup_lpc13.c cho LPC1343). Tất cả các trình xử lý ngắt có thể được xác định ở đó là bí danh WEAK. Nếu bạn không xác định XXX_Handler () của riêng mình cho nguồn ngắt, thì hàm xử lý ngắt mặc định được xác định trong tệp này sẽ được sử dụng. Trình liên kết sẽ sắp xếp hàm nào sẽ bao gồm trong nhị phân cuối cùng cùng với bảng vectơ ngắt từ cr_startup_xxx.c

Ví dụ về các ngắt GPIO từ các cổng được hiển thị trong các tệp demo trong gpio.c. Có một đầu vào ngắt cho cổng NVIC trên mỗi cổng GPIO. Mỗi bit riêng lẻ trong cổng có thể được bật / tắt để tạo ra một ngắt trên cổng đó. Nếu bạn yêu cầu ngắt trên các cổng PIO1_4 và PIO1_5 chẳng hạn, thì bạn sẽ kích hoạt các bit ngắt PIO1_4 và PIO1_5 riêng lẻ trong GPIO0IE. Khi chức năng xử lý ngắt PIOINT0_Handler () của bạn kích hoạt, bạn phải xác định ngắt PIO1_4 hoặc PIO1_5 (hoặc cả hai) đang chờ xử lý bằng cách đọc thanh ghi GPIO0RIS và xử lý ngắt một cách thích hợp.


10

(Xin lưu ý rằng điểm 1 và 2 là chi tiết triển khai và không giới hạn kiến ​​trúc.)

  1. Trong các chip NXP lớn hơn (như LPC17xx), có một vài chân ngắt chuyên dụng (EINTn) có bộ xử lý ngắt riêng. Phần còn lại của GPIO phải sử dụng một ngắt chung (EINT3). Sau đó, bạn có thể thăm dò thanh ghi trạng thái ngắt để xem chân nào đã kích hoạt ngắt.
  2. Tôi không quen thuộc lắm với LPC11xx nhưng có vẻ như nó có một ngắt trên mỗi cổng GPIO. Bạn một lần nữa sẽ phải kiểm tra thanh ghi trạng thái để tìm ra các chân cụ thể. Ngoài ra còn có tới 12 chân có thể đóng vai trò là nguồn thức dậy. Tôi không chắc liệu bạn có thể chiếm quyền điều khiển chúng dưới dạng các ngắt chung hay không (nghĩa là chúng có thể sẽ chỉ được kích hoạt khi ở trạng thái ngủ).
  3. Bảng xử lý mặc định được đặt tại địa chỉ 0 (trong flash). Mục nhập đầu tiên là giá trị đặt lại cho thanh ghi SP, thứ hai là vectơ thiết lập lại và phần còn lại là các ngoại lệ và vectơ ngắt khác. Một vài trong số những cái đầu tiên (như NMI và HardFault) được ARM cố định, phần còn lại là dành riêng cho chip. Nếu bạn cần thay đổi các vectơ khi chạy, bạn có thể sắp xếp lại nó vào RAM (trước tiên bạn cần sao chép bảng). Trong LPC11xx, ánh xạ lại được cố định vào đầu SRAM (0x10000000), các chip khác có thể linh hoạt hơn.
  4. NVIC được tối ưu hóa để xử lý ngắt hiệu quả:
    • mức độ ưu tiên lập trình 0-3 cho mỗi ngắt. Ngắt ưu tiên cao hơn thử trước các ưu tiên thấp hơn (lồng nhau). Việc thực hiện mức ưu tiên thấp hơn sẽ tiếp tục khi ngắt ưu tiên cao hơn kết thúc.
    • tự động xếp chồng trạng thái bộ xử lý khi vào ngắt; điều này cho phép viết các trình xử lý ngắt trực tiếp trong C và loại bỏ sự cần thiết của các trình bao bọc lắp ráp.
    • nối đuôi: thay vì bật và đẩy trạng thái một lần nữa, ngắt đang chờ xử lý tiếp theo được xử lý ngay lập tức
    • đến muộn: nếu ngắt ưu tiên cao hơn đến trong khi sắp xếp trạng thái bộ xử lý, nó sẽ được thực thi ngay lập tức thay vì trạng thái chờ xử lý trước đó.

Vì bạn đã quen thuộc với PIC, hãy xem Ứng dụng này Lưu ý: Di chuyển từ Vi điều khiển PIC sang Cortex-M3

Đó là về M3, nhưng hầu hết các điểm cũng áp dụng cho M0.


8

Câu trả lời của Austin và Igor đủ chi tiết. Tuy nhiên, tôi muốn trả lời nó theo cách khác, có thể bạn thấy nó hữu ích.

LPC11xx (Cortex-M0) có 4 cấp độ cho các chân GPIO, tất cả các chân từ GPIO0.0 đến GPIO0.n đều có chung số ngắt và tất cả các chân từ GPIO3.0 đến GPIO3.m đều có chung số ngắt.

Có sáu bước để khởi tạo ngắt GPIO trong LPC11xx

  1. Thiết lập chức năng ghim bằng cách sửa đổi các thanh ghi khối kết nối pin.
  2. Thiết lập hướng pin bằng cách sửa đổi thanh ghi hướng dữ liệu GPIO (giá trị mặc định là đầu vào).
  3. Thiết lập ngắt cho từng pin riêng lẻ, bạn phải truy cập GPIOnIE thanh ghi mặt nạ ngắt GPIO và đặt bit (tương ứng với chân) logic 1.
  4. Thiết lập ngắt cho cạnh tăng hoặc cạnh giảm hoặc cả hai bằng cách sửa đổi các thanh ghi cảm giác ngắt GPIO GPIOnIBE và GPIOnIS.
  5. Cho phép nguồn ngắt hoặc PIO_0 / PIO_1 / PIO_2 / PIO_3 trong Điều khiển ngắt được lồng vào nhau bằng các hàm CMSIS.
  6. Đặt mức độ ưu tiên ngắt bằng cách sử dụng các hàm CMSIS.

Thực thi mã. Bạn cần hai chức năng: một khởi tạo 6 bước trên và thứ hai là trình xử lý ngắt, được yêu cầu phải có cùng tên với trình xử lý được xác định trong mã khởi động, startup_LPC11xx.stệp. Các tên là từ PIOINT0_IRQHandlerđến PIOINT3_IRQHandler. Nếu bạn sử dụng tên khác, bạn phải thay đổi tên trong tệp khởi động.

/*Init the GPIO pin for interrupt control */
void GPIO_Init(){
    LPC_IOCON-> =..              //Pin configuration register
    LPC_GPIO1->FIODIR = ...      //GPIO Data direction register
    LPC_GPIO1->FIOMASK = ..      //GPIO Data mask register - choose  the right pin
    LPC_GPIO1->GPIOnIE = ..      //Set up falling or rising edge 
    NVIC_EnableIRQ(PIO_1);       //Call API to enable interrupt in NVIC
    NVIC_SetPriority(PriorityN); //Set priority if needed
}


/*Must have the same name as listed in start-up file startup_LPC11xx.s */
void PIOINT1_IRQHandler(void){
   //Do something here
}
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.