STM32F1 interrupt

Started by tha, September 20, 2020, 08:55:49 AM

Previous topic - Next topic

tha

4.3 Nested vectored interrupt controller (NVIC)
section นี้อธิบาย the Nested Vectored Interrupt Controller (NVIC) และ the registers ที่ใช้. The NVIC รองรับ :
   • มีถึง 81 interrupts (ขึ้นอยู่กับชนิดของ the STM32 device type, ดูที่ the datasheets)
   • A programmable priority level(ระดับความสำคัญที่โปรแกรมได้) จาก 0-15 สำหรับแต่ละ interrupt. ระดับสูงจะมีความสำคัญที่ต่ำ
     (lower priority), ดังนั้นระดับ 0 (level 0) จะเป็นระดับความสำคัญที่สูงสุด (the highest interrupt priority)
   • Level and pulse detection of interrupt signals (การตรวจจับแบบระดับและพลัสของสัญญาน interrupt)
   • Dynamic reprioritization of interrupts (จัดระดับความสำคัญใหม่ของอินเตอรัพท์ได้แบบไดนามิก)
   • Grouping of priority values into group priority and subpriority fields (จัดกลุ่มค่าระดับความสำคัญได้เป็น group priority
      และ subpriority 
   • Interrupt tail-chaining
   • An external Non-maskable interrupt (NMI)
The processor จะ stacks สถานะของมันเมื่อเข้าสู่ exception และ unstacks สถานะนี้เมื่อออกจาก exception, ไม่มีคำสั่ง (instruction) เพิ่มมา. นี้ทำให้การจัดการ exception มีเวลาแฝงที่ต่ำ (low latency exception handling). hardware ที่มีให้ใช้งานของ the NVIC registers เป็นดังนี้:

tha

4.3.1 The CMSIS mapping of the Cortex®-M3 NVIC registers
เพื่อปรับปรุงประสิทธิภาพของซอฟต์แวร์ CMSIS ช่วยลดความยุ่งยากในการนำเสนอ NVIC register ใน CMSIS เป็นดังนี้:
   • The Set-enable, Clear-enable, Set-pending, Clear-pending and Active Bit registers map ถึง arrays of 32-bit
      integers, ดังนั้น:
      – The array ISER[0] to ISER[2] ตรงกันกับ the registers ISER0-ISER2
      – The array ICER[0] to ICER[2] ตรงกันกับ the registers ICER0-ICER2
      – The array ISPR[0] to ISPR[2] ตรงกันกับ to the registers ISPR0-ISPR2
      – The array ICPR[0] to ICPR[2] ตรงกันกับ the registers ICPR0-ICPR2
      – The array IABR[0] to IABR[2] ตรงกันกับ the registers IABR0-IABR2.
   • The 8-bit fields ของ the Interrupt Priority Registers map ถึง an array of 8-bit integers, ดังนั้น the array IP[0] to
   IP[67] ตรงกันกับ the registers IPR0-IPR67, และ the array entry IP[n] จะถือครอง the interrupt priority สำหรับ
   interrupt n.

The CMSIS จัดให้มี thread-safe code ที่ให้การเข้าถึง the Interrupt Priority Registers เป็นแบบอตอมมิก. สำหรับข้อมูลที่มากขึ้นดูที่ the description of the NVIC_SetPriority function in NVIC programming hints on page 127. ตาราง 41 แสดงให้เห็นว่า the interrupts เหล่านี้, หรือ IRQ numbers, map ไปยัง the interrupt registers และตรงกันกับ CMSIS variables ที่มีหนึ่งบิตต่อหนึ่ง interrupt อย่างไร.


1. แต่ละ array element จะตรงกันกับ NVIC register เดียว, ตัวอย่างเช่น the element ICER[1] จะตรงกันกับ the ICER1 register.

ปล. ดูที่ตาราง interrupt เลยนะ ดูที่ position ว่าแต่ละ position เป็น interrupt อะไร แล้วมาไล่ดู register กัน

tha



     Bits 31:0 SETENA[31:0]: Interrupt set-enable bits.
     Write(ถ้าเขียน):
     0: No effect   (ไม่มีผลอะไร)
     1: Enable interrupt  (เปิดการใช้งาน interrupt)
     Read(ถ้าอ่าน):
     0: Interrupt disabled     (ปิดการใช้งาน interrupt แล้ว)
     1: Interrupt enabled.     (เปิดการใช้งาน interrupt แล้ว)
ดูที่ Table 41: Mapping of interrupts to the interrupt variables ที่หน้า 119 สำหรับ interrupts ที่ตรงกันของแต่ละ register bit.

ถ้าบิต a pending interrupt ถูกทำให้ทำงานค้างไว้อยู่, the NVIC จะทำงาน the interrupt นั้นตามระดับความสำคัญของมัน. ถ้า an interrupt ไม่ถูกเปิดการใช้งาน, การยืนยัน interrupt signal ของมันจะเปลี่ยน the interrupt state เป็น pending, แต่ the NVIC จะไม่ทำงาน the interrupt นี้เลย, โดยไม่คำนึงถึงระดับความสำคัญของมันด้วย.

Quote
//----------------------------------------------------------------------------------------------------//
//------------------------------ Function NVIC Configuration -----------------------------------------//
//----------------------------------------------------------------------------------------------------//
void NVIC_setup()
{
   NVIC_InitTypeDef NVIC_InitStructure;

   // Configure one bit for preemption priority
   NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
   // Enable the EXTI0 Interrupt
   NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQChannel;
   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
   NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
   NVIC_Init(&NVIC_InitStructure);
   // Enable the EXTI13 Interrupt
   NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQChannel;
   NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
   NVIC_Init(&NVIC_InitStructure);
}
อย่างที่ NVIC เราก็มีการเลือกชาแนล แล้วทำการเซ็ต(ENABLE) บิตนั้น ใช่ไหม ท่านใดว่ามา


tha



Bits 31:0 CLRENA[31:0]: Interrupt clear-enable bits.
     Write(ถ้าเขียน):
     0: No effect               (ไม่มีผลอะไร)
     1: Disable interrupt    (ปิดการใช้งาน interrupt)
     Read(ถ้าอ่าน):
     0: Interrupt disabled      (ปิดการใช้งาน interrupt แล้ว)
     1: Interrupt enabled.     (เปิดการใช้งาน interrupt แล้ว)
ดูที่ Table 41: Mapping of interrupts to the interrupt variables ที่หน้า 119 สำหรับ interrupts ที่ตรงกันของแต่ละ register bit.

tha

4.3.4 Interrupt set-pending registers (NVIC_ISPRx)
     Address offset: 0x00 - 0x0B
     Reset value: 0x0000 0000
     Required privilege: Privileged
     The ISPR0-ISPR2 registers บังคับให้ interrupts อยู่ใน the pending state, และแสดง interrupts ไหน pending บ้าง.



     Bits 31:0 SETPEND[31:0]: Interrupt set-pending bits
     Write:
     0: No effect     (ไม่มีผลอะไร)
     1: Changes interrupt state to pending  (เปลี่ยน interrupt state ไปเป็น pending)
     Read:
     0: Interrupt is not pending  (อินเตอรัพท์ไม่ได้เกิดขึ้นค้างอยู่)
     1: Interrupt is pending        (อินเตอรัพท์เกิดขึ้นแล้วค้างอยู่)
ดูที่ Table 41: Mapping of interrupts to the interrupt variables ที่หน้า 119 สำหรับ interrupts ที่ตรงกันของแต่ละ register bit.
    การเขียน 1 ไปยัง the ISPR bit ที่ตรงกันกับ an interrupt ที่ค้างอยู่นั้น:
    – จะไม่มีผลอะไร.
    การเขียน 1 ไปยัง the ISPR bit ที่ตรงกันกับ an interrupt ที่ปิดการใช้งาน:
    – จะเซ็ตสถานะของ interrupt นั้นให้อยู่ในสถานะค้าง(pending).

tha

4.3.5 Interrupt clear-pending registers (NVIC_ICPRx)
     Address offset: 0x00 - 0x0B
     Reset value: 0x0000 0000
     Required privilege: Privileged
     The ICPR0-ICPR2 registers ถอน the pending state ออกจาก interrupts, และแสดง interrupts ไหน pending บ้าง



     Bits 31:0 CLRPEND[31:0]: Interrupt clear-pending bits
     Write:
     0: No effect      (ไม่มีผลอะไร)
     1: Removes the pending state of an interrupt  (ถอนสถานะการค้างของ interrupt นั้น)
     Read:
     0: Interrupt is not pending    (อินเตอรัพท์ไม่ได้เกิดขึ้นค้างอยู่)
     1: Interrupt is pending          (อินเตอรัพท์เกิดขึ้นแล้วค้างอยู่)
ดูที่ Table 41: Mapping of interrupts to the interrupt variables ที่หน้า 119 สำหรับ interrupts ที่ตรงกันของแต่ละ register bit.
การเขียน 1 ไปยัง an ICPR bit ไม่มีผลต่อสถานะการทำงานของ the corresponding(ที่ตรงกัน) interrupt นั้น.
(คือเมื่อมี interrupt request มาแล้ว pending bit จะเป็น 1 ค้างอยู่ Interrupt ก็ทำงานไป เราต้องทำการเคลียร์ pending bit ให้เป็น 0 โดยการเขียน 1 ไปยังบิตนี้ ตามที่อธิบาย เพื่อที่จะรอรับ interrupt request ในครั้งต่อไป)

Quote
//------------------------------------------------------------------------------------------------//
//---------------------------------- Function ISR line 0 -----------------------------------------//
//------------------------------------------------------------------------------------------------//
void EXTI0_IRQHandler(void)
{
  if(EXTI_GetITStatus(EXTI_Line0) != RESET)  // Ensure get EXTI line 0 pending bit
  {
    // Toggle PC6 pin
    GPIO_WriteBit(GPIOC, GPIO_Pin_6, (BitAction)((1-GPIO_ReadOutputDataBit(GPIOC, GPIO_Pin_6))));
    EXTI_ClearITPendingBit(EXTI_Line0);   // Clear the EXTI line 0 pending bit
  }
}
อย่างโปรแกรมย่อยบริการอินเตอร์รัพท์นี้ก็จะมีการเคลียร์ pending bit ก่อน เพื่อรอรับ interrupt request ในครั้งต่อไป
Quote
EXTI_ClearITPendingBit(EXTI_Line0);   // Clear the EXTI line 0 pending bit
ปล. ถ้า pending bit มันค้าง interrupt จะวนมาทำงานตลอดใช่หรือเปล่า ต้องทำการเคลียร์ pending bit ให้เป็น 0 ในโปรแกรมย่อยบริการอินเตอร์รัพท์ ไม่ให้มันค้าง ท่านใดบอกมา