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에 따라 라이센스가 부여됩니다.