cancel
Showing results for 
Search instead for 
Did you mean: 

Strange interrupt handler problem on STM32H7

Pavel A.
Evangelist III

Another day, another bug....

I'm trying to use ADC3 with BDMA on H753.

Started from some cube-generated code that assigned BDMA channel 0 to ADC3.

Allocated memory in SRAM4. Added interrupt handler for BDMA_Channel0 and ADC3.

When I start the ADC3, I hit the default interrupt handler - as if the proper handler is not defined.

ICSR = 0x891 this means the active interrupt is 0x91.

0x91 - 16 = 129 which is exactly BDMA_Channel0_IRQn.

And there's the handler for it. But this handler is not hit. Why??

DMA_HandleTypeDef hdma_adc3;
ADC_HandleTypeDef hadc3;
 
void ADC3_IRQHandler(void)
{
    HAL_ADC_IRQHandler(&hadc3);
}
 
void BDMA_Channel0_IRQHandler(void)
{
    HAL_DMA_IRQHandler(&hdma_adc3);
}

I've checked the listing and the vector table, the vector indeed points to my BDMA_Channel0_IRQHandler.

VTOR looks correct (systick works, and the default handler is there as well).

Same behavior when the code is in internal flash or AXI RAM. Caches NOT enabled.

So how comes that the default handler is called?

Is there an example of ADC3 in DMA mode (BDMA) for STM32H7x3?

1 ACCEPTED SOLUTION

Accepted Solutions

> Have not increased the table alignment yet.

Do it.

Apparently, NVIC is not *adding*, but *ORing* the ISR's offset (ISR number << 2) to VTOR.

JW

View solution in original post

9 REPLIES 9

> I've checked the listing and the vector table, the vector indeed points to my

BDMA_Channel0_IRQHandler.

Show.

JW

TDK
Guru

Verify entry in vector table points to a different location than the default handler.

If you're using C++, make sure the handler is declared as extern "C".

If you have LTO enabled, disable it.

If you feel a post has answered your question, please click "Accept as Solution".
Pavel A.
Evangelist III

@Community member​ 

I've added some prints below.

Output:

VTOR=80E0200

intnum= 129 vec=80EA575, handler=0x80ea575

void Test_ADC3()
{
    printf("VTOR=%X\n", SCB->VTOR);
    printf("intnum= %u vec=%X, handler=%p\n", BDMA_Channel0_IRQn,
           ((uint32_t*)SCB->VTOR)[BDMA_Channel0_IRQn + 16],
           (void*)BDMA_Channel0_IRQHandler );
 
...............
        unsigned memsize = hadc3.Init.NbrOfConversion * sizeof(uint16_t);
        f_adc_cnvrt_complete = 0;
        HAL_StatusTypeDef st = HAL_ADC_Start_DMA(&hadc3, (void*)ADC3_BUF_BASE_, memsize);
        if (0 != st ) {
            __BKPT(14);
        }
  .............
}
 

0693W00000JPKIVQA5.pngHere it lands on the default handler, R1= 0x891

And snippet from the .list file

080ea574 <BDMA_Channel0_IRQHandler>:
{
 80ea574:	b508      	push	{r3, lr}
    HAL_DMA_IRQHandler(&hdma_adc3);
 80ea576:	4802      	ldr	r0, [pc, #8]	; (80ea580 <BDMA_Channel0_IRQHandler+0xc>)
 80ea578:	f7fe fae2 	bl	80e8b40 <HAL_DMA_IRQHandler>
}
 80ea57c:	bd08      	pop	{r3, pc}
 80ea57e:	bf00      	nop
 80ea580:	240002cc 	.word	0x240002cc

Try to generate *separate* handlers for every item in the table.

Also, try to align table to higher power of 2 (yes I know PM0253 requires only bits 0..8 to be zero, try more).

JW

@Community member​ Jan, with separate handlers I get a weird result .. simply cannot believe my eyes.

This appears to be vector #1 (so I've mis-interpreted the ICSR; no need to subtract 16, the low bits of 0x91 b'10001 mean 17 ?)

Vector 1 is PVD_AVD_IRQn - interrupt from programmable voltage detector or analog voltage detector (RM0433, 5.5.3-5.5.4).

The RM says the interrupt must be enabled in EXTI and AVD/PVD must be enabled in PWR_CR1. When the interrupt is hit RWR_CR1 = 0xF000C100 so bits AVDEN and PVDE are both 0. (RM0433, 5.8.1)

I'm still checking if there is some error in my setup.

Have not increased the table alignment yet.

The interrupt remains active, I don't know how to block it. NVIC_DisableIRQ(PVD_AVD_IRQn) does not help.

Regards,

P.

> Have not increased the table alignment yet.

Do it.

Apparently, NVIC is not *adding*, but *ORing* the ISR's offset (ISR number << 2) to VTOR.

JW

Piranha
Chief II

> VTOR=80E0200

The alignment is not correct for this device. PM0253 section "2.4.4 Vector table":

The silicon vendor must configure the top range value, which is dependent on the number of interrupts implemented. The minimum alignment is 32 words, enough for up to 16 interrupts. For more interrupts, adjust the alignment by rounding up to the next power of two. For example, if the user requires 21 interrupts, the alignment must be on a 64-word boundary because the required table size is 37 words, and the next power of two is 64, see Vector table offset register on page 197.

According to RM0433 section "19.1.2 Interrupt and exception vectors" this device has 150 interrupts. Therefore the size of vector table is 16+150=166 words. The next power of two is 256 and therefore the VTOR for this device must be aligned to 1024 bytes.

In this case the closest correct addresses are 0x080E0000 and 0x080E0400.

The 0x91 is 0b1001'0001, which after multiplication by 4 (left shift by 2) becomes 0b10'0100'0100. Now, because the current VTOR address ends with 0b10'0000'0000, after OR operation the bit #9 is effectively ignored. That means the device actually fetches an address, for which the offset is lowered by 2^9=512 bytes or 128 words. That's why instead of fetching a vector 145 (0x91) it fetches 145-128=17, which translates (by subtracting 16) to 129-128=1 for interrupt numbers.

Pavel A.
Evangelist III

@Community member​ @Piranha​ Thank you so much. The PM says bits 0-8 so I thought 0x200 alignment is enough.

Jan's reply is earlier so he takes the best answer.