설정은 이전 글에서 이어진다.
2022.09.07 - [DSP, MCU/TMS320F2838x (C28x)] - TMS320F28388D ] SCI (UART) 통신하기 - 송신
interrupt를 수행하는 함수를 Interrupt Handler 또는 ISR (Interrupt Service Routine) 이라고 표현한다.
그리고 핸들러 함수를 만들때는 앞에 __interrupt 키워드를 붙여 complier 가 이게 interrupt handler 라는 것을 알게 한다.
예시)
__interrupt void int_handler()
{
unsigned int flags;
...
}
Handling Interrupt에 대한 설명은 Technical Reference Manual 145페이지 부터 매우 자세히 설명되어있다. 그리고 __interrupt Keyword 에 대해 더 알고 싶다면 Optimizing C/C++ Complier 109페이지에 설명이 나와있다.
아무튼 아래의 코드는 Technical Reference Manual 148페이지에 나와있는 절차를 따른 코드이다.
//
// Interrupt Handler
//
// 핸들러 함수 원형 선언
__interrupt void sciaRXFIFOISR(void);
uint16_t receivedChar;
uint16_t rxStatus = 0U;
//
// Main
//
void main(void)
{
//
// Initializes system control, device clock, and peripherals
//
Device_init();
//
// Initializes PIE and clear PIE registers. Disables CPU interrupts.
// and clear all CPU interrupt flags.
//
Interrupt_initModule();
//
// Initialize the PIE vector table with pointers to the shell interrupt
// Service Routines (ISR).
//
Interrupt_initVectorTable();
// PIE vector init 과 Board init 사이에 아래 문구 추가
// register handler and enable interrupt
Interrupt_register(INT_SCIA_RX, sciaRXFIFOISR);
Interrupt_enable(INT_SCIA_RX);
// Issue PIE Ack 굳이 할필요는 없는거 같은데 안전빵코드
Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP9);
//
// Board Initialization
//
Board_init();
//
// Enables CPU interrupts
//
Interrupt_enableMaster();
//
// Loop.
//
for(;;);
}
//
// sciaRXFIFOISR - SCIA Receive FIFO ISR
//
__interrupt void sciaRXFIFOISR(void)
{
//
// Read a character from the FIFO.
//
receivedChar = SCI_readCharBlockingFIFO(SCIA_BASE);
rxStatus = SCI_getRxStatus(SCIA_BASE);
if((rxStatus & SCI_RXSTATUS_ERROR) != 0)
{
//
//If Execution stops here there is some error
//Analyze SCI_getRxStatus() API return value
//
ESTOP0;
}
//
// Echo back the character.
//
SCI_writeCharBlockingFIFO(SCIA_BASE, receivedChar);
SCI_clearOverflowStatus(SCIA_BASE);
//
SCI_clearInterruptStatus(SCIA_BASE, SCI_INT_RXFF);
//
// Issue PIE ack
//
Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP9);
}
핸들러 함수를 정의하고 해야할 일은 PIE Interrupt Vectors 에 ISR의 위치(함수의 주소값)를 알려주는 일이다.
CPU가 평상시 하던일을 하다가 인터럽트가 걸리면 ISR로 점프하여 함수를 실행하는 데 그 점프해야하는 주소가 PIE Vector table의 address에 저장이 된다.
주소를 지정하는 일은 위 코드처럼 Interrupt_register(INT_SCIA_RX, sciaRXFIFOISR); 함수를 사용하면 되고 첫번째 매개변수가 hw_ints.h 에 정의된 PIE Interrupt Numbers 두번째 매개변수가 내가 만든 핸들러 함수명이다.
그리고 매뉴얼 설명에 나와있듯이 ISR 끝부분에서 Interrupt_clearACKGroup(INTERRUPT_ACK_GROUPx); 함수를 호출해서 PIEACK bit 를 clear 해주어야 한다.
에코백 테스트
참고.
SCI_readChar 함수는 4종류가 있고 다음과 같은 특징을 가지고 있다.
SCI_readCharBlockingFIFO(uint32_t base);
//! Gets a character from the receive FIFO for the specified port. If there
//! are no characters available, this function waits until a character is
//! received before returning. Returns immediately in case of Error.
SCI_readCharBlockingNonFIFO(uint32_t base);
//! Gets a character from the receive buffer for the specified port. If there
//! is no characters available, this function waits until a character is
//! received before returning.
SCI_readCharNonBlocking(uint32_t base);
//! Gets a character from the receive buffer for the specified port. This
//! function does not block and only reads the receive buffer. The user should
//! use SCI_isDataAvailableNonFIFO() or SCI_getRxFIFOStatus() to determine if
//! the receive buffer or FIFO have data available.
SCI_readCharArray(uint32_t base, uint16_t * const array, uint16_t length);
//! Receives an array of characters from the receive buffer for the specified
//! port, and stores them as an array of characters starting at address
//! \e array. This function waits until the \e length number of characters are
//! received before returning.
'임베디드 개발 > TMS320F2838x (C28x)' 카테고리의 다른 글
TMS320F28388D ] Watch Expressions (Continuous Refresh) (0) | 2022.09.10 |
---|---|
TMS320F28388D ] External Interrupt 외부 인터럽트 (5) | 2022.09.08 |
TMS320F28388D ] SCI (UART) 통신하기 - 송신 (0) | 2022.09.07 |
TMS320F28388D ] 프로젝트 복사하기 (0) | 2022.09.07 |
TMS320F2838x ] PIE Vector Table (0) | 2022.09.07 |