2020-04-02 09:55 AM
Hi all,
I'm trying to figure out how to handle an interrupt. In particular I would like to handle an interrupt without using the HAL library.
I want to handle the uart interrupt in reception:
RXNEIE enabled: when the data is received an interrupt occours and RXNE = 1.
If I understand correctly, when an interrupt occurs, instructions are executed in the interrupt vector (NVIC) but I cannot understand how to manage this register.
In detail, how should the code that allows me to check the RXNE bit after the interrupt occur?
2020-04-02 10:07 AM
You did not tell us, which peripheral and which STM32, but maybe this little example ISR (Interrupt Service Routine) in https://community.st.com/s/question/0D50X0000BVpldhSQB/how-to-have-continuous-uart-burst-transmit-while-ensuring-receive-works- will help with understanding.
JW
2020-04-02 10:17 AM
I'm using a STM32F103RB Nucleo and the peripheral is UART2, now i reading your example.
2020-04-02 10:30 AM
@Community member how does "void USART1_IRQHandler(void)" work? What happens at the register level?
2020-04-02 10:39 AM
The processor has a vector table with the address of this function, when the interrupt occurs this function gets called by the processor, and when complete execution resumes where it left off. See stm32f1xx_startup.s
This all seems very basic micro-controller stuff, might I suggest something along the lines of the Joseph Yiu Essential Book on the Cortex-Mx
2020-04-02 11:10 AM
@Community member if it is a function that contains the address of the vector table why is it called USART1_IRQHandler? Is there a vector table only usart1?
2020-04-02 11:17 AM
The vector *table* has multiple entries, one for each interrupt source managed by the NVIC
__Vectors DCD __initial_sp ; Top of Stack
DCD Reset_Handler ; Reset Handler
DCD NMI_Handler ; NMI Handler
DCD HardFault_Handler ; Hard Fault Handler
DCD MemManage_Handler ; MPU Fault Handler
DCD BusFault_Handler ; Bus Fault Handler
DCD UsageFault_Handler ; Usage Fault Handler
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD SVC_Handler ; SVCall Handler
DCD DebugMon_Handler ; Debug Monitor Handler
DCD 0 ; Reserved
DCD PendSV_Handler ; PendSV Handler
DCD SysTick_Handler ; SysTick Handler
; External Interrupts
DCD WWDG_IRQHandler ; Window Watchdog
DCD PVD_IRQHandler ; PVD through EXTI Line detect
DCD TAMPER_IRQHandler ; Tamper
DCD RTC_IRQHandler ; RTC
DCD FLASH_IRQHandler ; Flash
DCD RCC_IRQHandler ; RCC
DCD EXTI0_IRQHandler ; EXTI Line 0
DCD EXTI1_IRQHandler ; EXTI Line 1
DCD EXTI2_IRQHandler ; EXTI Line 2
DCD EXTI3_IRQHandler ; EXTI Line 3
DCD EXTI4_IRQHandler ; EXTI Line 4
DCD DMA1_Channel1_IRQHandler ; DMA1 Channel 1
DCD DMA1_Channel2_IRQHandler ; DMA1 Channel 2
DCD DMA1_Channel3_IRQHandler ; DMA1 Channel 3
DCD DMA1_Channel4_IRQHandler ; DMA1 Channel 4
DCD DMA1_Channel5_IRQHandler ; DMA1 Channel 5
DCD DMA1_Channel6_IRQHandler ; DMA1 Channel 6
DCD DMA1_Channel7_IRQHandler ; DMA1 Channel 7
DCD ADC1_2_IRQHandler ; ADC1_2
DCD USB_HP_CAN1_TX_IRQHandler ; USB High Priority or CAN1 TX
DCD USB_LP_CAN1_RX0_IRQHandler ; USB Low Priority or CAN1 RX0
DCD CAN1_RX1_IRQHandler ; CAN1 RX1
DCD CAN1_SCE_IRQHandler ; CAN1 SCE
DCD EXTI9_5_IRQHandler ; EXTI Line 9..5
DCD TIM1_BRK_IRQHandler ; TIM1 Break
DCD TIM1_UP_IRQHandler ; TIM1 Update
DCD TIM1_TRG_COM_IRQHandler ; TIM1 Trigger and Commutation
DCD TIM1_CC_IRQHandler ; TIM1 Capture Compare
DCD TIM2_IRQHandler ; TIM2
DCD TIM3_IRQHandler ; TIM3
DCD TIM4_IRQHandler ; TIM4
DCD I2C1_EV_IRQHandler ; I2C1 Event
DCD I2C1_ER_IRQHandler ; I2C1 Error
DCD I2C2_EV_IRQHandler ; I2C2 Event
DCD I2C2_ER_IRQHandler ; I2C2 Error
DCD SPI1_IRQHandler ; SPI1
DCD SPI2_IRQHandler ; SPI2
DCD USART1_IRQHandler ; USART1
DCD USART2_IRQHandler ; USART2
DCD USART3_IRQHandler ; USART3
DCD EXTI15_10_IRQHandler ; EXTI Line 15..10
DCD RTC_Alarm_IRQHandler ; RTC Alarm through EXTI Line
DCD USBWakeUp_IRQHandler ; USB Wakeup from suspend
__Vectors_End
2020-04-02 11:21 AM
Look at your toolchain. You have somewhere a file like this https://github.com/STMicroelectronics/STM32CubeF1/blob/master/Drivers/CMSIS/Device/ST/STM32F1xx/Source/Templates/gcc/startup_stm32f103xb.s , and the toolchain is set up so that it compiles it and links to your project. IDEs tend to hide this detail into some "magic" they perform, but if you look closer, you'll find it. You don't need to do anything with this file, but that's where the interrupt vector table is, under g_pfnVectors . (There are also prototype ISRs there, doing nothing and tagged "weak"; you override any of them by writing a "true" ISR in your code).
The ordering in that table is not random, it's given by hardware, read the Interrupts chapter in RM0008.\
For the interrupt to be called, you need not only to enable it in the peripheral (here by setting the RXNEIE bit in USART), but also in the NVIC module; you do that by calling
NVIC_EnableIRQ(USART1_IRQn);
(that's a nothing else just a write to a bitfield in one of the NVIC registers, too, but it's not worth going to the details for now, just use it as it is).
The example I gave is for 'F0 and the USART there is slightly different than the one in 'F1 (the overrun interrupt is cleared somewhat differently, by reading the data register), so you can't use it as it is now - read the USART chapter in RM0008 for the details.
JW
2020-04-02 01:10 PM
Maybe this is of help.
https://github.com/turboscrew/blue_pill_init
Search for "init_usart1".
There the USART is used in a "terminal" way - no predefined messages (message lengths).
I did use stdint.h, though, but that's the only file not written by me.
Everything (except vectors in start.S) are in one file. Terrible for a program structure, but convenient for searching without downloading.
Oh, and in Cortex-M series, the interrupts work in a half-different way from any other architectures. In Cortex-A series the interrupts work in a totally different way from any other architectures. I highly recommend checking out ARM ARM (the ARM Architecture Reference Manual for yout chip - probably ARMv7-M.