STM32 인터럽트 벡터표의 내용을 바꾸는 대신코드
10539 단어 코드 세그먼트
우리는 인터럽트 서비스 함수부터 시작해서 코드에 인터럽트 벡터를 어떻게 배치하는지 살펴보자.
ISR(USART2_IRQn)
{
uint8 data;
uint32 _if=USART2->ISR;
잘못 보지 않았습니다. 이것이 바로 서비스 중단 함수의 이름입니다.이 ISR가 뭔지 추적해 봅시다.헤더 파일에는 다음과 같은 정의가 있다.보시면 ISR(USART2 IRQn)는void ISR 와 같습니다.NAME(USART2_IRQn)(void),ISR_NAME는 과 동일합니다.ISR_NAME,__ISR_NAME는 과 동일합니다.ISR_##A.이것이 마지막 매크로 정의입니다. 매크로를 연결하는 것입니다.
#ifndef ISR_NAME
#define ISR_NAME(A) __ISR_NAME(A)
#define __ISR_NAME(A) __ISR_##A
#endif
#ifndef ISR_Extern
#define ISR_Extern(A) ISR(A)
#endif
#ifndef ISR_Implement
#define ISR_Implement(A) ISR(A)
#endif
#ifndef ISR_Define
#define ISR_Define(A) ISR(A)
#endif
#ifndef ISR
#define ISR(A) void ISR_NAME(A)(void)
#endif
층층이 거대한 정의를 통해ISR(USART2 IRQn)은voidISR_USART2_IRQn(void).STM32를 자주 사용하는 우리는 직렬 인터럽트 함수는 일반적으로 이 USART2 라는 것을 안다IRQHandler, 위에 그게 아니에요.그럼 서비스 중단 함수에서 위에 있는 함수를 호출한 거 아닐까요?나는 전체 프로젝트 범위 내에서 USART2를 검색했다.IRQHandler, 이 함수를 찾을 수 없습니다.
프로젝트 파일에서 한 차례의 검색을 거쳐 나는 문제의 답안을 찾았다.나는 원본 파일에서 이러한 그룹의 정의를 찾았다.root는 이 그룹이 다른 파일에 사용되었든 안 사용되었든 간에 컴파일러가 컴파일된 파일에 강제로 컴파일된다는 뜻입니다. @". intvec"는 컴파일러에게 이 그룹을 컴파일해서. intvec 섹션에 놓는 것을 알려 줍니다. 이. intvec 섹션은 인터럽트 벡터표가 저장된 곳을 인터럽트 벡터로 덮어쓰는 것입니다. 이 섹션에는 인터럽트 벡터표가 층층이 정의되어 있습니다.
__root const intvec_elem __vector_table[] @".intvec"=
{
//======================================================================
// CM3 / ( )
ISR_VAL_2_15_FILL_IN_VECT_TAB(_Deault_Handler),
//======================================================================
// ,
[0].ptr = (uint32)__sfe( "CSTACK" ) - 32 ,
[1].handler = __iar_program_start,
//CM3 /
ISR_VAL_IN_VECT_TAB(NonMaskableInt_IRQn,_Deault_Handler),
//ISR_VAL_IN_VECT_TAB(HardFault_IRQn,_Deault_Handler),
ISR_VAL_IN_VECT_TAB(MemoryManagement_IRQn,_Deault_Handler),
ISR_VAL_IN_VECT_TAB(BusFault_IRQn,_Deault_Handler),
ISR_VAL_IN_VECT_TAB(UsageFault_IRQn,_Deault_Handler),
ISR_VAL_IN_VECT_TAB(SVCall_IRQn,_Deault_Handler),
ISR_VAL_IN_VECT_TAB(DebugMonitor_IRQn,_Deault_Handler),
ISR_VAL_IN_VECT_TAB(PendSV_IRQn,ISR_NAME(PendSV_IRQn)),
ISR_VAL_IN_VECT_TAB(SysTick_IRQn,ISR_NAME(SysTick_IRQn)),
//==============================================================================
//
#if defined(STM32F10X_LD) //0-42
ISR_VAL_FILL_43_IN_VECT_TAB(_Deault_Handler),
#elif defined(STM32F10X_LD_VL) //0-55
ISR_VAL_FILL_56_IN_VECT_TAB(_Deault_Handler),
#elif defined(STM32F10X_MD) //0-42
ISR_VAL_FILL_43_IN_VECT_TAB(_Deault_Handler),
#elif defined(STM32F10X_MD_VL) //0-55
ISR_VAL_FILL_56_IN_VECT_TAB(_Deault_Handler),
#elif defined(STM32F10X_HD) //0-59
ISR_VAL_FILL_60_IN_VECT_TAB(_Deault_Handler),
#elif defined(STM32F10X_HD_VL) //0-60
ISR_VAL_FILL_61_IN_VECT_TAB(_Deault_Handler),
#elif defined(STM32F10X_XL) //0-59
ISR_VAL_FILL_60_IN_VECT_TAB(_Deault_Handler),
#elif defined(STM32F10X_CL) //0-67
ISR_VAL_FILL_68_IN_VECT_TAB(_Deault_Handler),
#else
#warning "unkown type!"
#endif
//======================================================================
//STM32
ISR_IN_VECT_TAB(USART1_IRQn),
ISR_IN_VECT_TAB(USART2_IRQn),
ISR_IN_VECT_TAB(TIM3_IRQn),
// ISR_IN_VECT_TAB(USB_HP_CAN1_TX_IRQn),
// ISR_IN_VECT_TAB(USB_LP_CAN1_RX0_IRQn),
// ISR_IN_VECT_TAB(SDIO_IRQn),
// ISR_IN_VECT_TAB(SD_SDIO_DMA_IRQn),
// ISR_IN_VECT_TAB(USBWakeUp_IRQn),
};
우선 수조의 유형을 살펴보자.intvec_elem.연합체 유형은 함수 바늘일 수도 있고 32자리의 성형수일 수도 있다.함수 포인터의 유형을 볼 수 있습니다. 서비스 중단 함수와 마찬가지로 매개 변수가 없고 되돌아오지 않습니다.
typedef void ( vector_handler_t )( void );
typedef union { vector_handler_t * handler; uint32 ptr; } intvec_elem;
우리는 수조에 이런 두 마디가 있다는 것을 볼 수 있는데 이것은 우리가 M3 내핵에 대한 인식에 부합된다.벡터 테이블 앞의 네 바이트는 창고 끝 주소입니다.sfe는 IAR의 어셈블리 문법으로 CSTACK 단락의 마지막 주소로 가는 것을 의미한다.벡터 테이블에 이어서 저장된 것은 벡터를 복원하는 주소이다.여기 코드가 라고 적혀있어요.iar_program_start 이건 IAR와 관련이 있을 거예요. 추적이 안 돼요.
//======================================================================
// ,
[0].ptr = (uint32)__sfe( "CSTACK" ) - 32 ,
[1].handler = __iar_program_start,
우리는 이어서 수조 안의 매크로 정의를 보았다.일단 ISR...VAL_2_15_FILL_IN_VECT_TAB
// CM3 / ( )
ISR_VAL_2_15_FILL_IN_VECT_TAB(_Deault_Handler),
매크로 정의는 다음과 같습니다.
#define ISR_VAL_2_15_FILL_IN_VECT_TAB(A)\
[2].handler = A,\
[3].handler = A,\
[4].handler = A,\
[5].handler = A,\
[6].handler = A,\
[7].handler = A,\
[8].handler = A,\
[9].handler = A,\
[10].handler = A,\
[11].handler = A,\
[12].handler = A,\
[13].handler = A,\
[14].handler = A,\
[15].handler = A
수조에 이런 조작이 있을 수 있다???나도 놀랐다. 네가 아래와 같이 수조를 정의하는 것과 같다.소동 조작은 여태껏 만난 적이 없다.
typedef union{
uint32_t reg;
uint8_t buff[4];
}un_test_t;
un_test_t test[] = {
[0].reg = 0,
[1].reg = 1,
};
_Deault_Handler의 정의는 다음과 같다. 디버깅을 할 때 창고와 레지스터의 수요를 고려해야 한다.보아하니 대신이 M3 내핵 처리 함수를 뛰어넘을 때 창고의 조작을 손금 보듯 잘 알고 있어 탄복하고 탄복한다
#if VECT_DEBUG==1
typedef struct
{
uint32 _r0;
uint32 _r1;
uint32 _r2;
uint32 _r3;
uint32 _r12;
uint32 _lr;
uint32 _pc;
uint32 _xpsr;
}__irq_reg_t;
__root volatile __irq_reg_t __irq_reg;
#endif
#define _Deault_Handler ((void (*)(void))&__Deault_Handler)
__task void __Deault_Handler(void)
{
#if VECT_DEBUG==1
uint32 *sp=(uint32 *)__get_MSP();
for(int i=0;i
전면 ISRVAL_2_15_FILL_IN_VECT_TAB 이 매크로는defaulthandler.startup을 뒤져서 기본 인터럽트 벡터표를 보면 2에서 15가 시스템 인터럽트 벡터라는 것을 알 수 있습니다.
다시 데이터 속의 매크로를 내려다보면 또 하나의 끼워 넣은 매크로가 나를 너무 피곤하게 본다.Bus Falut 같은...IRQn, 브레이크 벡터 번호,
//CM3 /
ISR_VAL_IN_VECT_TAB(NonMaskableInt_IRQn,_Deault_Handler),
//ISR_VAL_IN_VECT_TAB(HardFault_IRQn,_Deault_Handler),
ISR_VAL_IN_VECT_TAB(MemoryManagement_IRQn,_Deault_Handler),
ISR_VAL_IN_VECT_TAB(BusFault_IRQn,_Deault_Handler),
ISR_VAL_IN_VECT_TAB(UsageFault_IRQn,_Deault_Handler),
ISR_VAL_IN_VECT_TAB(SVCall_IRQn,_Deault_Handler),
ISR_VAL_IN_VECT_TAB(DebugMonitor_IRQn,_Deault_Handler),
ISR_VAL_IN_VECT_TAB(PendSV_IRQn,ISR_NAME(PendSV_IRQn)),
ISR_VAL_IN_VECT_TAB(SysTick_IRQn,ISR_NAME(SysTick_IRQn)),
#define ISR_IN_VECT_N16_TAB(A) [(A)+16].handler = ISR_NAME(A)
#define ISR_VAL_IN_VECT_N16_TAB(A,B) [(A)+16].handler = B
#define ISR_IN_VECT_TAB(A) ISR_IN_VECT_N16_TAB(A)
#define ISR_VAL_IN_VECT_TAB(A,B) ISR_VAL_IN_VECT_N16_TAB(A,B)
우리는 M3 내핵의 중단 벡터 번호의 마이너스를 한 부 붙여서 보면 다음과 같다.매크로에 16을 추가했기 때문에 이 부분의 내부 핵 단계의 중단은 중단 벡터표에 정확하게 넣을 수 있다.NonMaskableInt_IRQn에 16을 더하면 2가 된다.
typedef enum IRQn
{
/****** Cortex-M3 Processor Exceptions Numbers ***************************************************/
NonMaskableInt_IRQn = -14, /*!< 2 Non Maskable Interrupt */
MemoryManagement_IRQn = -12, /*!< 4 Cortex-M3 Memory Management Interrupt */
BusFault_IRQn = -11, /*!< 5 Cortex-M3 Bus Fault Interrupt */
UsageFault_IRQn = -10, /*!< 6 Cortex-M3 Usage Fault Interrupt */
SVCall_IRQn = -5, /*!< 11 Cortex-M3 SV Call Interrupt */
DebugMonitor_IRQn = -4, /*!< 12 Cortex-M3 Debug Monitor Interrupt */
PendSV_IRQn = -2, /*!< 14 Cortex-M3 Pend SV Interrupt */
SysTick_IRQn = -1, /*!< 15 Cortex-M3 System Tick Interrupt */
/****** STM32 specific Interrupt Numbers *********************************************************/
WWDG_IRQn = 0, /*!< Window WatchDog Interrupt */
PVD_IRQn = 1, /*!< PVD through EXTI Line detection Interrupt */
TAMPER_IRQn = 2, /*!< Tamper Interrupt
잠깐만, 방금 우리 ISRVAL_2_15_FILL_IN_VECT_TAB 홍리, 2에서 15에 값을 매겼잖아. 어떻게 여기서 2에서 15의 내용에 값을 매길 수 있겠어. 아래와 같고 수조에 이런 조작이 있을 수 있잖아.나는 정말 탄복한다. 지금까지 이런 수조의 정의를 본 적이 없다.
typedef union{
uint32_t reg;
uint8_t buff[4];
}un_test_t;
un_test_t test[] = {
[0].reg = 0,
[0].reg = 1,
};
그 다음에 MCU의 용량에 따라 조건컴파일을 했습니다. 그중 하나를 보겠습니다.
ISR_VAL_FILL_43_IN_VECT_TAB(_Deault_Handler),
추적해 보면 이 단락이 비교적 길어서 나는 몇 마디만 붙이면 된다.내가 눈을 좀 비비면 눈이 좀 침침해진다.사십삼은 사십삼과 사십이를 정의했고, 사십이는 사십이와 사십일을 정의했다...접룡이요...위와 같이 수조 인덱스를 통해 수조의 구성원을 정의하는 것이 아니라 정의값을 직접 쓰는 것이다.
#define ISR_VAL_FILL_43_IN_VECT_TAB(A) A,ISR_VAL_FILL_42_IN_VECT_TAB(A)
#define ISR_VAL_FILL_42_IN_VECT_TAB(A) A,ISR_VAL_FILL_41_IN_VECT_TAB(A)
#define ISR_VAL_FILL_41_IN_VECT_TAB(A) A,ISR_VAL_FILL_40_IN_VECT_TAB(A)
#define ISR_VAL_FILL_40_IN_VECT_TAB(A) A,ISR_VAL_FILL_39_IN_VECT_TAB(A)
...
#define ISR_VAL_FILL_1_IN_VECT_TAB(A) A
이렇게 쓰는 것이 아니겠는가. 오 마이 갓. 나는 이미 나의 C언어가 체육 선생님께서 가르쳐 주신 것인지 의심하고 있다. 이것은 분명히 수조인데 나는 이런 조작을 전혀 본 적이 없다.
typedef union{
uint32_t reg;
uint8_t buff[4];
}un_test_t;
un_test_t test[] = {
[0].reg = 0,
[0].reg = 1,
52,
};
배열의 마지막
//======================================================================
//STM32
ISR_IN_VECT_TAB(USART1_IRQn),
ISR_IN_VECT_TAB(USART2_IRQn),
ISR_IN_VECT_TAB(TIM3_IRQn),
익숙한 ISR 을 보는 추적 매크로의 정의NAME이야, 이것이 바로 우리가 처음에 본 그 거대한 것 아니야.원래 그 직렬의 인터럽트 서비스 함수는 인터럽트 벡터표에 쓰여 있었다.
#define ISR_IN_VECT_N16_TAB(A) [(A)+16].handler = ISR_NAME(A)
#define ISR_VAL_IN_VECT_N16_TAB(A,B) [(A)+16].handler = B
#define ISR_IN_VECT_TAB(A) ISR_IN_VECT_N16_TAB(A)
#define ISR_VAL_IN_VECT_TAB(A,B) ISR_VAL_IN_VECT_N16_TAB(A,B)
이 신묘한 조작을 보고 나니 내 머리가 멍해졌다.잠시 말이 막혀서, 강요하는 것이 좋을지, 아니면 어리석은 것이 좋을지 모르겠다.
인터럽트 벡터에 대한 재작성은 훌륭하지 않다고 할 수 없다.그러나 이 층층의 매크로 정의, 매크로 연결은 코드를 보는 사람들을 괴롭힌다.코드 안에 도처에 이런 층층이 매크로 정의가 있으니, 시간을 내서 내가 다시 한 편을 공유할게.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
POI Excel 스타일 설정Copyright 2002-2019 Petro-CyberWorks Information Technology Co. Ltd. All rights reserved. PCITC PROPRIETARY/CONFIDENTIAL...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.