cancel
Showing results for 
Search instead for 
Did you mean: 

Need help to understand relationship of USART1 (as a source of interrupts), EXTI (as an enabler of external interrupts), and NVIC. USART1 RXNE=1 with RXNEIE=1 does not cause interrupt.

wb0gaz
Senior

(BACKGROUND) I'm working on small (GCC/C-language) tests of STM32F051 with STM32CubeIde 1.8.0 on STM32F051 target. These tests are being done ---> without HAL, Lower Level drivers, but am using #include "cmsis_gcc.h" to access CPU interrupt enable/disable/status <---, so your patience is appreciated (that is, I don't intend in these tests to involve HAL or Lower Level drivers). RM0091 is my documentation resource.

(PROBLEM) USART1 is configured to cause interrupt (RXNEIE=1) when RXNE=1 (receive character). Settings verified (RXNE becomes 1 when a receive character is accepted, and RXNEIE is 1.) The expected entry to void USART1_IRQHandler(void) is not happening.

(QUESTIONS)

1. Section 11.2.5: "EXTI line 25 is connected to the internal USART1 wakeup event". Is this used to allow USART1 interrupt request to reach the CPU? I am not using sleep or wake up conditions (the CPU is always running.) In this case is "event" same as "interrupt"?

2. RM0091 section 11.2.4 includes an instruction I do not understand: "• Configure the enable and mask bits that control the NVIC IRQ channel mapped to the EXTI so that an interrupt coming from one of the EXTI line can be correctly acknowledged." From what I see in the various examples at the end of RM0091 (however, not in the USART examples in section A.19.12), two important steps are:

NVIC_EnableIRQ();

NVIC_SetPriority();

I do not see any definition of NVIC registers in RM0091. cmsis_gcc.h contains nothing referring to NVIC. I have no other libraries or include files referenced at this point. Is NVIC something I can manipulate with registers like other peripherals?

I believe __enable_irq() is working: __get_PRIMASK() result follows the expected result based on preceding __disable_irq() or __enable_irq().

Thank you for any suggestions, questions or requests for clarifying information.

13 REPLIES 13

Yes, but you want to include it in every .c - especially the one where main() sits (main.c?) - don't you?

JW

wb0gaz
Senior

Thank you JW and TDK, this is helpful and important for my early-stage learning curve! Sorry delay in my reply --- I had some other tasks requiring attention.

Creating new stm32cubemx application with LL option selected instead of HAL still creates some initialization (and maybe run-time functions like system tick timer), however, the code all seems to be clearly visible, and so far I found that simply ignoring the provided code by making it unreachable (but keeping the include paths and available files) seems to provide exactly what I wanted in the first place (where entry point is main() and nothing has been done to the CPU before that point, but the special functions for ARM core remain accessible.)

I have not yet verified USART interrupt (which was the original task) functions, however, NVIC_EnableIRQ(USART1_IRQn) now compiles without error and __disable_irq and __enable_irq both compile and work (along with __get_PRIMASK()) - those were my root cause problem, not USART specific ISR.

Detail debugging of individual device interrupt should not be big problem once fundamental concepts of interaction with STM32 peripherals and ARM core are understood (which I did not understand at all before.)

Thank you again, I will report back when I have success (or failure) of initial serviced interrupt.

Dave

Pavel A.
Evangelist III

The chain of headers is this, if I understand correctly:

  • Every HAL component header (stm32NN_hal_xxxx.h) includes stm32NNxx.h which is in .../Drivers/CMSIS/Device/ST/STM32NNxx
  • The stm32NNxx.h defines some obligatory CMSIS junk and then includes one of more specific stm32NNMMxx.h - based on symbol STM32NNMMx defined in the project. If no such symbol is defined, compilation error occurs.
  • These specific stm32NNMMxx.h headers are in .../CMSIS/Device/ST/STM32NNxx/Include ; these can be included directly into user code.
  • Each stm32NNMMxx.h then includes core_cmX.h which is ARM-provided header for cortex-M family. They are in .../Drivers/CMSIS/Include. For STM32F0 it is core_cm0plus.h.
  • These core_cmX.h files contain all the CMSIS defined macros for every supported compiler (by inclusion of cmsis_gcc.h, cmsis_armcc.h and so on). This is how we get __enable_irq, __disable_irq, __get_PRIMASK, NVIC, SysTick and so on.

The Cube generator adds include paths to .../Drivers/CMSIS/Device/ST/STM32NNxx/Include and .../Drivers/CMSIS/Include

Another include chain for HAL users begins from stm32NN_hal_def.h - it includes stm32NNxx.h and so on.

For dual core chips such as H7, stm32H7xx.h includes either CM7 or CM4 header, based on CORE_CM7 or CORE_CM4 defined in the project.

-- pa

wb0gaz
Senior

Pavel A - this is **REALLY** helpful!

I was already wondering how I could organize a set of header files so I could make my application work "portable" (to other tool chain). I do not object to STMCube32IDE, however, my application will need portability to some completely different MCU families (outside of STM32 or ARM); in this case I need to have .h file set I can "take with me" for each target (because in the end, the application source files will be subject to different tool chains.)

In my prior work, there is always only one .h file for whole MCU part number, so tree structure and dependencies left me wondering how I could identify the correct files and the hierarchy of files to support a given MCU type.

Thank you again for the guided tour, it is very good for helping my understanding!

Dave