이 블로그 검색

2011년 12월 16일 금요일

인터럽트(BF506F)

블랙핀은 2 레벨의 인터럽트를 처리과정을 따른다.



Core event controller(CEC)와 System interrupt controller(SIC)이다.

CEC는 CCLK 클록영역에서 동작하며,프로그램 시퀀서와 밀접하게 상호동작하
고, 이벤트 벡터 테이블(EVT)을 관리한다. 또한, Core와 관련된 인터럽트들 즉, 예외, Core 에러 그리고 emulation events 뿐만아니라 소프트웨어 인터럽트들도 지원한다.

SIC는 SCLK 클록영역에서 동작하며, 칩내부 또는 외부의 주변장치에 의해서 알려지
는 인터럽트 요구들을 masking, grouping, 그리고 우선순위를 결정하고, CEC로 전송
한다.


프로세서의 CEC는 5가지 종류의 활동과 이벤트를 처리한다.

1) Emulation
2) Reset
3) NMI :
NMI event는 software watchdog timer에 의해서 발생될 수도 있고, _NMI pin, 또는
software에 의해서 발생될 수 있다. 일반적으로 NMI event는 system의 shutdown을 순
서대로 수행하기 위한 power-down indicator로 사용된다.
4) Exceptions :
software에 의해서 초기화된 event로서 program flow에 동기적으로 발생하는 events.
예) data alignment violations, undefined instructions, etc.
5) Interrupts :
program flow에 비동기적으로 발생하는 events. 이들은 timers 그리고 다른 주변장치들
의 입력 신호들에 의해서 발생하거나 명확한 software 명령에 의해서 발생한다.
각각의 event type은 return address를 유지하기 위한 관련된 register와 관련된
return-from-event instruction을 가지고 있다. Event가 발생하면, ISR은 supervisor
stack에 processor의 상태를 저장해야 한다.

여기에서 Event는 위의 5가지를 말하며 CEC는 좀더 엄밀히 말해서 15개의 확장된 이벤트들를 처리하는데 아래 테이블을 참조하라.




CEC는 전용 interrupt와 exception events외에 9개의 general-purpose
interrupts(IVG15-7)를 지원한다. 이들 general-purpose interrupts 중에서 2개의 가장
우선 순위가 낮은 interrupts(IVG15-14)는 software interrupt handlers로 사용되는 것
이 좋다.

위에서 SIC에 대해서 간략히 설명했지만 좀더 자세히 다루어 보자

SIC는 많은 주변장치 인터럽트들로 부터 우선권을 갖는 CEC의 general-purpose
interrupt inputs(IVG7-15)로 이벤트들의 연결을 라우팅할수 있는 기능을 제공한다. 비록 프로세서가 기본적으로 Mapping된 연결을 제공하지만 사용자는 interrupt assignment register(SIC_IARx)를 통해 인터럽트의 Mapping과 우선권을 변경할수 있다. 주변장치들에서 발생한 인터럽트들은 SIC로 들어가고, 이어서 직접 CEC의general-purpose interrupts로 들어간다.

SIC_IAR registers안에 interrupt 할당은 peripheral interrupts를 grouping할 뿐만 아니라,
개별적으로 IVG channel에 할당하여 우선권을 부여할 수 있다. 만일, 한 개의 interrupt
source 이상이 동일한 interrupt에 mapping된다면, 이들은 hardware 적인 우선권이 없이
단순히, 논리적으로 ORing되며, software가 interrupt 처리에 대한 우선권을 부여해 주어야
한다.
리셋을 하면, SIC_IMASK register의 내용은 모든 peripheral interrupts를 mask off 하기
위해서 “0”이 된다. 이제, 특정 interrupt를 enabling하는 것은 SIC_IMASK register 의 해당비트를 1로 세팅함으로 이루어 진다.

SIC는 peripheral interrupt sources 중에서 어느 하나의 interrupt 상태에 대응하는 개별적
인 bits를 포함하는 하나 또는 그 이상의 read-only SIC_ISR registers를 가지고 있다. 즉,
SIC가 interrupt를 검출할 때, 그 bit는 asserting되고, deasserting된 것을 검출할 때는 대
응하는 bits가 clearing된다.
Peripheral DMA channels는 peripheral interrupt IDs에 고정된 방법으로 mapping된다. 그
러나, peripherals와 DMA channels 사이의 할당은 DMA_PERIPHERAL _MAP registers로
자유롭게 programming될 수 있다. 일단, 임의의 peripheral이 임의의 다른 DMA channel에
할당되면, 그것은 DMA가 enabling 된 것과 상관없이 새로운 DMA channel's interrupt를
이용한다. 그러므로, DMA가 사용되지 않는다고 하더라도, DMA_PERIPHERAL_MAP은
clearing 제대로 관리되어야 한다. 만일, non-DMA applications만 사용할 것이라면, default
setup을 사용하는 것이 제일 좋다.
만일, 동적으로 power를 관리하고 싶다면, 임의의 peripherals가 core를 idle 상태에서
interrupt를 처리하는 상태로 wake up하도록 수어될 수 있는데, 이것은 단순히 SIC_IWR
register안에 있는 적절한 bit를 enabling하면 된다. 즉, 임의의 peripheral interrupt source
가 SIC_IWR안에서 enabling되어 있고, core idle 상태에 있다면, core가 interrupt를 처리할
수 있도록 일련의 과정을 따르도록 한다. 그러나, 이 mode를 이용하는 경우에는 interrupt
processing에 약간의 latency가 추가되는 데 주의하자.
정리하면, SIC_IWR register는 core가 idle 상태에 있을 때만 효과를 가진다는 데 주의하자.
그리고, 모든 interrupt가 disabling 되어 있을 때에 이 register에 어떠한 writing operation
을 수행해야 한다.
wakeup 기능은 interrupt mask 기능과는 다른 것이다. 만일, 어떠한 interrupt source가
SIC_IWR안에서 enabling되어 있고, SIC_IMASK register에서 mask off되어 있다면, idle 상
태에서 께어나기는 하지만, interrupt는 발생하지 않는데 주의하자. 결국, core에 interrupt는
발생하지 않지만, core를 깨우는 동작만 하게 되는 셈이다.



임의의 interrupt(즉, interrupt A)가 interrupt-enabled peripheral에 의해서
생성된 경우이다. 각각의 register에 대해서 간단히, 정리하면 다음과 같다.

1) SIC_ISR :
SIC_ISR은 request를 반영하고, asserting된 system interrupts의 track을 유지하지만, 아
직, servicing되지는 않았다.
2) SIC_IWR :
SIC_IWR은 발생한 interrupt request에 근거하여 idle 상태에 있는 core를 깨워야 하는지
check한다.
3) SIC_IMASK :
SIC_IMASK는 system level에서 peripherals로부터 interrupts를 enabling하거나 mask
off한다.
4) SIC_IAR :
SIC_IAR은 그 peripheral interrupts를 general-purpose core interrupts(IVG7-IVG15)
에 mapping하여 interrupt A의 core priority를 결정한다. 즉, 각각의 peripheral
interrupt ID를 대응하는 IVG priority level에 mapping한다. 이것은 4-bit grouping이
IVG levels로 translation되는 것을 의미한다.
5) ILAT :
ILAT는 interrupt A를 core에 의해서 latch되는 interrupts에 등록하지만, 아직도
servicing은 되지 않고 있다.
6) IMASK :
서로 다른 core 우선권들을 가지는 events를 enabling하거나 mask off한다. 만일,
interrupt A에 해당하는 IVGx event가 mask되지 않았다면, 7)번 단계로 수행한다.
7) EVT(Event Vector Table) :
EVT는 interrupt A의 ISR을 위한 적절한 vector를 찾기 위해서 접근된다.
8) IPEND :
interrupt A를 위한 event vector가 core pipeline으로 진입할 때, 적절한 IPEND bit가
set되고, 그것은 각각의 ILAT bit를 clear 해 준다. 그러므로, IPEND는 ISR을 servicing
해 줄뿐만 아니라 모든 pending interrupts를 추적한다.
9) RTI(Return From Interrupt) :
interrupt A를 위한 ISR이 실행 될 때, RTI는 적절히 IPEND bit를 clearing해 주어서 또
다른 interrupt를 받아 들일 수 있도록 해 준다. 그러나, ISR이 interrupt A를 생성한
mechanism을 clearing해 주지 않는다면, 계속해서 해당 peripheral로부터 interrupt가 들
어오므로 SIC_ISR은 clearing되지 않는다.





위의 그림은 어떻게 7개의 SIC_IAR registers가 9개의 사용할 수 있는 CEC의
peripheral request inputs에 할당하는 것을 제어하는 지 보여주고 있다.
여기서 주의할 것은 어떠한 interrupt를 받아들인 것에 대한 인정(acknowledge)
mechanism이 없다는 것이다.

EVT레지스터는 인터럽트 벡터그룹에 대응하는 서비스루틴 어드레스를 가진다.
우리는 이 레지스터에 인터럽트 서비스 루틴의 함수 어드레스를 포인팅함으로서 인터럽트를 처리할수 있다.

아래는 general purposed timer의 인터럽트 설정 이다.
이 세팅을 보면 Timer 6이 사용됨을 알수 있다.

register_handler(ik_ivg11,GPTimer_ISR);
    - 이 부분이 IVG11 그룹에 EVT[11]에 GPTimer_ISR함수 어드레스를 설정하는 함수 이다.
 *pSIC_IAR4   &= 0xF0FFFFFF;
 *pSIC_IAR4   |= 0x04000000;   // 


    - 해당 SIC-IARx을 찾아 4를 세팅하여 IVG11을 사용을 설정한다.
/*
  IVG7------0  IVG11------4
  IVG8------1  IVG12------5
  IVG9------2  IVG13------6
  IVG10-----3  IVG14------7
      IVG15------8
 */

 *pSIC_IMASK1|= 0x00000040; 
   - 해당 SIC-IMASKx 을 찾아 4를 세팅하여 SIC인터럽트를 CEC로 넘겨준다.


typedef void (*ex_handler_fn)();
#define EX_HANDLER(KIND,NAME) \
_Pragma(#KIND) \
void NAME (void)

#define EX_HANDLER_PROTO(KIND, NAME) EX_HANDLER(KIND, NAME)
#define EX_INTERRUPT_HANDLER(NAME) EX_HANDLER(interrupt,NAME)
#define EX_EXCEPTION_HANDLER(NAME) EX_HANDLER(exception,NAME)
#define EX_NMI_HANDLER(NAME)  EX_HANDLER(nmi,NAME)

#define EX_REENTRANT_HANDLER(NAME) \
_Pragma("interrupt_reentrant") \
EX_HANDLER(interrupt,NAME)

ex_handler_fn register_handler(interrupt_kind int_kind, ex_handler_fn handler);

register_handler :
- 기능 설명 :
이 함수는 event handler를 등록해 준다.
이 함수는 어떻게 hardware event kind가 처리될지를 결정한다. 이것은 그 event를 위한
handler로서 fn 에 의해서 지적된 함수를 등록함에 의해서 그리고, interrupt가 실행수 있
도록 IMASK register를 갱신한다.
register_handler_ex 함수는 register_handler보다 확장되고, 더 기능이 많은 interface를
제공한다.

EX_INTERRUPT_HANDLER(GPTimer_ISR)
{
 *pTIMER_STATUS= TIMIL6;//w1c , Timer6 Interrupt, indicates an interrupt request when   IRQ_ENA is set.
}

위의 함수가 인터럽트 서비스 루틴이다. 위의 매크로들을 참조하기 바란다.

댓글 없음:

댓글 쓰기